Learn
504 Gateway Timeout: Causes and Fixes Behind a CDN
A 504 Gateway Timeout behind a CDN means one proxy in the chain (the CDN edge, an origin shield, a load balancer or a ...
HTTP 503 Service Unavailable means the server, or a proxy in front of it, is temporarily refusing requests because it is overloaded, has no healthy backends, or is in planned maintenance. RFC 9110 (2022) lets the response carry a Retry-After header, for example 120 seconds, so clients know when to come back. A 503 is a deliberate "not now", while a 502 is a broken upstream reply and a 504 is an upstream that never answered in time. The playbook below finds which layer emitted the 503 and gets you to recovery in about 30 to 60 minutes.
An HTTP 503 error tells you that some component chose not to serve the request and expects the condition to be temporary. It does not tell you which component made that choice. A CDN edge, a load balancer, a reverse proxy, a service mesh sidecar and the application itself can all return an identical status line.
That ambiguity is why most 503 incidents take longer than they should. Teams scale the application when the real emitter was a load balancer with zero registered targets, or a rate limiter returning 503 by default. Identify the emitter first, then fix.
A 503 means a component refused the request on purpose. A 502 means a proxy received an invalid or empty response from its upstream. A 504 means a proxy waited for an upstream and gave up when its timeout expired. All three are 5xx server-side errors, but each points to a different failure and a different first fix.
| Status | What happened | Typical latency of the error | First thing to check |
|---|---|---|---|
| 503 Service Unavailable | Component refused: overload, no healthy backends, maintenance, rate limit | Often fast, under 50 ms, because nothing upstream was tried | Backend health, concurrency limits, maintenance flags |
| 502 Bad Gateway | Upstream reset the connection or sent a malformed response | Variable, often fast on connection refused | Crashed processes, TLS mismatch to origin, keepalive races |
| 504 Gateway Timeout | Upstream accepted the request but did not answer before the proxy timeout | Equal to the proxy timeout, commonly 30 to 60 seconds | Slow queries, blocked workers, timeout mismatch between layers |
Error latency is the fastest discriminator: a 503 that returns in milliseconds was a refusal, while a 5xx that returns exactly at your timeout value is a 504 in disguise or a proxy misconfiguration.
Every common proxy leaves fingerprints in the response body and headers. Match what you captured against this matrix before touching capacity.
| Emitter | Signature | Most likely cause |
|---|---|---|
| HAProxy | Body says no server is available to handle this request | All servers in the backend marked down by health checks, or maxconn and queue timeout exceeded |
| Envoy or Istio sidecar | Body "no healthy upstream" or "upstream connect error", server header envoy | Empty endpoint set, outlier ejection, or circuit breaker max pending requests hit |
| nginx | Default nginx error page, server header nginx | limit_req or limit_conn rejecting requests (both default to 503), or a maintenance return rule |
| Varnish | "Backend fetch failed" with a Guru Meditation XID | Backend probe sick, first byte timeout, or origin connection refused |
| Kubernetes ingress-nginx | nginx page from the ingress controller pod | Service has no ready endpoints: failing readiness probes or a label mismatch |
| Amazon Application Load Balancer | Server header awselb, short HTML body | Target group has no registered targets |
| Application | Your own error JSON or template, often with Retry-After | Intentional load shedding, dependency down, maintenance mode |
In most 503 incidents the fix belongs to the layer named in the response signature, not to the application tier that gets scaled by reflex.
Little's law gives the capacity of any worker pool: sustainable throughput equals concurrency divided by latency. A service with 400 workers and a 200 ms average response time handles 400 / 0.2 = 2,000 requests per second.
Now a database index goes missing and average latency climbs to 800 ms. The same 400 workers handle 400 / 0.8 = 500 requests per second. At an offered load of 1,200 requests per second, 700 requests per second have nowhere to go, so roughly 58% of traffic receives 503 while CPU sits at a fraction of its peak.
Retries make it worse. If each rejected client retries 3 times with no backoff, those 700 rejections add up to 2,100 extra requests per second, pushing offered load to 3,300 and the rejection rate above 80%. This is why the fix for a latency-driven 503 is the slow dependency plus retry backoff, not more application pods.
If relaxing a limit or health check makes things worse, revert that single change and keep the rest. Raising a concurrency cap on a service whose dependency is the bottleneck simply moves the queue downstream and can turn 503s into 504s. Roll back deploys before tuning thresholds: a bad release that fails readiness probes is fixed by the previous image, not by a looser probe.
Load shedding versus queueing: rejecting early with 503 keeps latency predictable for admitted requests, while deep queues accept more work but turn every request slow and eventually produce 504s. For interactive traffic, shedding usually wins.
Serving stale versus serving errors: stale-if-error and stale-while-revalidate (RFC 5861) let a cache hide origin 503s, at the cost of users seeing content that may be minutes or hours old. That is acceptable for video segments, installers and images, and wrong for account balances or inventory.
Search visibility: major search crawlers treat a short 503 with Retry-After as temporary and come back later, which is the correct status for maintenance. A 503 lasting more than a few days risks pages being dropped, and returning 200 with a maintenance message is worse because the error page itself gets indexed.
For high-volume static traffic such as video segments, installers and game patches, the CDN layer is where most origin-overload 503s are prevented. BlazingCDN includes origin shield and request coalescing on every plan, and it can run as a second CDN behind DNS with a weighted traffic split, so a 503 storm at one provider does not take down delivery.
A 503 Service Unavailable error is almost always caused by the website's infrastructure, not the visitor's browser or connection. The server, load balancer or CDN refused the request because of overload, missing healthy backends or maintenance. Clearing the browser cache rarely helps; waiting for the Retry-After interval or the operator's fix does.
An HTTP 503 error usually lasts seconds to minutes during traffic spikes or deploys, and as long as the maintenance window during planned work. Servers can state the expected wait in a Retry-After header, in seconds or as a date. A 503 lasting hours typically means zero healthy backends or a maintenance flag nobody cleared.
A 503 means a component deliberately refused the request, while a 502 means a proxy received an invalid or empty response from its upstream. Practically, 503 points to capacity, health checks, rate limits or maintenance, and 502 points to crashed processes, TLS problems between proxy and origin, or connections reset mid-response.
A short 503 Service Unavailable status does not hurt SEO and is the recommended way to signal planned maintenance. Crawlers treat it as temporary and retry later, especially when Retry-After is present. Problems start when 503 persists for several days, at which point pages may drop from the index until normal 200 responses return.
A CDN should cache a 503 response for a few seconds at most, or not at all. Short negative caching protects a struggling origin from a thundering herd, but long TTLs keep serving errors after recovery. A better pattern is serving stale content on origin errors for static assets while passing dynamic 503s through uncached.
Pick one service and run a 30-minute game day: drain all backends behind its load balancer in staging, then throttle its database to triple latency. Record which component returns the 503, whether Retry-After is set, whether your CDN serves stale or passes the error through, and how long dashboards take to name the emitter. If any answer takes longer than five minutes to find, that gap is your next ticket, and the signature matrix above is a starting runbook.
If static delivery is part of what failed, BlazingCDN can run as a second CDN behind DNS with a weighted split, and the BlazingCDN multi-CDN integration guide describes how to add it beside your current provider.
Heavy traffic.
Light bill.
The CDN for video and large traffic
Learn
A 504 Gateway Timeout behind a CDN means one proxy in the chain (the CDN edge, an origin shield, a load balancer or a ...
Learn
A 502 Bad Gateway means a proxy in your request path, such as nginx, a load balancer or a CDN edge, reached the next ...