Troubleshooting guide · http-status · Published 2026-08-16 · 4 min read

HTTP 504 gateway timeout

HTTP 504 gateway timeout: what the proxy is waiting for, how to read the logs for the upstream, and how to fix the slow request.

Flat editorial illustration showing a lantern-style status readout with a neat row of stacked directory rails, each rail marked with an abstract tally.
Illustration: this article at a glance.

504 Gateway Timeout says the proxy in the middle got nothing from the next hop within its own wait window. The browser reached the gateway, the gateway reached the upstream (PHP, a second application, or a cache host), and the work simply stopped coming back in time. It is the actual timeout you hit when the 502 story ends in the proxy.

Editorial close-up illustration showing a lantern-style status readout with a neat row of stacked directory rails, each rail marked with an abstract tally.
Illustration: a closer look at the technique described above.

What 504 means

The difference from a 502 is timing: a 502 is "could not connect or got garbage", a 504 is "connected but never finished in time". Both live in the gateway layer, so the fix is usually at the nginx/Apache/CDN config or the upstream (PHP-FPM), never in the page.

LayerTimeout that 504sWho owns the knob
nginx → PHP-FPMfastcgi_read_timeoutServer config
nginx → appproxy_read_timeoutServer config
CDN → originCloudflare proxy timeout (~100s)Edge config
Browser → CDNGateway/user-agentClient side

Common causes

Fix in order

  1. Confirm 504 is live. A CDN can serve a stale 504 from cache for a while after the origin recovers. Fetch past the proxy:
curl -sI -H "Cache-Control: no-cache" https://example.com/slow-page

Read the status, then compare against the cloudflare 524 article for the edge case where the edge itself gave up.

  1. Read the log that knows the upstream. The nginx error log names the exact layer: upstream timed out (fastcgi_read_timeout) vs upstream prematurely closed (app crashed). See error log reading.
  2. Find the slow request. top, the PHP-FPM status, and a slow-query log will show which page or job hogs the worker. If it is a specific page, keep it out of the synchronous path (push the work to a queue).
  3. Raise the timeout only to the real ceiling. If the job must finish, raise fastcgi_read_timeout or proxy_read_timeout (not proxy_connect_timeout, which governs dialing, not waiting):
location ~ \.php$ {
    fastcgi_read_timeout 300;
}
  1. If the worker pool is the limit, the symptom is "504 only when busy". Add workers or vertical power as in the 502 fix order, and cache the page that was slow.
  2. After the fix, tail the error log and load the page; a 200 with a clean log is the pass.

Verification table

TestCommandWhat it proves
Live statuscurl -sI https://example.com/slow200, not 504
Proxy layergrep "upstream timed out" /var/log/nginx/error.lognginx saw the issue
PHP healthsystemctl status php-fpmWorker pool up
Slow pagetime curl -s https://host/slowRuntime matches the timeout

Prevention

When to involve a professional

If a clean re-crawl still 504s every few minutes while the origin is idle, the problem is the health of the reverse proxy or load balancer, which the host owns. Get the host to test from outside the network, not to tune a page.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services