A 502 Bad Gateway means a proxy in front of your site got an invalid response from the server behind it. A 504 Gateway Timeout means that upstream server didn't respond in time. Both point to the same place to start: figure out whether the failure is happening at Cloudflare's edge or on your hosting account, then narrow down from there.
If your domain is proxied through Cloudflare, check that layer first since it sits in front of everything. If it's not proxied, or Cloudflare shows the origin as healthy, the problem is almost always PHP running out of time or memory, or the application itself hanging on something slow.
Check whether Cloudflare is in the path
If your domain's DNS is proxied through Cloudflare (the orange-cloud icon on a DNS record), Cloudflare sits between visitors and your hosting account. A 502 or 504 in this setup can come from either side:
- Cloudflare-generated error page (has a Cloudflare ray ID and Cloudflare branding at the bottom): Cloudflare reached your server but didn't get a valid or timely response. The origin server is the thing to fix.
- Plain error with no Cloudflare branding: the request may not be going through Cloudflare at all, or your origin returned its own 502/504 page.
To rule Cloudflare out as the cause, temporarily switch the DNS record to DNS-only (grey cloud) in Domains → click the domain → DNS, and reload the site directly against the origin. If the error persists with Cloudflare out of the path, the issue is on your hosting account, not the proxy. If it disappears, Cloudflare's proxy layer was involved, most often because the origin took too long to respond and Cloudflare gave up waiting.
When it's a timeout: PHP and application limits
504s specifically mean something took too long. The most common cause is a PHP script that's still running when the proxy's patience runs out: a slow database query, an external API call that's hanging, a large import or export, or unoptimized code processing too much at once.
Start with the error log. Open cPanel from your hosting service and check Metrics → Error Log, or look at your per-account log as described in enabling error logging. A "Maximum execution time exceeded" entry confirms a PHP-level timeout: the script hit max_execution_time before finishing. You can raise this value from Services → PHP → Edit PHP options, but raising the limit is a bandage, not a fix, if the underlying request is genuinely too slow. Find out what's actually slow first:
- Database queries: check for a slow query log or missing indexes.
- External API calls: if your code calls a third-party service, that service's latency becomes your latency. Add timeouts on your end so a hanging external call fails fast instead of stalling the whole request.
- Large operations: bulk imports, PDF generation, or image processing should run in the background (a cron job or queue) instead of inside a single page request.
If memory is the real constraint rather than time, you'll usually see "Allowed memory size exhausted" instead, which is a 500-family error, not a 502/504. The two get confused often since both come from a script that couldn't finish cleanly. See fixing a 500 Internal Server Error for that case.
When it's not a timeout: broken upstream response
A 502 without a timeout involved usually means the upstream process crashed or closed the connection instead of running long. Common causes:
- PHP fatal error mid-request: a fatal error can terminate the process abruptly enough that the proxy sees an incomplete or empty response rather than a clean error page. Check the error log for a fatal error matching the request time.
- A crashed or restarting PHP worker: if PHP itself crashed (an extension conflict, a bad update, a corrupted process), the request behind it gets no response at all.
- Bad .htaccess rewrite loop: a redirect loop or malformed rewrite rule can occasionally surface as a gateway error rather than a redirect error. Rename
.htaccessto.htaccess.baktemporarily to test.
If you're on WordPress and the symptoms line up with a broken plugin or theme rather than a slow one, work through fixing the WordPress white screen of death: the plugin-isolation steps there (disable all, re-enable one at a time) apply just as well when the failure mode is a gateway error instead of a blank page.
Narrowing down which is happening
A quick way to tell time-based from crash-based failures: reload the page and note how long it hangs before the error appears. A request that hangs for 30, 60, or 90+ seconds before failing is a timeout, raise or fix the slow operation. A request that fails almost instantly is a crash, check the error log for a fatal error or process failure at that exact timestamp.
If the page works sometimes and fails other times under the same conditions, suspect a resource limit being hit intermittently under load, such as PHP workers maxing out during traffic spikes, rather than a single broken script.
When to contact support
If you've confirmed the origin (not Cloudflare) is timing out or crashing, checked the error log, and still can't identify the cause, or if disabling Cloudflare proxy isn't fixing a Cloudflare-side 502, open a ticket from the portal under Support → New ticket. Include the exact URL, roughly when it happens, and whether you tested with Cloudflare proxy on and off. That last detail alone saves a full round of back-and-forth.