A 503 Service Unavailable error means the web server is temporarily unable to handle requests. This guide covers every cause — from server overload to maintenance mode — and provides targeted fixes for Nginx, Apache, and application servers.
| Cause | Typical symptom | Fix |
|---|---|---|
| Server overload (CPU/RAM exhausted) | Affects all visitors simultaneously | Scale up or optimize resource usage |
| Too many concurrent connections | Intermittent during traffic spikes | Increase worker limits or add load balancing |
| Maintenance mode enabled | Intentional, all visitors affected | Disable maintenance mode when done |
| Rate limiting triggered | Affects specific IPs or users | Adjust rate limit thresholds |
| Application crash with no auto-restart | Persistent until manually fixed | Restart app service, fix crash cause |
| Database connection pool exhausted | Affects all database-dependent pages | Increase pool size or optimize queries |
# Check server load average (should be below number of CPU cores)
uptime
# Check memory usage
free -h
# Check top processes consuming resources
top -b -n 1 | head -20
# Check Nginx / Apache status
sudo systemctl status nginx
sudo systemctl status apache2
# Check recent error logs
sudo tail -50 /var/log/nginx/error.log
sudo tail -50 /var/log/apache2/error.logWhen the server's CPU or RAM is exhausted, it cannot process new requests and returns 503. Identify the resource bottleneck first:
# Check CPU and memory in real time
htop
# Find processes using the most memory
ps aux --sort=-%mem | head -10
# Find processes using the most CPU
ps aux --sort=-%cpu | head -10
# Check if OOM killer has been active
sudo dmesg | grep -i "oom|killed" | tail -20Nginx has limits on concurrent connections. When all workers are busy, new requests receive a 503. Check and increase worker limits:
# Increase worker processes (set to number of CPU cores)
worker_processes auto;
events {
# Increase max connections per worker
worker_connections 2048;
use epoll;
multi_accept on;
}
http {
# Increase keepalive connections
keepalive_timeout 65;
keepalive_requests 100;
}sudo nginx -t && sudo systemctl reload nginx<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>sudo apache2ctl configtest && sudo systemctl reload apache2apache2ctl status to see current worker usage. If MaxRequestWorkers is frequently reached, increase it — but ensure the server has enough RAM to support additional workers.Rate limiting is intentional — it protects the server from abuse. If legitimate users are being rate-limited, adjust the thresholds:
# In nginx.conf http block:
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
# In server/location block:
limit_req zone=api burst=10 nodelay;
limit_req_status 503;$http_x_forwarded_for or $realip_remote_addr), not the CDN's IP address.If you intentionally put your site in maintenance mode, ensure you return a proper 503 response (not 200) so search engines know it is temporary:
# Create a maintenance page
echo '<!DOCTYPE html><html><body><h1>Maintenance in progress</h1></body></html>' | sudo tee /var/www/html/maintenance.html
# In your Nginx server block:
location / {
if (-f /var/www/html/maintenance.html) {
return 503;
}
}
error_page 503 /maintenance.html;
location = /maintenance.html {
root /var/www/html;
internal;
add_header Retry-After 3600;
}When returning a 503, always include a Retry-After header. This tells search engine crawlers when to retry, preventing them from treating the outage as permanent and de-indexing your pages.
# In your error_page 503 location block:
add_header Retry-After 3600; # Retry in 1 hour (seconds)# In .htaccess or virtual host config:
Header always set Retry-After "3600"Alive24x7 monitors your website every minute from multiple global locations. When a 503 error is detected, you receive an instant alert — via email, SMS, or Slack — so you can act before the outage impacts your business.
Start Free Monitoring