504 means nginx waited for your app and gave up. Either the app really is too slow for the timeout, or the timeout is set for a faster app than you run.
Default is 60s; anything slower gets cut. Report jobs, batch endpoints, and model inference are the usual offenders.
All app workers busy; new requests wait in the proxy until the timeout fires. Load-related, not request-related.
The request wedged on a lock, stuck DB query, or dead peer connection. Even huge timeouts won't help.
tail -f /var/log/nginx/access.log | grep ' 504 '
location /reports/ {
proxy_read_timeout 300s;
proxy_send_timeout 60s;
}
upstream app { server 127.0.0.1:8080 max_conns=50; }
# return 202 + job id; let a worker do the work; poll or push the result
Infinite timeouts are an outage waiting to happen: worker slots fill with stuck requests and healthy traffic dies too. Long work belongs in a queue; HTTP belongs in seconds.
proxy_read_timeout defaults to 60 seconds. Failures clustering at exactly one minute are the fingerprint of this default being hit — raise it for the specific slow path, scoped in its own location block.
No: global increases keep hung upstream connections (and their workers) alive far longer, hurting capacity under incidents. Scope raises to the endpoints that legitimately need them, and move genuinely long work to async jobs.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.
One short email when new fixes and production templates drop. No spam, unsubscribe anytime.
High-frequency cloud servers in 32 locations — deploy in 60 seconds, pay by the hour.
DigitalOcean — Predictable flat-bandwidth cloud — $200 credit for new accounts.
We earn a commission if you buy through our links — it never costs you extra. More vetted tools on our picks hub · comparing clouds? DigitalOcean vs Vultr and vs AWS · full deals: DigitalOcean · Vultr · NordLayer · Semrush