504 Gateway Timeout: Causes and How to Fix It

A 504 Gateway Timeout means the proxy waited for your server and gave up. Learn why it happens, how it differs from a 502, and the fixes that actually hold.

A 504 Gateway Timeout means two servers were talking, one of them was too slow, and the one holding the visitor’s connection stopped waiting. The proxy did its job. The upstream did not answer in time.

This is the most misdiagnosed of the gateway errors, because the obvious fix — increase the timeout — rarely solves anything. The proxy is reporting a symptom of slowness that already exists. Raising the limit only changes how long a visitor stares at a spinning tab before the error appears.

504 versus 502: which one you have

Both appear on the same proxy error page, and the difference tells you where to look.

What it means Where the problem is
502 Bad Gateway The upstream answered with something unusable, or refused the connection The upstream is down, crashing, or misconfigured
504 Gateway Timeout The upstream accepted the connection and never answered in time The upstream is alive but slow, or unreachable in a way that hangs

A 504 is the better of the two, in a narrow sense: the process is running. It is simply not finishing. Read 502 Bad Gateway if your error is the other one.

The key detail to capture is timing. A 504 that appears after exactly the same number of seconds every time is a timeout ceiling. A 504 that appears after a random interval is resource exhaustion or contention.

Where the timeout is actually set

A single request can pass through four or five separate timers, and the shortest one wins:

  1. The visitor’s browser — usually generous, rarely the cause.
  2. The CDN — Cloudflare’s default origin timeout is 100 seconds.
  3. The proxyproxy_read_timeout in nginx (60s by default), ProxyTimeout in Apache.
  4. The application’s own limitmax_execution_time in PHP, a query timeout in the database driver.
  5. The database or an external API — a lock wait, a slow query, a third-party call with no timeout at all.

Changing the wrong one is the standard mistake. If nginx gives up at 60 seconds while PHP is allowed 300, raising PHP’s limit changes nothing. Find the smallest number in the chain and start there.

The usual causes

A slow database query

The most common cause on a site that used to be fast. A table grew past the point where an index still helped, a plugin added an unindexed ORDER BY, or a reporting page scans everything. The query is not broken; it is linear where it used to be constant.

Fix: turn on the slow query log and read it rather than guessing. In MySQL, SET GLOBAL slow_query_log = 1; with long_query_time = 2 will name the offender within a day on a busy site. Add the missing index, or move the heavy work off the request path.

The upstream is saturated

Every worker is busy, so new requests queue. This produces timeouts that come and go with traffic, which is why they are often misread as “the host is flaky.” Look at load average against CPU count, and at the number of active workers versus the pool size.

Fix: add capacity or reduce the work per request. On PHP-FPM, a pool that is fully occupied is the signal — but raising pm.max_children without adding RAM converts a queueing problem into a 502 as the kernel starts killing workers.

A firewall is dropping packets instead of rejecting them

This one is genuinely hard to spot. A firewall, security group, or proxy rule that drops traffic leaves the connection hanging open until the timer expires — producing a 504. A rule that rejects produces an instant connection error instead, which would be a 502. So a 504 that appears on every request, even for a page that should be instant, is often a network rule rather than a slow application.

Fix: confirm the origin is reachable from the proxy’s network on the port in question, and that ICMP or the relevant ports are not being silently dropped. Check whether the timeout duration matches the proxy’s configured limit exactly — if it does, the connection is being established and then going nowhere.

A long-running operation on the request path

Report generation, PDF exports, large image processing, feed imports, and payment webhooks that do real work inline. These will always exceed a sensible proxy timeout, and they should not be synchronous.

Fix: move the work to a background job and return a status page. Raising the timeout keeps the visitor waiting on a request that is still the wrong shape.

An external dependency with no timeout

An API call to a payment provider, a geolocation service, or an email sender that hangs will hold your worker until something else gives up. One slow third party becomes a site-wide 504 because workers are all parked waiting on it.

Fix: set an explicit, short timeout on every outbound request and handle the failure path. This is the single highest-value change for sites that depend on third-party APIs.

DNS resolution delay

If the proxy resolves the upstream’s hostname per request and DNS is slow, requests can exceed the limit before a connection is even attempted. Look for upstream timed out ... while resolving in the proxy log.

Fix: resolve once at startup rather than per request, or use a resolver with a cache.

Confirming the fix

Clearing a 504 requires evidence, not a single successful reload:

  1. The same request that failed now completes — not a lighter page, the one that broke.
  2. The duration is comfortably inside every timeout in the chain, not just under the largest one.
  3. It holds under load. Replay the request while the site is busy; a fix that only works on an idle server is not a fix.
  4. The proxy log stops recording timeouts — check timestamps.

Why a repeating 504 matters more than a one-off

Search engines treat timeouts as a temporary condition and come back. That is generous, and it is also why slow failures are more damaging than clean ones: a site that answers in 45 seconds occasionally, and 504s otherwise, is a site that crawlers learn to visit less often. Crawl budget is finite, and a server that wastes it gets a smaller share of it.

The pattern to watch for is not the error itself but its recurrence. A 504 on the same URL at the same time each day is a scheduled job colliding with traffic. A 504 that spreads across URLs is a resource trend.

Both are visible from outside without instrumenting the application. SitesRadar’s free plan records response time alongside status code for one site and alerts you when either degrades, so you learn about a growing timeout problem before a customer reports it. For the wider picture — uptime, SSL, DNS, and broken links on the same schedule — see the client site down triage checklist.

FAQ

Is a 504 my server’s fault? Almost always. A 504 means the proxy reached your server and your server did not finish in time. The exception is a dropped network rule between the two, which is still a configuration problem on your side of the CDN.

Should I just increase the timeout? Only if you have confirmed the request legitimately takes longer than the limit. Increasing it without that evidence hides the problem and gives visitors a longer wait before the same failure.

Why does my site work but one page always 504s? That page does something expensive the others do not — a heavy query, an export, or a call to a slow external service. It is the most fixable version of this error: the cause is isolated to one code path.

How long should I wait before investigating? A single 504 can be a transient upstream hiccup. Two within an hour, or any repeat on the same URL, is a pattern worth investigating.

Can a 504 affect SEO? Repeated timeouts can reduce how often crawlers visit. A site that is sometimes slow and sometimes unavailable teaches them to come back less often, which slows indexing of everything else.

← More from the SitesRadar blog