SYSTEMS OPERATIONAL
Troubleshooting

504 Gateway Timeout: Causes and How to Fix It

Getwebup 6 min read

A 504 means your server didn't crash - it just didn't answer fast enough. Somewhere between the visitor's browser and your app, one layer got tired of waiting for another and gave up. The fix isn't "restart everything," it's finding which layer quit first.

What 504 actually means

Every 500-series error is your server telling on itself, and 504 has a very specific story: a proxy or gateway (Nginx, Apache acting as a proxy, Cloudflare, a load balancer) sent a request upstream to the real backend - PHP-FPM, a Node process, MySQL through PHP - and got no response within its timeout window. It's not that the backend refused; it's that it never replied in time. That distinction matters, because it means the fix is almost always about timeouts and slow processes, not broken code.

Contrast this with its cousins: a 502 means the backend replied with garbage or closed the connection outright, a 503 means the server is overloaded and refusing new work, and a 504 means the backend just went quiet. Same family, different diagnosis.

Find out which layer is actually timing out

A request to a typical Getwebup or cPanel-hosted site can pass through several hops, and each one has its own timeout clock:

LayerTypical default timeoutWhere to check
Cloudflare (proxied/orange-cloud)100 seconds (fixed on Free/Pro)Cloudflare dashboard → shows a 524, not 504, when it's the one that gave up
Nginx (reverse proxy or in front of Apache)60 seconds/var/log/nginx/error.log - look for "upstream timed out"
Apache (as the app-facing server)300 seconds/var/log/apache2/error.log or cPanel's error log viewer
LiteSpeed / OpenLiteSpeed300 seconds (Connection Timeout)WHM → LiteSpeed Web Admin, or the site's error log
PHP-FPMGoverned by max_execution_timephp.ini or MultiPHP INI Editor in cPanel

Start at the outside and work in. If you're behind Cloudflare, the error page itself tells you something: a genuine 524 (not 504) means Cloudflare's own clock ran out waiting on your origin - the problem is downstream, on your server. If Cloudflare is just passing along a 504 it received from your origin, the fault is entirely inside your hosting.

Common causes, and the fix for each

1. A single request is doing too much work

The most frequent cause on WordPress and PHP sites: a plugin import, a large database migration, a report generator, or a poorly written API call is taking longer than any of the timeouts above allow. Check your slow query log or add simple timing to the suspect script. If a specific admin action (bulk import, backup trigger, theme install) reliably 504s, that's your culprit - not the whole site.

Fix: move it off the request/response cycle. Run it as a cron job or WP-Cron background task instead of making the visitor's browser wait on it. If it must be synchronous, raise the specific timeout for that one endpoint rather than globally.

2. Nginx's proxy timeout is too short for your backend

If you're running Nginx in front of Apache, LiteSpeed, or a custom app (Node, Python, Docker), Nginx's own proxy timeouts default to 60 seconds - shorter than Apache's or PHP-FPM's. That mismatch means Nginx gives up before the backend would have finished.

Fix it in the relevant server or location block:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_connect_timeout 90s;
    proxy_send_timeout 90s;
    proxy_read_timeout 90s;
}

Reload after editing: sudo nginx -t && sudo systemctl reload nginx. Set this a little above your backend's own timeout, not wildly beyond it - a huge value just means visitors stare at a spinner for minutes before eventually getting an error anyway.

3. PHP is hitting max_execution_time

If PHP-FPM kills the script before Nginx or Apache even times out, you'll see it in the PHP error log as "Maximum execution time of 30 seconds exceeded." In cPanel, raise it per-domain via MultiPHP INI Editor:

max_execution_time = 120
max_input_time = 120

On a VPS without cPanel, edit the pool's php.ini or the FPM pool config directly, then restart:

sudo systemctl restart php8.2-fpm

Again - this buys time, it doesn't fix a query that shouldn't take 90 seconds in the first place.

4. The database or an external API is the actual bottleneck

A lot of 504s trace back to a slow MySQL query (missing index, a huge JOIN, table locking) or an external service your site calls out to - a payment gateway, a shipping API, a third-party font or ad script your server fetches server-side. If the slow part is external, add a short timeout in your own code so it fails fast instead of hanging until the gateway kills it for you.

5. Server resources are maxed out

On shared cPanel hosting under CloudLinux, if you're near your LVE limits, PHP processes queue up waiting for CPU or entry processes, and requests time out before they're even properly served. This usually shows as intermittent 504s under load rather than every single time. Check WHM → Resource Usage or run top/htop on a VPS during the slow window to confirm.

Prevention checklist

  • Line up timeouts so they increase as you go inward: Cloudflare/CDN ≤ Nginx ≤ Apache/LiteSpeed ≤ PHP-FPM. A shorter outer timeout than inner one guarantees premature errors.
  • Move anything that takes more than a few seconds - imports, exports, bulk emails, report generation - to a background queue or cron job.
  • Keep an eye on the MySQL slow query log and add indexes before a table grows large enough to make every query borderline.
  • Set explicit timeouts on any outbound API calls your server makes, so a flaky third party can't hang your whole request.
  • Enable page and object caching so most requests never reach PHP or the database at all.
  • If you're on shared hosting and hitting this under load, that's usually a sign it's time to move to a VPS where you control the resource ceiling directly.

When it's not really a 504

Two look-alikes worth ruling out first. A 508 Resource Limit Reached on cPanel/CloudLinux is a hard resource cap, not a timeout - different fix, different log. And a request that just spins forever with no error at all is often a redirect loop or a stuck WP-Cron job, not a gateway timeout - check for that before you start tuning timeout values.

Frequently asked questions

What's the difference between 502, 503, and 504 errors?

502 means the backend sent back an invalid or broken response. 503 means the server is intentionally refusing requests because it's overloaded or in maintenance. 504 means the backend never responded at all within the gateway's timeout window - it just went quiet.

Is a 504 the same as Cloudflare's 524 error?

No. A 524 is specifically Cloudflare's own timeout (100 seconds) running out while waiting on your origin server. If your origin itself returns a 504, Cloudflare will usually pass that through unchanged. Seeing 524 instead of 504 tells you the delay is happening on your server, not in Cloudflare's network.

Will raising max_execution_time in PHP fix a 504?

Sometimes, but only if PHP was the layer cutting the request short. If Nginx or Cloudflare has a shorter timeout than your new PHP limit, you'll still get a 504 - just after a longer wait. Check every layer in the chain, not just PHP.

Why does the 504 happen only sometimes, not on every page load?

Intermittent 504s usually point to load-dependent causes: a slow query that's fine most of the time but chokes under concurrent traffic, or a shared server nearing its CPU/entry-process limits during peak hours. Consistent 504s on one specific page point to that page's own code or a particular database query.

Can a WordPress plugin cause a 504 Gateway Timeout?

Yes, commonly. Import/export tools, backup plugins, and search re-indexers can run long enough to exceed every timeout in the chain. If the 504 only happens when you trigger a specific plugin action, disable that plugin temporarily to confirm, then move the task to WP-Cron or a server cron job instead of running it synchronously.

#504-error #gateway-timeout #nginx #php-fpm #cloudflare #troubleshooting

Keep reading

Chat with Support