HTTP 503 Service Unavailable: Causes and Solutions
503 Service Unavailable is the server saying "I am alive but cannot serve this request right now." Unlike 500, this is NOT an exception: the cause is known to the server and usually temporary. Let us cover the real scenarios that cause 503, how to use it correctly as a maintenance tool, and how to restore service quickly.
What 503 Means
Per RFC 9110 §15.6.4, 503 means the server is temporarily unable to handle the request due to overload or scheduled maintenance. It is a temporary state — the client should retry later.
Important: 503 MUST include a Retry-After header telling clients how many seconds to wait. This is critical for search bots — Googlebot handles 503 with Retry-After gracefully and does not deindex the site.
6 Common Causes of 503
- Server overload — CPU/RAM exhausted, workers saturated.
- Maintenance mode — admin took the site down for updates.
- PHP-FPM pool exhausted — all children busy, new requests queued.
- Rate limiting — nginx
limit_reqor Cloudflare throttled traffic. - Kubernetes healthcheck fail — pod not ready, readinessProbe failed.
- Upstream overload behind load balancer — all backends reporting unhealthy.
How 503 Differs from 500 and 502
| Code | What Happened | Root Cause |
|---|---|---|
| 500 | Exception in application code | Application |
| 502 | Proxy got no valid response from upstream | Upstream unreachable |
| 503 | Server temporarily unavailable (known reason) | Overload / maintenance |
| 504 | Upstream response timeout | Slow upstream |
Diagnosis
Check externally via the HTTP Header Checker by Enterno.io — you will see the status code and the Retry-After header. If it is missing, the server is not configured correctly.
curl -I https://example.com
# HTTP/2 503
# Retry-After: 120
# Content-Type: text/html
# Server: check load
top -bn1 | head -20
free -m
ss -s
# PHP-FPM status
systemctl status php8.4-fpm
curl http://127.0.0.1/fpm-statusSolutions
nginx: proper 503 for maintenance
server {
# Maintenance toggle
if (-f /var/www/maintenance.flag) {
return 503;
}
error_page 503 @maintenance;
location @maintenance {
root /var/www/maintenance;
rewrite ^(.*)$ /503.html break;
add_header Retry-After 300 always;
}
}PHP: 503 during deployment
<?php
if (file_exists(__DIR__ . '/maintenance.flag')) {
header('HTTP/1.1 503 Service Unavailable');
header('Retry-After: 300');
header('Content-Type: text/html; charset=utf-8');
readfile(__DIR__ . '/503.html');
exit;
}PHP-FPM: increase worker pool
# /etc/php/8.4/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500Calculate max_children as (RAM_MB - 500) / 30, where 30MB is the average PHP worker size.
Rate limiting without 503 chaos
limit_req_zone $binary_remote_addr zone=api:10m rate=60r/m;
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429; # prefer 429 over 503 for rate limits
proxy_pass http://backend;
}For rate limiting, use 429 Too Many Requests, not 503.
Kubernetes readinessProbe
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3SEO-safe Maintenance
Correct maintenance mode:
- Return 503 (not 200!)
- Include Retry-After in seconds
- Keep maintenance under 24 hours
- Do NOT change
robots.txttoDisallow: / - Do NOT redirect to a static 200 page
After maintenance, verify the site via Uptime Monitoring — configure an alert for any deviation from 200.
Frequently Asked Questions
Q: Is 503 during deployment OK?
A: Yes, if brief (<30 sec) and with Retry-After. For zero-downtime deploys use blue-green or rolling deployment.
Q: Will Google deindex my site because of 503?
A: No — if 503 lasts up to 24-48 hours. For prolonged 503 (>1 week) deindexing starts.
Q: How can I be notified of 503 automatically?
A: Enterno.io Monitors with expected_code=200 sends Email/Telegram/Slack alerts within seconds.
Q: Is Retry-After required?
A: Yes. Without it, clients and bots retry aggressively, worsening the overload.
Conclusion
503 is a tool, not a bug, when used correctly. Keys: always return Retry-After, size your PHP-FPM pool to real traffic, use 429 for rate limits, and monitor your site via Enterno.io.
Check your website right now
Check now →