503 Service Unavailable: What It Means and How to Fix It

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.

Common Causes of 503 Errors

CauseTypical symptomFix
Server overload (CPU/RAM exhausted)Affects all visitors simultaneouslyScale up or optimize resource usage
Too many concurrent connectionsIntermittent during traffic spikesIncrease worker limits or add load balancing
Maintenance mode enabledIntentional, all visitors affectedDisable maintenance mode when done
Rate limiting triggeredAffects specific IPs or usersAdjust rate limit thresholds
Application crash with no auto-restartPersistent until manually fixedRestart app service, fix crash cause
Database connection pool exhaustedAffects all database-dependent pagesIncrease pool size or optimize queries

Quick Diagnosis

Terminal — check server load and services
# 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.log

Fix: Server Overload

When the server's CPU or RAM is exhausted, it cannot process new requests and returns 503. Identify the resource bottleneck first:

Terminal
# 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 -20
If the OOM (Out of Memory) killer has terminated processes, your server does not have enough RAM for the current load. You need to either add more RAM, reduce memory usage, or add horizontal scaling.

Fix: Nginx Worker Exhaustion

Nginx has limits on concurrent connections. When all workers are busy, new requests receive a 503. Check and increase worker limits:

/etc/nginx/nginx.conf
# 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;
}
Terminal — apply changes
sudo nginx -t && sudo systemctl reload nginx

Fix: Apache Worker Exhaustion

/etc/apache2/mods-enabled/mpm_prefork.conf
<IfModule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxRequestWorkers   150
    MaxConnectionsPerChild 0
</IfModule>
Terminal — apply changes
sudo apache2ctl configtest && sudo systemctl reload apache2
Use apache2ctl status to see current worker usage. If MaxRequestWorkers is frequently reached, increase it — but ensure the server has enough RAM to support additional workers.

Fix: Rate Limiting

Rate limiting is intentional — it protects the server from abuse. If legitimate users are being rate-limited, adjust the thresholds:

Nginx — rate limiting configuration
# 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;
If a CDN or load balancer is in front of Nginx, ensure you are rate-limiting by the real client IP ($http_x_forwarded_for or $realip_remote_addr), not the CDN's IP address.

Fix: Maintenance Mode

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:

Nginx — maintenance mode
# 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;
}

Retry-After Header for SEO

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.

Nginx — add Retry-After header
# In your error_page 503 location block:
add_header Retry-After 3600;  # Retry in 1 hour (seconds)
Apache — add Retry-After header
# In .htaccess or virtual host config:
Header always set Retry-After "3600"

Know About 503 Errors Before Your Users Do

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

Frequently Asked Questions

Related Articles