Key takeaways
- Each layer has its own limit: nginx, a host proxy, PHP, PHP-FPM, the CDN. In one WordPress.org thread, nginx allowed 300 seconds and the request still died at 60.
- The action may have finished anyway. A menu save that returned a 504 had saved, and a checkout that timed out still sent its order email, so check before you retry.
- On a store, look up the payment in your gateway’s records and in WooCommerce → Status → Logs before telling a customer to try again.
- Raise a timeout only at the layer the logs point to. One user fixed a bulk image job by raising a cPanel proxy timeout from 300 to 1,200 seconds.
- If many unrelated URLs time out together, look at PHP worker capacity before blaming one plugin.
A 504 Gateway Timeout means a server that passes requests along, such as nginx, your host’s proxy or a CDN, waited for the server behind it and gave up. RFC 9110, the HTTP standard, defines it like that: a gateway or proxy did not get a timely response from an upstream server it needed. On a WordPress site, that upstream is almost always PHP running WordPress, and behind PHP sits the database or a remote service.
So the code tells you where the waiting stopped. It doesn’t tell you what was slow. The most common mistake is to raise a timeout before working out which layer gave up and what work was taking so long. If you are seeing 503s as well, our explainer on what a 503 response code means covers the code that looks the most like this one.
How is a 504 different from a 502 or 503?
All three are server-side errors, but each one blames a different part of the chain. The table shows where each one sends you first.
| Code | What happened | Where to look first |
|---|---|---|
| 502 Bad Gateway | The upstream answered, but the answer was broken or unusable | PHP error log, crashed PHP processes |
| 503 Service Unavailable | The server said it can’t take the request right now | Maintenance mode, overload, resource limits |
| 504 Gateway Timeout | The upstream didn’t answer before the gateway’s limit ran out | Which request hung, and which layer ended it |
| 524 (Cloudflare only) | Cloudflare’s own timeout waiting for your origin | Your origin server, not Cloudflare |
The error page won’t tell you whether your host, a plugin, the database or a payment API was slow. It can also look different depending on who generated it: “504 Gateway Time-out (nginx)”, “Update failed: 504 Gateway Timeout” in the admin, an import plugin’s error line, or a checkout that spins and then fails.
Why the action may have worked even though you saw an error
A 504 means the gateway stopped waiting. PHP may keep going after that. In one WordPress.org thread, a menu save returned a 504 after about a minute, but the menu had been updated. In a WooCommerce thread, checkout hung for 60 seconds and showed “Gateway Timeout”, and the order email still arrived.
That changes what you do next. Don’t refresh a heavy request over and over. Every retry can start another copy of the same slow work, take another PHP worker and make the queue longer. Check what happened first: did the post save, did the import write rows, did the payment go through.
Step one: find the exact request that timed out
Most of the diagnosis comes before you change a single setting. Collect these facts while the error is fresh:
- Write down the URL, the action and the time. “Saving the main menu at 14:32”, not “the admin is broken”.
- Open the browser’s Network panel (right-click, Inspect, Network), repeat the action once and find the red 504 row. Note the request URL, such as
/wp-admin/admin-ajax.php,/wp-json/...or?wc-api=..., and how long it ran before failing. - Work out the scope. One action or many URLs? Admin only, or the front end too? Every time, or only some of the time?
- Look at the duration. If failures keep stopping at about the same number of seconds, that number is a configured limit. It points you to the layer that set it.
- Get the logs for that timestamp. You need the access log, the error log, the PHP error log and, if you can get it, the database slow-query log. On shared or managed hosting, ask support to match your URL and time against their logs and tell you which component returned the 504.
Kinsta’s server-errors documentation recommends the same thing: match the time and URL of the failure to the access and error logs. If you want PHP errors from WordPress too, turn on private logging in wp-config.php above the “stop editing” line:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
Errors then go to wp-content/debug.log and visitors don’t see them. WordPress’s debugging handbook says these tools are meant for local or staging sites, so turn them off when you are done. In one Stack Overflow case, reinstalling and deactivating plugins did nothing, and the debug log showed the exact line that was breaking.
What usually causes a WordPress 504, and the fix for each
Nobody publishes data on how often each cause happens. The order below follows how often each one turns up as the confirmed answer in WordPress.org, Stack Overflow and Reddit threads. That partly reflects which fixes are easy to report, so treat it as a place to start, not a ranking.
A plugin doing too much work in one request
This is the usual cause when the 504 hits one action, especially in wp-admin, and the rest of the site works. Admin requests skip the page cache and run admin-only plugin code, so a slow hook shows up there first. In the Nav Menu Roles thread, deactivating the plugin turned a save that timed out after about a minute into a two-second save.
Scale can make this worse. A plugin that is harmless on 500 posts can rewrite every post on every dashboard load when you have tens of thousands. One detailed 2026 write-up described a post-ordering plugin doing exactly that. The 504 looked like a failed login.
Fix: use the Health Check plugin’s troubleshooting mode. WordPress’s support handbook explains that it turns off plugins and switches to a default theme for your logged-in session only, so visitors keep seeing the normal site. Turn plugins back on one at a time until the 504 comes back. Then update, configure, replace or report the plugin. Turning it off for good is a workaround, not a fix.
A long job running inside a browser request
Imports, backups, migrations, security scans and bulk image optimization all try to do minutes of work inside one web request. Messages like “Import Error 504 Gateway Time-out” come from this.
Fix: make the work smaller or move it out of the browser. Kinsta recommends WP-CLI or scripts for imports, exports and bulk operations. Use the plugin’s batch or chunk settings if it has them. For Duplicator, its documentation suggests directory filters, a different database build method or the DupArchive engine, which has a 500 MB limit in the free Lite version. Duplicator’s Max Build Time limits only the plugin’s own build. It does not lift your host’s limits.
A slow external service
Some plugins call out to SMTP servers, payment gateways, shipping APIs or licence servers while the page waits. If that service is slow, the whole request waits with it. In the WooCommerce checkout thread, turning off the SMTP plugin made checkout work but stopped all order emails. Trying other SMTP plugins didn’t help. Switching from the SMTP server to a mail API service fixed it.
Fix: find which remote call is hanging and replace it, cache its result or give it a shorter deadline. Turning off the feature only hides the symptom.
PHP workers are all busy
If many unrelated URLs return 504 at the same moment, think capacity before you think plugin. Kinsta’s documentation explains that requests can queue while they wait for a free PHP thread, then time out. Requests that visitors have already abandoned can still be holding workers.
Fix: find out what is filling the workers, such as uncached traffic, a bot or one slow endpoint called over and over. In one thread, restarting PHP-FPM brought a site back after renaming the plugins folder did not. That restart is a host or server task, and it clears the jam without explaining it. More workers need more memory, so a plan upgrade without a diagnosis can cost more and change nothing. One store on a 6-core, 12 GB plan still had 504s.
The limit was raised at the wrong layer
Every layer between the visitor and the database has its own clock, and whichever runs out first sends the error. In one WordPress.org thread, a scan of about 150,000 files kept dying at about 60 seconds. Nginx was set to 300 seconds, and raising PHP’s max_execution_time made no difference. Duplicator’s documentation makes the same point: if PHP limits are already high and the problem continues, the web server’s timeout may be the one cutting the request off.
| Layer | Setting | Who usually changes it |
|---|---|---|
| PHP | max_execution_time | You (php.ini or host panel), if the host allows it |
| PHP-FPM | Pool and request time limits | Host or server admin |
| Nginx | proxy_read_timeout, fastcgi_read_timeout | Host or server admin |
| Host proxy (for example cPanel’s) | Proxy timeout | Host |
| CDN | Origin response timeout | CDN plan and settings |
The nginx documentation gives proxy_read_timeout a default of 60 seconds. It measures the gap between two reads from the upstream, not the total time the response takes. Hosts often change these values, so a repeating 60-second failure is a clue, not proof.
Fix: raise a limit only at the layer the logs point to, and only for work that really needs the time. In one thread, a bulk image job failed at 60.081 seconds and worked once the cPanel proxy timeout went from 300 to 1,200. Raising limits everywhere just lets slow work hold workers for longer.
A CDN in front of the site
A CDN can have a shorter timeout than your origin server. Cloudflare reports its own timeout as 524, not 504, and its “Host Error” page points at your server. A CDN won’t fix a slow origin. It only caches pages for anonymous visitors, which is why the homepage can load fine while wp-admin and checkout time out.
A 504 at checkout: check the payment before anything else
On a WooCommerce store, a checkout that times out can still have charged the customer. One WordPress.org case with Stripe and PayPal shows exactly that: the payment went through, but the request back to the store returned 504 and the thank-you page never loaded. If the customer tries again, you can end up charging them twice.
WooCommerce’s troubleshooting guide for orders gives the order of checks. Open the order and read its status and notes. Search the payment gateway’s own records for the transaction. Read the gateway log under WooCommerce → Status → Logs. If the gateway shows a charge but the order is still pending, check the webhook or callback setup and match the two up before you ship anything. Only then tell the customer what to do.
When to stop and get help
Stop guessing once you have the URL, the time and a scope, but no logs. At that point the fix sits with whoever can see the server: your host for proxy, PHP-FPM and resource limits, or a developer for plugin code and slow queries. Send them the request, the timestamp, the duration and what you have already ruled out. If a store migration or plugin update stalls partway, don’t mark steps as complete by hand to get past the timeout. Keep the backup and get help.
If you’d rather hand over the whole job, SiteSelf’s WordPress troubleshooting and bug fixes work starts from the error on your live site: with hosting (SSH) access it reads the logs, makes the fix, fetches the page again and tells you in chat what changed. For other errors, the guide to why WordPress is not loading sorts problems by what you see on screen.
Frequently asked questions
Is a 504 my host’s fault or my site’s?
The code alone can’t tell you, and in public threads the answer goes both ways. Some 504s come from a plugin’s admin code, others from a crowded server. The logs decide it, so ask your host to match your URL and timestamp against them before you change plans or blame anyone.
Why does the 504 still happen after I raised max_execution_time?
Another layer is probably ending the request first, such as nginx, the host’s proxy or PHP-FPM. If the error still arrives at the same number of seconds after your change, you changed the wrong clock. Ask the host which component returned the 504.
Why does it happen only in wp-admin?
Admin pages skip the page cache and run plugin code that never runs for visitors. A fast cached homepage doesn’t mean the server behind it is healthy. Test with Health Check’s troubleshooting mode to find which plugin’s admin code is slow.
Will a CDN or better hosting fix a 504?
A CDN caches pages for anonymous visitors. It doesn’t make slow PHP faster, so admin pages and checkout still time out. Bigger hosting helps when the logs show the server is out of capacity, and does nothing for a plugin stuck in a loop.
Will moving away from WordPress stop the timeouts?
Not on its own. Replies in r/webdev made the point that heavy work times out on any framework if it runs inside a web request. The fix is the same anywhere: batch the work, queue it or run it from the command line.
Is there a fix for a 500 error that hides a 504?
Some hosts show a generic 500 page while their access log records a 504. If the 500 steps don’t help, ask what the access log recorded for that request. Our guide to fixing a server error 500 covers the real 500 cases.
Leave a Reply