Deploy Error Decoder

504 Gateway Timeout — how to fix it

Quick answer: 504 Gateway Timeout means your reverse proxy forwarded the request to your app but didn't get a response in time and gave up. Unlike a 502 (no/invalid response), the app is reachable but too slow. Find the slow endpoint, fix the slowness (a query, an external call, a blocked loop), and only raise proxy_read_timeout if the work is legitimately long.

What the error looks like

The proxy returns 504 and logs a timeout against the upstream:

# /var/log/nginx/error.log
upstream timed out (110: Connection timed out) while reading
response header from upstream, upstream: "http://127.0.0.1:3000/"

502 vs 504: a 502 means the upstream gave nothing or garbage; a 504 means it was reachable and simply too slow to answer within the timeout. The app is alive — it's the latency that's the problem.

Why it happens

A slow database query

An unindexed or heavy query holds the request open past the proxy timeout.

A slow external call

The endpoint waits on a third-party API that's slow or itself timing out.

A blocked event loop

Synchronous CPU-heavy work stalls the process so it can't respond in time.

Timeout set too low

The work is legitimately long but the proxy's read timeout is shorter than it needs.

Diagnose it in three steps

1

Find the slow endpoint

# Time the request straight at the app, bypassing the proxy
time curl -s http://127.0.0.1:3000/slow-endpoint > /dev/null
2

Find what it waits on

# Add timing/log lines around DB and external calls.
# Most 504s trace to one slow query or one slow dependency.
3

Decide: fix or extend

# Accidentally slow -> fix the query/call.
# Legitimately long -> move it to a background job (return 202),
#   or raise proxy_read_timeout for that route only.
The real fix

Make it fast, or make it async

Raising the timeout is the last resort, not the first. Most 504s are a slow query or a slow dependency you can fix. For genuinely long work, don't hold the HTTP connection open — accept the job, return immediately, and let the client poll:

# nginx: only extend the timeout where the work really is long
location /reports/generate {
    proxy_pass http://app;
    proxy_read_timeout 120s;
}
# Better: return 202 Accepted + a job id, do the work in a queue.
How Infraveil handles this

See the slow request, not just the timeout

Infraveil gives you request tracing and live logs across your services on your own servers, so a 504 isn't a guessing game — you can see which request is slow and what it's waiting on. Health checks catch a degraded instance, and recovery is approval-gated and recorded.

Request tracing and live logs show which path is slow
Health checks surface degraded instances before they pile up
Recovery actions approval-gated and recorded, on servers you control

Frequently asked questions

What is a 504 Gateway Timeout?

A reverse proxy or gateway forwarded a request to the upstream app but didn't receive a response within its timeout, so it returned 504. The app is reachable but too slow.

What's the difference between 502 and 504?

502 means the upstream returned no valid response (crashed, not listening, wrong port). 504 means the upstream was reachable but took too long to respond.

How do I fix nginx 504?

Find and fix the slow endpoint (query, external call, blocked loop). For legitimately long work, move it to a background job, or raise proxy_read_timeout for that route only.

Should I just increase the timeout?

Only for genuinely long operations. For accidental slowness, raising the timeout hides the problem; for long jobs, prefer an async pattern (return 202 and let the client poll).