Ana içeriğe geç

Guides / http-status-codes

503 Service Unavailable: Overload, Maintenance and Retry-After

A 503 Service Unavailable means the server is alive and deliberately refusing to do the work, because it is overloaded or in maintenance. Unlike a crash, a 503 is a decision, and RFC 9110 describes the condition as temporary and likely to clear after some delay.

Alive, and refusing the work

To return a 503 at all, something has to be running: it accepted the TCP connection, parsed the request and generated a response. That single fact rules out a whole class of problems. The host is up, the network path works, TLS terminated, and the web server or proxy is functioning. What is missing is capacity or willingness.

RFC 9110 adds a caveat: a server is not obliged to use 503 when overloaded. Some simply refuse the connection instead. A 503 is therefore the polite form of overload. If you get a connection refused or a timeout rather than a 503, you are looking at a different and usually worse failure.

Two neighbors are easy to confuse. A 504 Gateway Timeout means the backend was accepted and then never answered in time; the request was attempted. A 503 means the request was declined before real work started. The whole family is compared in the 5xx overview.

Retry-After, and why you should always send it

RFC 9110 allows a 503 to carry a Retry-After header, in either of two forms: a number of seconds to wait, or an absolute HTTP date.

HTTP/1.1 503 Service Unavailable
Retry-After: 300
Content-Type: text/html

It costs nothing. Well-behaved clients and libraries back off for the stated interval instead of hammering an already struggling server. Search engine crawlers treat the URL as temporarily unavailable and come back later rather than treating the outage as content removal. Your own monitoring and status tooling gets an explicit expected-recovery time to display.

A 503 is not cacheable by default, so intermediaries will not keep serving it after the service recovers.

What causes a 503

  • Overload. All worker threads, processes or connection slots are busy, so new requests are rejected rather than queued indefinitely. Typically starts intermittently at peak and becomes constant as load grows.
  • Maintenance mode. An intentional switch, from a framework flag, a maintenance file or a proxy rule. This is a 503 doing exactly what it should.
  • A dependency is down. A well-written application that cannot reach its database, cache or queue should return 503 rather than a stack trace, because the condition is temporary and not the request's fault.
  • No healthy backends. A load balancer with every member failing its health check has nothing to route to, and many return 503 in that state.
  • Deploys and restarts. The window between draining the old process and the new one becoming ready.
  • Deliberate shedding. Circuit breakers and admission control return 503 on purpose to protect the parts of the system that still work.
  • Resource exhaustion at the host level. Out of memory, out of file descriptors or a full disk, which prevents new work from starting.

The 503-during-deploy pattern

This is the most common 503 that is not a real incident, and it has a recognizable shape: a short burst of 503s, seconds to a couple of minutes long, starting exactly at a release and ending on its own. Correlate the timestamps with your deployment history before investigating anything else.

Handled well, a maintenance 503 should:

  1. Return the real status code. A maintenance page served with 200 tells crawlers your content is now a maintenance notice, which is the worst possible outcome for a planned window.
  2. Include Retry-After with a realistic estimate of the window.
  3. Stay static and cheap. The maintenance page should not depend on the database or application you just took offline.
  4. Allow your own addresses through so the team can verify the new release before reopening.
  5. Be scheduled in monitoring as a maintenance window, so a planned outage does not page whoever is on call.

The fix for unplanned deploy 503s is a health-gated rolling update: start the new process, wait for it to pass a readiness check, then drain and stop the old one. Done properly, there is no window in which nothing can serve.

How to fix an unplanned 503

  1. Confirm the code and read the headers, including whether a Retry-After was sent and which component signed the response:
    curl -sS -o /dev/null -D - https://example.com/
  2. Rule out maintenance mode first. Check for a maintenance flag or file left in place after a release. It happens more often than anyone admits.
  3. Check backend health. On a load balancer, look at how many members are passing checks. Zero healthy members is an immediate answer.
  4. Look at saturation. Worker and connection pool usage, memory, database connections and queue depth. A 503 under load with everything at its ceiling is capacity, not a bug.
  5. Check dependencies. If the database, cache or a critical API is down, fix that rather than the web tier.
  6. Relieve load, then find the cause. Scaling out or raising limits restores service, but a 503 that appeared without a traffic increase usually hides a slow query or a leak that will return.

Peak-hour 503s and scheduled maintenance windows

Overload 503s are usually intermittent long before they become constant, appearing at peak hours and clearing on their own. That early phase is easy to miss from a browser and obvious in a continuous record. A scheduled HTTP check that asserts the expected status code turns those scattered failures into a visible trend with times attached, so you can act before the intermittent phase becomes an outage. Scheduling maintenance windows in the same tool keeps planned 503s from generating alerts.

Check it now

Run the free check against your own site - no account needed.

HTTP check

Monitor this permanently

Get alerted the moment it breaks: HostTracker checks from 300+ locations and notifies you by email, SMS, Slack, Telegram and more.

HostTracker features