503 Service Unavailable Error: Causes and How to Fix It
A 503 means the server itself is fine, but whatever is supposed to answer your request - PHP, a backend process, or the web server's worker pool - isn't. It's a traffic-jam error, not a code error, and that distinction changes how you fix it.
What a 503 actually means
Unlike a 500 (something crashed while running your code) or a 508 (CloudLinux capped your account), a 503 means the web server received the request but couldn't hand it off to anything that could process it. Nginx or Apache is up. The thing behind it - PHP-FPM, a proxied app, or a rate limiter - isn't answering in time.
You'll usually see one of these on the page itself:
503 Service Unavailable- plain Apache/Nginx default pageService Temporarily Unavailablewith no branding- A Cloudflare-branded 503 (different cause - see below)
- Site loads for a few seconds then drops mid-session under load
503 vs the errors it gets confused with
| Error | What it really means |
|---|---|
| 500 | Your code (PHP, .htaccess) threw an error |
| 502 | Backend sent back a garbled/invalid response |
| 503 | No backend worker was available to respond at all |
| 508 | CloudLinux LVE hit a hard resource cap (shared hosting) |
Cause 1: PHP-FPM ran out of workers
This is the most common cause on WordPress and WooCommerce sites. PHP-FPM has a fixed pool of worker processes (pm.max_children). If every worker is busy - a traffic spike, a slow plugin, a stuck cron job - new requests queue up and eventually time out with a 503.
Check the PHP-FPM error log, usually at:
/var/log/php-fpm/www-error.log
# or, on cPanel with PHP-FPM per-account:
/home/username/logs/domain.com.error.logLook for a line like:
WARNING: [pool www] server reached pm.max_children (10), consider raising itThat confirms it. Your pool is undersized for the traffic it's getting.
Cause 2: Apache/Nginx worker or connection limits
Even if PHP is fine, the web server itself has a cap on simultaneous connections (MaxRequestWorkers in Apache, worker_connections in Nginx). Hit that ceiling during a traffic spike - a sale, a viral post, a bot crawl - and new visitors get a 503 while existing ones keep working.
Cause 3: A plugin or cron job locked up the database
A backup plugin, a bulk import, or a runaway WP-Cron job can hold a MySQL table lock long enough that every other PHP process queues behind it, exhausts the FPM pool, and you get a 503 that looks like a server problem but is really one plugin.
Quick check via SSH or cPanel Terminal:
mysqladmin processlist -u root -p | grep -i lockIf you see the same query sitting in "Locked" state for more than a few seconds, that's your culprit.
Cause 4: Cloudflare is returning the 503, not your origin
If you're behind Cloudflare and see a Cloudflare-branded 503 (with a Ray ID at the bottom), the cause is different - it usually means Cloudflare's own edge is rate-limiting or health-checking your origin and decided not to forward the request. Check Cloudflare dashboard → Analytics → Traffic for a spike, and confirm your origin server itself is actually reachable and not the one timing out (that would show as 521/522 instead).
Cause 5: Maintenance mode or a deploy script mid-run
Some deployment tools and a few caching/security plugins deliberately return a 503 with a Retry-After header while they update in the background. Check response headers to rule this out before you go hunting for a real fault:
curl -I https://yourdomain.comIf you see Retry-After: 30 or similar, this is expected behavior, not a bug - just wait it out.
The fix, in order
- Confirm it's not Cloudflare. Temporarily set the DNS record to "DNS only" (grey cloud) in Cloudflare and reload. If the 503 disappears, the issue is between Cloudflare and your origin, not your server.
- Check PHP-FPM's pool status. In cPanel, go to MultiPHP Manager → PHP-FPM for the domain and raise
Max Childrena reasonable amount (don't jump blindly to 100 - calculate from available RAM ÷ average PHP process size, roughly 40-60MB per worker on WordPress). - Restart PHP-FPM and the web server to clear any stuck workers:
systemctl restart php-fpm systemctl restart httpd # or nginx - Disable plugins one by one if the FPM log shows the pool maxing out during specific actions (backups, imports). Backup and SEO plugins are the usual suspects.
- Check for a stuck cron job and kill it if one query has been running for an unreasonable amount of time:
mysqladmin processlist -u root -p mysqladmin kill-u root -p
Prevention
- Size PHP-FPM's
pm.max_childrento your actual RAM, and revisit it after every traffic milestone, not just once at setup. - Move heavy backup/import jobs to off-peak hours via cron instead of running them live during business hours.
- Put a real caching layer (page cache + object cache) in front of PHP so most requests never touch a worker at all.
- If you're consistently hitting FPM limits on shared hosting, that's usually a sign you've outgrown the plan - a VPS with dedicated resources removes the shared-pool ceiling entirely.
- Set up basic uptime monitoring so a 503 alerts you within minutes instead of you finding out from a customer complaint.
Most 503s trace back to one overloaded resource - PHP workers, database locks, or Apache connections - not a broken server. Find which one maxed out, fix that specific limit, and put monitoring in place so the next spike doesn't catch you off guard.
Frequently asked questions
Is a 503 error the same as my site being down?
Not exactly. Your server is up and responding - it's just telling visitors it can't process the request right now. It's usually temporary and tied to a resource limit, not a crash.
Why do I only see 503 errors during traffic spikes?
Because the error is almost always a capacity problem. PHP-FPM or Apache has a fixed number of workers, and once every one is busy, new visitors get queued and then timed out with a 503.
Does raising PHP-FPM's max_children always fix it?
It helps if you genuinely have spare RAM, but raising it blindly can backfire - too many workers competing for limited memory causes swapping, which makes things slower, not faster. Calculate the number from available RAM first.
Why does my 503 show a Cloudflare error page instead of my site's?
That means Cloudflare's edge returned the 503, not your origin server. It usually points to rate limiting or a failed health check at Cloudflare's layer - check Cloudflare's analytics before touching your server.
Can a single plugin really cause a site-wide 503?
Yes. Backup, import, and some security plugins can hold database locks or spin up long-running processes that eat every available PHP worker, which then blocks every other visitor's request too.