504 Gateway Timeout meaning: read the page, name the machine
504 Gateway Timeout means a machine standing in front of the website asked the machine behind it for a page, waited a fixed number of seconds, and gave up. The site was not refused, and nothing crashed. Something was too slow, and a stopwatch reached zero.
The definition is the easy part. The part that decides what you do next is which machine ran that stopwatch, and it is written on the error page you are already looking at.
Who emitted it, from the page in front of you
Every intermediary produces its own error document, and they are distinctive enough to identify at a glance.
| What the page says | Who gave up | Who can change the limit |
|---|---|---|
| Cloudflare branding, "Error 504", a Ray ID at the bottom | Cloudflare, waiting on your origin | Cloudflare, on the plans where the setting is exposed |
Plain text, "504 Gateway Time-out", nginx on the second line | nginx, waiting on PHP-FPM or an app server | Whoever owns the server config |
| "Gateway Timeout", Apache signature with a version string | Apache acting as a reverse proxy | Same |
| Your host's own branded error page | The hosting frontend | Support, and only support |
| A styled page from the site's own theme | Nobody. This is not a 504 | See below |
If curl -sSI disagrees with what the browser rendered, believe curl. Cloudflare and several hosts will serve a helpful-looking page with a status the browser never shows you.
The last row of that table is worth its own sentence. A themed page means the request reached the application and the application answered, so whatever went wrong happened inside the site and the status code is almost certainly 200. That is a different problem with a different fix, and it will not appear in any uptime report.
What it does not mean
It does not mean the server is down. A server that is down refuses the connection or does not answer at all, which produces a different failure with no HTTP code in it.
It does not mean your connection is bad. The 504 was generated on the internet side, by a machine that reached your site's network perfectly well.
It does not mean the work stopped. This is the detail that matters most on a client site and the one nobody mentions. The backend usually keeps running the request after the proxy has walked away. An import that timed out may finish. A payment may go through. A visitor who reloads and retries can end up with the operation performed twice, once for each attempt, and no error visible anywhere.
502, 503, 504: the one-line difference
| Code | What the intermediary experienced |
|---|---|
| 502 Bad Gateway | An answer came back and it was unusable, or the connection died |
| 503 Service Unavailable | The server answered, and what it said was "not right now" |
| 504 Gateway Timeout | No answer came back in time |
Only 503 is a deliberate message. The other two describe an intermediary's experience of silence, which is why they are so often reported by people who cannot see the machine that stayed silent. The longer version of the 502 case, including the three commands that separate a dead process from a saturated one, is in what a 502 actually tells you.
The first thing to measure, before changing anything
Time the request rather than reading about timeouts.
curl -s -o /dev/null -w 'ttfb %{time_starttransfer} total %{time_total} code %{http_code}\n' \
https://example.com/
Run it on a static file and on the page that failed. A static file that answers instantly while a dynamic page crawls tells you the host and the network are fine and the application is the subject. Both slow, and the subject is the host.
Raising the limit is not a fix, and on shared hosting it is usually not even available. It converts a page that fails in sixty seconds into a page that fails in a hundred and twenty, which no visitor will ever see, because nobody waits. The configuration side of this, and the reason the component that gives up is never the component that was slow, is laid out in the number behind a 504.