Loading...

Basics · 8 min read

502 Bad Gateway: what it means and how to fix it

A 502 is not your visitor's fault and it is rarely the CDN's. It means the machine in front of your site asked your server for the page and got something it could not use. This guide is written from the proxy side: what the edge actually saw, and which of the four causes it was.

Güncellendi

502 Bad Gateway: what it means and how to fix it

Who is actually saying "bad gateway"

The status code is generated by whatever sits in front of your application, not by the application itself. A request travels visitor → CDN edge → your origin server → (often) your app server, and any hop that proxies to the next one can produce a 502 about the hop after it. That matters because the page you are looking at is written by the proxy: if your application had answered at all, even with an error, you would be looking at your own 500 page instead.

So a 502 is a statement about a conversation that failed, and the useful question is always the same: which two machines were talking, and what went wrong between them?

502 vs 504: the distinction everyone skips

These two get used interchangeably in blog posts and they should not be.

504 Gateway Timeout means the proxy connected fine and then waited. Your origin accepted the request and never finished answering within the timeout. The usual causes are a slow database query, an external API call with no timeout of its own, or a process pool that is full and queueing.

502 Bad Gateway means there was no usable answer to wait for. The connection was refused, or it was accepted and then dropped, or the bytes that came back were not a valid HTTP response.

If you are seeing 504s, look at how long your application takes. If you are seeing 502s, look at whether your application is answering at all.

Cause 1 — the origin refused the connection

The proxy opened a TCP connection to your origin and got an immediate refusal or no route at all. Nothing was listening on that port, or a firewall dropped the packet.

What produces it in practice: the web server or container is stopped; it is listening on 127.0.0.1 instead of the public interface; the port in your origin settings does not match the port the service is on; a host firewall or security group blocks the CDN's IP addresses.

How to confirm. From outside your own network, ask the origin directly and send the Host header your site uses — an origin that serves several sites will otherwise answer for the wrong one or refuse:

curl -sI -H "Host: example.com" http://ORIGIN_IP/

If that curl fails the same way, the CDN is reporting the truth and the fix is on the origin. If that curl succeeds while the edge sees a refusal, the difference is almost always a firewall rule that allows you and not the edge.

Cause 2 — the origin closed the connection early

The connection was accepted, then died before a complete response came back. This is the most common 502 on PHP and Node stacks under load.

What produces it: a PHP-FPM pool with every worker busy, so new connections are accepted by the kernel backlog and then dropped; a worker that hit its memory limit and was killed mid-response; an application process that crashed on that specific request; a keepalive mismatch where the origin closes idle connections earlier than the proxy expects to reuse them.

How to confirm. Look at the origin's own error log at the moment of the 502 — this is the one case where the origin has a clear story to tell. A Premature end of script headers, a segfault line, or a PHP-FPM server reached pm.max_children warning names the cause outright. If the 502s cluster at traffic peaks rather than appearing randomly, you are looking at pool exhaustion, not a bug.

Cause 3 — the TLS handshake to the origin failed

If the proxy talks to your origin over HTTPS, the handshake can fail for reasons that have nothing to do with the certificate your visitors see. The edge holds the public certificate; the connection behind it is a separate conversation with its own certificate.

What produces it: the origin certificate expired and nobody noticed because the public certificate is auto-renewed; the origin serves several names and needs SNI to pick the right one; the origin only accepts TLS versions or ciphers the proxy does not offer; the certificate covers www.example.com but the proxy connects asking for example.com.

How to confirm.

openssl s_client -connect ORIGIN_IP:443 -servername example.com </dev/null | head -20

Read the chain and the dates. On cdn.com.tr the edge sends SNI to the origin, so a certificate that is valid for the hostname you configured will negotiate; one that is only valid for the default vhost will not.

Cause 4 — the response was not valid HTTP

Rarer, and satisfying to find. The origin answered, but what came back could not be parsed: a header line longer than the proxy's buffer, a stray line of output printed before the headers (a PHP warning, a byte-order mark in an include file), a response claiming Content-Length that does not match the body, or a plain-text crash dump served on port 443.

How to confirm. Fetch the origin directly and look at the raw bytes rather than a rendered page:

curl -sv -H "Host: example.com" http://ORIGIN_IP/ -o /dev/null

If the first line back is not HTTP/1.1 ..., you have found it. The fix is in your application or its output buffering, and the proxy was right to refuse it.

What to do when a CDN is in front

A CDN changes the diagnosis in two useful ways.

Cached pages keep serving. A visitor asking for something already in the edge cache gets it even while the origin is down, so a partial 502 — some pages broken, others fine — usually means the origin is up but failing on the uncached paths, which are typically the dynamic ones.

You gain a second vantage point. The edge sees your origin from the outside, continuously. If the edge reports 502 and your own browser reaches the origin, the difference between those two requests is the bug: a firewall that allows your IP, a DNS record that points somewhere else for you, or a certificate that only matches the name you happen to be using.

On cdn.com.tr, delivery rules let you keep a longer cache TTL on the paths that can tolerate it, which is what turns an origin incident into a degraded site instead of a dead one. That is worth configuring before you need it, not during.

The 502 that is not about your origin at all

One case deserves naming because it wastes hours. If your DNS points at a CDN edge but the hostname has not been configured on that edge yet, you are not going to get a 502 — you will get a 503 with a page saying no service is configured for this domain. That is the edge telling you it has no idea which origin to ask.

People see an error page immediately after changing DNS, assume the origin is broken, and start restarting services that were never involved. Check the status code first: 502 means the edge tried your origin and failed; 503 of that kind means the edge never had an origin to try.

502 Bad Gateway FAQ

Is a 502 my fault or the CDN's?

Usually neither — it is the origin's. The CDN reports the failure it experienced; it does not invent it. The exception worth checking is connectivity: if the origin firewall blocks the edge IP addresses, the origin is healthy for you and unreachable for the CDN, and the fix is an allow rule rather than anything on the application.

Why do I get a 502 only sometimes?

Intermittent 502s almost always mean capacity rather than configuration. A process pool that is full during peaks, a worker being recycled, or an origin that closes keepalive connections sooner than the proxy expects will all produce errors that come and go while a simple test from your laptop passes every time.

Does refreshing help?

It tells you something. If a refresh works, the failure is intermittent and you are looking at capacity or a specific worker. If every refresh fails identically, it is configuration — a refused connection, a wrong port, an expired origin certificate — and refreshing will not change it.

How do I tell a 502 from a 504 without the status code?

By how long you waited. A 504 makes you wait out the timeout, typically tens of seconds, because the proxy is genuinely waiting for an answer. A 502 usually arrives quickly, because a refused or broken connection fails fast.

Can I show my visitors something better than the default error page?

Yes, and you should. A CDN serves stale cached content or a branded error page instead of the proxy default, which turns an outage into a worse-than-usual experience rather than a broken one. Set it up before an incident, because during one you will not have the attention to spare.