Operations · 4 min read

Why a deployment returns 502 Bad Gateway

Trace a 502 from proxy to app through startup, port binding, health, timeouts and logs, and find where the request stopped before you change any code.

Published

What a 502 actually tells you

HTTP 502 means a gateway received an invalid response from an upstream server. In an app deployment, the gateway is often a reverse proxy or load balancer and the upstream is your process. This narrows the search: the browser reached an edge, but the edge could not complete a valid exchange with the app.

Begin with a timestamp and one failing URL. Compare the proxy error at that time with application logs. A deployment may have built successfully and still fail because the process exited, listened on the wrong port, timed out, or closed a connection before responding.

Diagnose by where the request stopped

Diagram of a 502 error. A browser asks for a URL. A gateway, which is a proxy or load balancer, answers 502 Bad Gateway because your process gave no valid reply. Below, four cases show where the request stopped and what to look at: no process running (the first startup error), running but no connection (the port, and binding to 0.0.0.0), works locally but fails live (health path and network rules), and only slow routes fail (upstream timeout and busy workers).
A 502 comes from the gateway. Where the request stopped tells you what to look at.
  • No process: inspect the first startup exception. Common causes are missing runtime variables, import failures, a failed migration, or out-of-memory termination.
  • Process running, no connection: compare the expected target port with the actual listener. In a container, 127.0.0.1 binding can make a service unreachable from the proxy; use 0.0.0.0.
  • Connection works locally, fails live: inspect health check path, network rules, and whether the process survives after startup.
  • Fast routes work, slow routes fail: inspect upstream timeout, request duration, and worker saturation. Move long work to a job queue instead of raising every timeout.
bash
docker run --rm -e PORT=3000 -p 3000:3000 my-app:local
curl -v http://127.0.0.1:3000/health/ready

This local test isolates image startup and port binding. It does not test the platform's routing or secrets, so repeat the readiness request against the platform URL and compare logs from the same release.

Do not treat every 502 as a deployment bug

A shared dependency outage may cause the app to close or time out upstream connections. CPU starvation can do the same under load. If a 502 began only after traffic grew, correlate it with memory, CPU, connection pool waits, and latency rather than changing DNS records.

Once fixed, add a check that would have caught the specific failure: a clean-container startup test, a readiness probe, or a post-deploy request to a real route. The goal is to turn a one-off incident into a reproducible signal.

Read the time pattern

An immediate 502 after every deploy suggests startup or port configuration. A 502 only during a spike suggests exhausted workers, memory pressure, or upstream connection limits. A 502 only on one route suggests that route's dependency or timeout. Plot failures by release, route, and minute before changing infrastructure.

When the process exits, capture the first exception after startup. Later proxy errors are symptoms. If the logs show an out-of-memory kill, examine memory growth and limits; increasing the limit may buy time but does not explain a leak. If the logs are empty, inspect platform events for image-pull, permission, and health-check failures that happened before your process could log. On ProductEcho, a container app's Logs tab keeps seven days, and your agent can run diagnose_application to get the status, the most repeated recent errors and suggested next steps in one call. If the build itself failed, get_build_logs returns the end of its output.

After a fix, write down a minimal reproduction: container command, required environment names, failing URL, and expected response. Turn it into a smoke test or startup check. This makes the next incident faster to diagnose and prevents the same 502 from returning under a different release.

Further reading

MDN's 502 definition describes the gateway semantics. NGINX proxy module documentation covers upstream timeouts and connection behavior.