Debugging a 150k-Request 404 Storm: How I Saved My WordPress Server from High Load
Have you ever looked at your server’s top and seen mysqld and php-fpm battling for 40% of your CPU, even though your traffic shouldn’t be that high?
That was exactly the situation I found myself in this week on my Ubuntu server. Here’s the story of how a small missing CSS file turned into a massive performance nightmare—and how I fixed it.
🕵️ The Investigation: Following the CPU Spikes
It started with a slow-loading site. A quick check of the process list revealed multiple php-fpm processes consuming 12-15% CPU each, while MySQL was hovering around 36%.
Step 1: Identify the Culprit Site
Using the command line, I audited the active processes and log sizes:
ps -eo user,pcpu,pmem,comm --sort=-pcpu | head -n 10
One site stood out: culprit.vengalavinay.com. It was breathing heavy.
Step 2: The “Smoking Gun” in the Logs
I dove into the Apache access logs for that specific site. What I found was shocking:
sudo grep " 404 " /var/log/apache2/culprit.vengalavinay.com_access.log | awk '{print $7}' | sort | uniq -c | sort -nr | head -n 5
Results:
- 151,966 requests for
/wp-content/themes/jobaway/assets/css/flaticon-one.css - 722 requests for
/wp-content/themes/jobaway/assets/css/icomoon.css
That’s over 150,000 requests in just 5 minutes from the server’s own internal IP!
💡 The Problem: Why 404s via PHP are “Expensive”
In a standard WordPress setup, when a static file (like a .css or .png) is missing, Apache doesn’t just say 404. Instead, it hands the request off to index.php. This means every time that missing CSS file was requested:
- PHP-FPM was invoked.
- MySQL was queried to check for slugs/redirects.
- WordPress Internal Logic ran just to tell the user “File Not Found.”
Multiply that by 150,000 requests, and you have a recipe for server exhaustion.
🛠️ The Solution: From Mitigation to Optimization
1. The Quick Fix (The “Dummy File” Trick)
To stop the expensive PHP execution immediately, I created an empty, zero-byte file at the expected paths:
sudo touch /home/culpritvengala/public_html/wp-content/themes/jobaway/assets/css/flaticon-one.css
sudo touch /home/culpritvengala/public_html/wp-content/themes/jobaway/assets/css/icomoon.css
Suddenly, those 150,000 requests became cheap static asset calls. CPU usage for PHP dropped from 12% to under 1% instantly.
2. Tuning for the Future (LCP Optimization)
To ensure the site doesn’t just survive but thrives, I implemented three core performance upgrades:
- HTTP/2 Multiplexing: Switched to the
h2protocol to allow simultaneous asset downloads. - Aggressive Browser Caching: Used
mod_expiresto cache images, fonts, and scripts for 1 year. - PHP Opcache Tuning: Increased Opcache memory to 256MB for higher throughput.
📊 The Results: A Healthier Server
| Metric | Before | After |
|---|---|---|
| PHP CPU Usage | ~12.5% per process | < 1% |
| MySQL CPU Load | ~36% | ~33% (Stabilizing) |
| Asset Delivery | HTTP/1.1 (Sequential) | HTTP/2 (Parallel) |
Scaling isn’t always about bigger servers—sometimes, it’s just about finding that one missing file.