502 Bad Gateway: What It Means and How to Fix It
A 502 Bad Gateway means the server in front of your site got an unusable reply from the one behind it. Find the culprit — origin, proxy, or host — and fix it.
A 502 Bad Gateway is a message from the middle of your stack, not the end of it. One server — a reverse proxy, load balancer, or CDN edge — asked another server for your page, and the answer it got back was unusable. So it returned an error instead of your site.
That detail matters more than the number. The proxy is telling you it is fine and something behind it is not. Your web server may be down, the application process may have crashed, or the two may be speaking to each other incorrectly. The page visitors see is usually a plain white screen with the words 502 Bad Gateway and the name of the proxy that produced it — nginx, cloudflare, or your host’s own gateway.
What actually happens during a 502
Your request passes through at least two programs before it becomes a page:
- The proxy — nginx, Apache in proxy mode, HAProxy, or a CDN edge. It accepts the visitor’s connection and holds it open.
- The upstream — the process that generates the page: PHP-FPM, Node, Python, a Java application server, or a container behind a load balancer.
The proxy opens a connection to the upstream and waits for a well-formed HTTP response. A 502 is raised when that response never arrives in a usable form. The connection may have been refused, reset, timed out, or answered with headers the proxy cannot parse.
The most useful first question is therefore not “why is my site broken” but “which of those two is broken?”
Is it your site or your host?
Check whether the error is constant or intermittent, and whether it is only you.
- Everyone sees it, all the time. Your upstream process is down or unreachable. This is yours to fix, or your host’s if you are on managed hosting.
- Intermittent, a few requests in every hundred. Something behind the proxy is dying and restarting under load — usually a memory limit, a crashed worker, or one bad upstream node in a pool.
- Only you, or only from one network. A CDN edge node, your local DNS, a corporate proxy, or your own VPN is at fault. The site is likely fine for everyone else.
To separate the last case from the others, load the site on a phone over mobile data instead of Wi-Fi, and run the domain through the website checker. That check runs from an independent server, so a clean result there plus an error on your screen points at your network rather than your site.
Causes, and how to tell them apart
| Symptom | Most likely cause | Where to look |
|---|---|---|
| 502 on every request, immediately | Upstream process not running, or wrong upstream address/port | Proxy config, process manager |
| 502 after a delay, under traffic | Upstream timed out or was killed — memory limit, OOM killer | Web server and kernel logs |
| 502 on one URL only | A specific script crashes or exceeds limits | Application log for that route |
| 502 intermittently, one node | One unhealthy backend in a load-balancer pool | Health checks, pool status |
| 502 with a TLS error in the log | Proxy and upstream disagree on SSL | Proxy upstream / proxy_ssl settings |
| 502 right after a deploy | New build is missing, crashing, or listening on the wrong port | Deploy log, container status |
The upstream process is not running
The most common cause by a wide margin. PHP-FPM crashed, the Node process exited, or the container stopped. The proxy keeps listening, so the port is open and the site looks alive, but nothing is there to answer.
Fix: restart the upstream and read why it stopped. systemctl status php8.2-fpm, pm2 status, or your host’s process panel. If it restarts and dies again within minutes, go to the memory cause below — the crash is a symptom.
The upstream ran out of memory
A process that hits its memory ceiling is killed by the operating system. dmesg | grep -i "killed process" shows the OOM killer’s work, and journalctl -u php8.2-fpm shows PHP-FPM’s own “child exited on signal 9” lines. Each request that arrives before the process is restarted produces a 502, which is why this pattern looks intermittent and load-dependent.
Fix: raise the memory limit and reduce the per-worker footprint. With PHP-FPM, pm.max_children multiplied by memory_limit must fit inside the server’s RAM; the single most common misconfiguration is max_children set far too high for the box, so workers compete and the kernel starts killing them.
The proxy is pointing at the wrong place
A configuration change, a migration, or a container that moved IP address leaves the proxy knocking on a door nobody answers. This produces an instant 502 on every request with a connect() failed (111: Connection refused) line in the proxy error log.
Fix: confirm the upstream host and port in the proxy config match what the application is actually bound to. A process listening on 127.0.0.1:3000 is not reachable from a proxy in another container; it needs 0.0.0.0.
The proxy’s timeout is shorter than the upstream’s work
Long reports, exports, image processing, and slow database queries can legitimately take longer than the proxy is willing to wait. This one is easy to misread, because a fast page loads fine and one heavy endpoint always fails.
Fix: raise the proxy timeout for that route — proxy_read_timeout in nginx, ProxyTimeout in Apache — and separately reduce the work being done. Raising the timeout without fixing the slow query just moves the failure to a bigger number. If the failure is a timeout rather than a refusal, read 504 Gateway Timeout instead; the two are frequently confused.
TLS mismatch between proxy and upstream
When the proxy speaks HTTPS to an origin expecting HTTP, or presents a certificate the origin rejects, the handshake fails before any response exists, and the proxy reports it as a 502. Look for SSL_do_handshake() failed or upstream prematurely closed connection in the log.
Fix: make the protocol match. If the origin is behind Cloudflare’s “Full” SSL mode but only serves HTTP on port 80, use “Flexible”; better, install a real certificate on the origin and use “Full (strict)”.
Malformed response headers
An upstream that returns headers larger than the proxy allows, or headers with illegal characters, gets its response discarded. upstream sent too big header in the nginx log is the giveaway, and it usually arrives alongside a growing cookie — a plugin or session handler appending to a cookie on every request until the header block exceeds the buffer.
Fix: raise proxy_buffer_size and large_client_header_buffers, then fix the runaway cookie. Raising the buffer alone defers the problem.
Cloudflare and CDN-specific 502s
A CDN adds a third machine to the chain, and its 502 page usually names the cause directly:
- Error 502 with “Web server is down” — the origin refused the connection. The origin is not running, or a firewall is blocking the CDN’s IP ranges.
- Error 502 with “Connection timed out” — the origin accepted nothing within the CDN’s limit. Usually the origin is overloaded or a security group is silently dropping packets.
- Error 502 with “SSL handshake failed” — the origin’s certificate is invalid, expired, or does not cover the hostname. This is the single most common CDN 502, and it is a certificate problem wearing a gateway costume.
If your site is served through a CDN and only some visitors see 502s, suspect a stale or unhealthy edge node before you touch the origin.
How to confirm the fix
A 502 is a symptom that clears the moment the upstream answers correctly, which makes it easy to declare victory too early. Confirm all three:
- The upstream process is running and has stayed up for longer than it previously survived.
- The proxy error log has stopped adding 502 lines — check the timestamps, not the file size.
- A request from outside your network succeeds, not just one from the server itself.
curl -sI https://example.comfrom a separate machine removes every local variable.
Then watch it. A 502 that recurs weekly is a memory leak or a growth trend, and each occurrence is a window where every visitor, and every search engine crawler, is turned away.
Why this is worse than it looks
An error page is not a neutral event. Visitors leave, and some do not come back. Crawlers that repeatedly meet a 502 start slowing down and may drop the page from the index entirely — and unlike a 404, a 502 tells the crawler “try again later,” so the damage accumulates quietly rather than resolving itself.
That is the case for watching the status code rather than waiting for a customer to mention it. SitesRadar’s free plan checks one site on a schedule and emails you when it starts returning 5xx errors, alongside uptime, SSL expiry, broken links, and DNS. If you look after several client sites, the client site down triage checklist is the order to work through when the alert lands.
FAQ
Is a 502 error my fault or my host’s? If the upstream process is not running or was killed for using too much memory, it is configuration you control. On managed hosting, the upstream may be the host’s responsibility — send them the timestamp and the URL, and ask what the origin returned.
What is the difference between 500, 502, 503, and 504? A 500 means the application was asked to build the page and failed. A 502 means the proxy got an unusable answer. A 503 means the server is deliberately or temporarily unable to handle the request. A 504 means the upstream was too slow and the proxy gave up waiting. The gateway three usually appear on the same proxy page.
Can a 502 fix itself? Yes, if the upstream is restarting on a loop. That is not a fix — it is a crash cycle with a gap between restarts. Treat a self-healing 502 as a memory or stability bug that is still there.
Will a 502 hurt my search rankings? Repeated 502s can. Crawlers slow down and may drop the URL. A brief outage is recovered from quickly; a recurring one is not.
Does a 502 mean the site was hacked? Rarely. It is almost always a process, memory, configuration, or certificate problem. Check the origin logs before assuming an attack.