Przejdź do treści głównej

Guides / http-status-codes

502 Bad Gateway: What Broke Behind the Proxy and How to Find It

A 502 Bad Gateway means a proxy in front of your site asked the backend for a response and got something invalid, or nothing at all. The proxy is working correctly; it is reporting that whatever sits behind it is down, crashing or speaking the wrong protocol.

Who returns a 502 and why

RFC 9110 defines 502 for a server acting as a gateway or proxy that received an invalid response from an inbound server it accessed while trying to fulfill the request. Every modern stack has at least one such hop: nginx or Apache in front of an application server, a load balancer in front of a fleet, a CDN in front of your origin, or all three.

That layering is the key to reading a 502. The component that answered is healthy enough to generate an error page. The component behind it is not. So a 502 always splits your stack into a working half and a broken half, and your job is to work out where the boundary is.

Its neighbors say something narrower. A 504 Gateway Timeout means the backend was reachable but too slow. A 500 means the backend itself ran and threw an error. A 502 means the backend gave a bad answer or no answer at all. The full comparison is in the 5xx overview.

Common causes

  • The backend process is not running. A crashed app server, a stopped PHP-FPM pool, a container that exited or failed its health check. The proxy connects to a port nobody is listening on.
  • The backend crashed mid-request. An out-of-memory kill or a segmentation fault closes the connection before the response headers are complete.
  • Wrong upstream address or port. A config that points at the old port after a change, or at a host that no longer resolves.
  • Protocol mismatch. The proxy speaks plain HTTP to a port expecting TLS, or the reverse. The bytes are unparseable, so the proxy calls the response invalid.
  • Response headers too large. An oversized cookie or an unusually long header exceeds the proxy's buffer, and the response is rejected rather than passed on.
  • Keep-alive mismatch. The proxy reuses an idle connection that the backend has already closed, producing sporadic 502s under otherwise normal load.
  • Restarts and deploys. Any window where the old process has stopped and the new one is not yet accepting connections.
  • All backends unhealthy. A load balancer with no passing members has nowhere to send the request.

Reading the proxy log, which usually ends the investigation

The status code is generic, but the proxy log line is specific. With nginx, these are the messages worth recognizing:

[error] connect() failed (111: Connection refused) while connecting to upstream,
        upstream: "http://127.0.0.1:8080/"

[error] upstream prematurely closed connection while reading response header
        from upstream

[error] recv() failed (104: Connection reset by peer) while reading response
        header from upstream

[error] upstream sent too big header while reading response header from upstream

[error] no live upstreams while connecting to upstream

Each points somewhere different:

  • connect() failed (111: Connection refused). Nothing is listening on that address and port. The backend is stopped, bound to a different interface, or on a different port than the config says.
  • upstream prematurely closed connection. The backend accepted the request and then died or hung up before finishing the response. Look for crashes, out-of-memory kills or a worker timeout inside the application, not at nginx.
  • connection reset by peer. Similar, but the connection was actively reset. Often a firewall in between, or a backend that closed a pooled connection the proxy still considered open.
  • upstream sent too big header. A buffer size issue in the proxy, not a fault in the backend. The response is valid but bigger than the proxy is configured to hold.
  • no live upstreams. Health checks have marked every backend down.

How to fix it

  1. Test the backend directly, bypassing the proxy. From the proxy host, request the upstream address itself:
    curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/
    A 200 here with a 502 on the public URL means the fault is in the proxy configuration or the link between the two. A refused connection means the backend really is down.
  2. Check the backend is running and listening on the address the proxy expects. Binding to 127.0.0.1 when the proxy dials a container address is a frequent cause.
  3. Read the proxy error log and match the message to the list above before changing any configuration.
  4. Then read the backend log. A crash, an out-of-memory kill or a worker timeout at the same second confirms the "prematurely closed" case. Silence points back at connectivity.
  5. Verify the upstream address, port and scheme in the proxy config, especially after a migration or a container rebuild.
  6. Raise proxy header buffers if the log says the header was too big, and separately find out why the header grew.
  7. Make deploys overlap. Start the new process, wait for it to pass a health check, then drain and stop the old one. Health-gated rolling updates remove the restart window that causes deploy-time 502s entirely.

Catching a 502 that lasts twenty seconds

Deploy-time and crash-loop 502s are short. A backend restarts, errors for twenty seconds and recovers, so by the time anyone checks the site is fine and there is nothing left to look at. A scheduled HTTP check running continuously records those windows with timestamps, which turns "it was briefly weird this morning" into a pattern you can correlate with deploys and restarts. A 502 can also come from a CDN edge rather than your origin, so checking from several regions separates a global backend failure from an edge problem affecting part of your traffic, which is what distributed availability monitoring is for.

Check it now

Run the free check against your own site - no account needed.

HTTP check

Monitor this permanently

Get alerted the moment it breaks: HostTracker checks from 300+ locations and notifies you by email, SMS, Slack, Telegram and more.

HostTracker features