breakitdown

504 Gateway Timeout

Answer

504 Gateway Timeout means a proxy or load balancer forwarded your request to an upstream server and gave up waiting for its response. The proxy is fine; the upstream is slow or stuck.

504
Gateway Timeout RFC 9110 §15.6.5

A proxy or gateway waited too long for the server behind it to respond.

The upstream accepted the connection or request but did not reply within the proxy's timeout, for example nginx's proxy_read_timeout (60 seconds by default). The upstream may still be working on the request and finish it after the client has given up, which matters for non-idempotent operations. Find the slow query or external call before raising timeouts.

Explained

The proxy-to-upstream hop is the one that failed, and it failed by timing out rather than by being refused (that would be 502). nginx logs upstream timed out (110: Connection timed out) while reading response header from upstream when proxy_read_timeout (60 seconds by default) runs out, and while connecting to upstream when proxy_connect_timeout does.

Other layers have their own limits: an AWS Application Load Balancer's idle timeout is 60 seconds by default, and Cloudflare reports its 100-second timeout as 524 rather than 504. The shortest timeout in the chain wins, so check every hop.

A 504 does not mean the work stopped. The upstream may finish the request after the client gave up, so a retried POST can run twice. For long jobs, return 202 Accepted with a status URL and do the work in the background instead of raising timeouts.

How to debug it

  1. Read the proxy error log to see which timeout fired: connect, send or read.
  2. Find the same request in the upstream's logs and measure how long it actually took.
  3. Profile the slow path: slow database queries, lock waits, calls to external APIs without their own timeout, exhausted connection pools.
  4. List every timeout between the client and the app (CDN, load balancer, nginx, app server) and make them consistent, with outer layers slightly longer than inner ones.
  5. Raise a timeout only for endpoints that are legitimately slow, for example in a dedicated nginx location block.

Gotchas

Related explainers

← All HTTP status codes