Troubleshooting guide · http-status · Published 2026-08-15 · 4 min read
HTTP 503 service unavailable
HTTP 503 service unavailable explained: the maintenance and overload status, examples with Retry-After, and the ordered fixing sequence.
- ·What a 503 is
- ·Maintenance mode
- ·Fix order
What a 503 means
A 503 Service Unavailable says the server, or the app behind it, is temporarily unable to serve this request, but expects to be back. Unlike a 500, the server is healthy enough to say "not now". Unlike a 502, there was no gateway in the middle to confuse; the app issued the 503 directly. The headers usually carry Retry-After, and it may carry a real number or an HTTP-date the client can parse and wait on.
| Owner | Typical message | True state |
|---|---|---|
| The app in maintenance mode | A branded "back soon" page | Deploy or maintenance files are active |
| nginx/LB rate or upstream | Plain "Service Unavailable" | Backend exhausted or drained |
| Platform (host, Cloudflare) | Cloudflare-branded 503 | Edge or origin slot temporarily unavailable |
Causes
- Maintenance mode is left on: WordPress
.maintenancefile, a plugin "maintenance mode" toggle, or a deploy script that never removed its marker. - A deploy scale-down: the app is starting on a fresh slot and the health gate does not pass yet.
- The server is genuinely overloaded: too many concurrent requests, a slow endpoint holding the whole pool, or a memory ceiling.
- A database is down, so every app request returns 503 after the connection attempt.
- A platform or single instance (Heroku, Railway, Vercel) is scaling, and the warm-up window is slower than the load balancer retries.
The ordered fix
- Check the obvious toggle first. A stale
.maintenancefile, an old deploy marker, or a "maintenance" plugin is the cause nine times out of ten. In WordPress, look for a deadmaintenancefile inwp-content/or a plugin still publishing its maintenance page. - Reproduce the state. Ask who else sees the 503: visit in a private window, then
curlthe home and one deep page. A private window that loads the site normally points to a cache your own browser keeps. - Read the log and the rate. A
Retry-After: 600plus a load-bound error means the server expects you to wait; aRetry-After: 0plus an app trace means maintenance or a bot attack. - Fix the maintenance marker. Remove the file or toggle the mode and reload. Keep a checklist: deploy scripts must clean the marker in the same job that deploys the app.
- If overloaded: scale temporarily (more workers, a second process) or offload a heavy endpoint. On MySQL, confirm the DB is reachable before touching frontend rules.
- If the health gate stalled: check the app's health endpoint; a 503 is often the LB eagerness. Fix the process, then bring the instance into rotation.
curl -sI https://example.com/
HTTP/1.1 503 Service Unavailable
retry-after: 300
When 503 is the right answer
A 503 is the correct status during maintenance, deploys, and genuine overload, and it beats a 200 with a "coming soon" page for two reasons. A 200 maintenance page gets cached and ranks, which misleads users and crawlers. A 503 tells bots to come back; you keep the URL in the crawl queue and lose no equity while the gap holds.
Prevention
- Wire the maintenance toggle to a single environment flag, so "off for five minutes for a deploy" cannot leave an orphan state.
- Verify after every deploy that the maintenance marker is gone and the real home page returns 200.
- Add a monitoring ping that alerts on "503 for X minutes", not just on "site down".
When to involve a professional
If the 503 line in the log is a timeout or an exhausted connection pool and the page is yours, a host or an AWS/LB specialist will map the backpressure. Do not disable Retry-After or the maintenance file holding the site up; fix the underlying cause first.