Introduction
During my summer internship I was tasked with building an accounting and inventory management system for a small business in Tanzania. The system was primarily written in PHP and MySQL. For rapid development I leaned heavily on the XAMPP stack, which provides an easy local server environment for PHP projects. XAMPP is convenient for beginners and quick prototypes, but as the project grew I started hitting some walls that made me rethink how suitable it was for anything beyond small internal tools.
In this post I want to detail the specific issues I faced, the lessons learned, and the measures I eventually put in place to keep the project stable. Hopefully these experiences help someone else who might be considering using XAMPP for more than light experimentation.
Internship Project
The core goal of the internship was to create a unified system where inventory transactions and accounting entries were linked. We wanted the sales team to record invoices while the finance team could view journal entries generated from the same data. Everything had to run on a shoestring budget, so the initial choice was to build the app in PHP and host it locally with XAMPP.
Because it was a summer internship I did not have months to experiment with infrastructure. XAMPP was attractive because I could get Apache and MySQL running in minutes on any Windows machine. I could write the PHP pages, test them locally, and move on to the next feature. For the first couple weeks development was smooth and nothing felt out of place.
Why XAMPP
XAMPP bundles Apache, MySQL, PHP, and other common tools into a single click-to-run package. On Windows it sets up all the necessary services so you can start coding right away. For a small team with limited sysadmin knowledge, this is compelling. The installer even includes phpMyAdmin for quick database management. My mentors were already familiar with the stack, so the decision was largely influenced by convenience.
However, convenience often hides deeper issues. XAMPP is primarily targeted at local development. It lacks built‑in mechanisms for scaling or for handling high‑reliability workloads. In a controlled environment with only a few users this is rarely a problem, but the inventory system grew to the point where multiple employees were using it simultaneously. Soon the cracks began to show.
Limitations of XAMPP
The first limitation was performance. The MySQL version bundled with XAMPP lagged behind the one in standard repositories. Query optimizations available in newer releases simply weren’t there. While debugging slow reports I discovered that a few heavy joins were overwhelming the database service. Because updating MySQL within XAMPP is not straightforward, I had to manually install a newer version alongside it just to test improvements.
Another limitation is that XAMPP is not hardened for security by default. Passwords are left empty, configuration files are accessible, and there is no built‑in firewall configuration. In a production setting this opens the door to data leaks. We mitigated some of this by locking the local network, but it underscored how XAMPP wasn’t meant for anything more than quick demos.
Perhaps the biggest drawback is the way XAMPP handles MySQL data directories. When the power went out unexpectedly one afternoon, MySQL refused to start and reported corruption in a few tables. We soon discovered that the InnoDB .ibd files were partially written when the crash occurred. The automatic recovery process wasn’t always reliable.
Handling Data Corruption
The corrupted tables were a wake-up call. Important records simply would not load. The error logs pointed to mismatched transaction IDs within the InnoDB engine. After some research I learned that XAMPP’s MySQL build ships with crash recovery turned on, but if the binary log gets out of sync the server can still refuse to start. This happened twice in the span of a month.
Initially I thought we had lost all customer invoices from those days. Thankfully I had nightly exports generated by a simple PHP script, but manually restoring them was tedious and left small gaps. I realized that relying solely on XAMPP’s built-in mechanisms was a mistake. We needed a more resilient backup plan and a method to recover data if corruption struck again.
Recovering IBD Files
Digging into MySQL internals revealed that the .ibd files still contained our data even when the server refused to import them. The trick that finally worked was to copy the entire mysql
directory from a recent backup, start the server, and then replace only the corrupted database folder with the newer files. Because the rest of the system files were from an older snapshot, MySQL believed it was upgrading from a previous state and accepted the tables.
This process felt dangerous at first, but it recovered every row. The key was maintaining a rolling archive of the entire mysql
folder so there was always a known-good version to pair with the latest data. Once the server started, I exported the tables properly and reimported them into a fresh instance just to be safe.
# start server with backup system files
net stop mysql
xcopy C:\backup\mysql C:\xampp\mysql /E /I
net start mysql
# replace corrupted db with newer files
xcopy C:\latest_data\inventory C:\xampp\mysql\data\inventory /E /I
During the first incident I spent hours combing through the logs. MySQL kept printing "InnoDB: Page checksum mismatch" errors. I tried different innodb_force_recovery
levels with no success. Comparing file sizes with backups finally revealed that several tables were truncated. That clue pushed me toward a more careful restore process instead of random fixes.
I even experimented with mysqlfrm
and mysqlbinlog
to rebuild lost schema and transactions. These tools were helpful for small tables but didn’t scale well, which taught me how critical consistent binary logs are for recovery.
Backup Strategy
After those scares I automated the backup process. A scheduled task runs every night, dumping each database with mysqldump
and copying the entire mysql
directory to an external drive. Once a week the script also syncs the archive to a cloud bucket using rclone
. This might seem excessive for a small project, but having multiple restore points meant I could experiment without fear of losing everything.
One lesson I learned is to always test your backups. I wrote a small verification script that spins up a temporary MySQL instance, restores the latest dump, and checks that the record counts match the production database. It only takes a few minutes to run but gives immense peace of mind.
Over time the routine evolved into a two-tier system. Daily dumps acted as checkpoints while a weekly copy of the entire mysql
directory preserved the engine files exactly as MySQL expected. With both available I could spin up a replica in minutes by copying a folder and running a few commands.
Moving Beyond XAMPP
As my internship progresses, I am gaining a much deeper appreciation for proper server setups. XAMPP served us well in the early stages, but the constant manual maintenance is convincing me to migrate the project to a standard LAMP stack on Ubuntu. The performance gains alone are worth it, and configuration management becomes far simpler with package managers and system services.
Transitioning away from XAMPP also forced me to learn about permissions, firewall rules, and scheduled jobs—skills that are crucial for any real-world deployment. While XAMPP will always have a place for quick demos, I would hesitate to rely on it for a business-critical application again.
The move to Ubuntu also let me automate deployments using shell scripts and systemd services. Instead of clicking buttons in the XAMPP control panel, I could use git pull
and restart the app via systemctl
. That alone saved a surprising amount of time.
Conclusion
Using XAMPP taught me a great deal about the importance of backups and understanding the underlying database engine. Data corruption can happen suddenly, and without a clear recovery plan you risk losing weeks of work. I was fortunate that my nightly scripts and some experimentation with IBD files saved the project.
If you plan to deploy a PHP application beyond local testing, I strongly recommend setting up a proper production environment or at least hardening your XAMPP installation. Regular backups, strict permissions, and keeping your database engine up to date will save you many headaches down the road.