Apache 503 Errors
Apache returns a 503 Service Unavailable error when it cannot process a request, typically because it has run out of worker threads or a backend it is proxying to is unreachable. Unlike a 502 (which is always a backend communication error), a 503 can originate from Apache itself when it is overloaded. Understanding whether Apache is generating the 503 directly or forwarding it from a backend determines the right fix.
503 vs 502: what is the difference?
| Error | Generated by | Meaning |
|---|---|---|
| 502 Bad Gateway | Proxy (nginx/Apache) | Backend sent invalid/no response |
| 503 Service Unavailable | Apache itself or backend | Server too busy, maintenance, or backend down |
Diagnosing 503 errors
# Check Apache error log immediately:
sudo tail -100 /var/log/apache2/error.log
Apache error log showing 503 cause
[Mon Jun 09 14:35:22.123456 2025] [proxy:error] [pid 1234] (111)Connection refused:
AH00957: HTTP: attempt to connect to 127.0.0.1:9000 (localhost) failed
[Mon Jun 09 14:35:22.456789 2025] [proxy_http:error] [pid 1234]
AH01114: HTTP: failed to make connection to backend: localhost
# "Connection refused" to port 9000 = PHP-FPM not running on that port
# Check Apache server status (enables the mod_status page):
# If not enabled: sudo a2enmod status && sudo systemctl reload apache2
curl http://127.0.0.1/server-status?auto
Apache server-status output
Total Accesses: 1234567
Total kBytes: 9876543
BusyWorkers: 150 ← All workers busy (MaxRequestWorkers hit)
IdleWorkers: 0
Scoreboard: WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
# W = Working. IdleWorkers: 0 with all W means 503 coming soon
Worker thread exhaustion
# Apache MPM configuration determines max workers:
# Check which MPM is active:
apache2ctl -M | grep mpm
# For mpm_prefork (common with PHP mod_php):
sudo nano /etc/apache2/mods-enabled/mpm_prefork.conf
/etc/apache2/mods-enabled/mpm_prefork.conf
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150 # Max simultaneous connections
MaxConnectionsPerChild 0 # Recycle workers after N requests (0=never)
# MaxRequestWorkers = ServerLimit in older Apache
# Calculate: MaxRequestWorkers = Available RAM / Apache process size
# Check process size: ps aux | grep apache2 | awk '{print $6/1024 "MB"}' | sort -rn | head -5
# For mpm_event (better performance, default in newer Apache):
sudo nano /etc/apache2/mods-enabled/mpm_event.conf
# Increase MaxRequestWorkers and ThreadsPerChild
# mpm_event uses threads, not processes → can handle more connections per RAM
# Apply changes:
sudo apachectl configtest # Validate config first
sudo systemctl reload apache2
Backend unavailable in reverse proxy
# Apache proxying to a backend that is down:
# Check if backend is listening:
sudo netstat -tlnp | grep :8080 # Is the app listening on port 8080?
curl http://127.0.0.1:8080/health # Can Apache reach it?
# If backend is down, start it:
sudo systemctl start myapp
sudo systemctl status myapp
# Apache maintenance mode (return 503 intentionally during deploys):
sudo a2enmod rewrite
# Add to VirtualHost:
# RewriteEngine On
# RewriteCond %{DOCUMENT_ROOT}/maintenance.flag -f
# RewriteRule ^(.*)$ /maintenance.html [L]
# ErrorDocument 503 /maintenance.html
# Enable maintenance:
sudo touch /var/www/html/maintenance.flag
# Disable:
sudo rm /var/www/html/maintenance.flag
Conclusion
Check Apache's /server-status page when investigating 503 errors — BusyWorkers at max with IdleWorkers: 0 confirms worker exhaustion. The fix is either increasing MaxRequestWorkers (if RAM allows), reducing response time of slow requests (if they are tying up workers), or switching from mpm_prefork to mpm_event for better connection handling under load. Enable mod_status permanently for monitoring; it provides real-time insight into Apache's workload that is unavailable from logs alone.
Need help with Ubuntu administration?
Work directly with Muhammad Irfan Aslam for Ubuntu Server, Linux, cloud, Docker, DevOps, CI/CD, or infrastructure troubleshooting support.
Work with Muhammad Irfan Aslam