HTTP 502 vs 504 — Bad Gateway vs Gateway Timeout Comparison

http 502 vs 504: both come from your reverse proxy, but 502 means the upstream returned a bad response while 504 means it didn't respond in time. Nginx, ALB, Cloudflare debugging tips.

5xx

502

Bad Gateway

View full 502 page →

5xx

504

Gateway Timeout

View full 504 page →

Quick Cheat Sheet

Aspect 502 Bad Gateway 504 Gateway Timeout
Upstream responded? Yes, but invalidly (or connection failed) No — exceeded timeout
Cause Backend crash, malformed response, conn reset Slow query, blocked thread, hung process
Fix priority Restart / fix backend Tune timeouts AND fix slow path
Common Nginx config proxy_pass upstream issues proxy_read_timeout exceeded

The Distinguishing Factor: Did the Upstream Respond?

Both 502 and 504 come from a proxy/gateway, not from your application directly. The difference is what the upstream did:

  • 502 Bad Gateway: the upstream returned something, but the proxy couldn't make sense of it (malformed HTTP, unexpected EOF, connection reset, or refused connection).
  • 504 Gateway Timeout: the upstream simply didn't respond within the configured timeout. Maybe it's slow, maybe it's hung, maybe it's gone.

Real-World Triggers

For 502:

  • Backend process crashed mid-request (segfault, panic, OOM)
  • Backend closed the connection without sending a response (e.g., process.exit() in middle of handler)
  • Upstream sent invalid HTTP headers (rare, usually a buggy custom server)
  • TLS handshake failure between proxy and backend

For 504:

  • A slow database query holds up the request (SELECT without an index)
  • The backend is waiting on a third-party API that's slow
  • Lambda cold start exceeds API Gateway integration timeout (29s for REST APIs)
  • Thread pool exhausted, request queued behind others
  • Backend is in a deadlock or infinite loop

Timeouts in Common Stacks

Layer Default Read Timeout
Nginx proxy_read_timeout 60s
AWS ALB idle timeout 60s (configurable up to 4000s)
AWS API Gateway REST integration 29s (hard cap)
Cloudflare Free 100s
Vercel serverless 10s (Hobby), 60s (Pro), 900s (Enterprise)

If your backend ever takes longer than these, the user gets 504 even if the work completes successfully on the backend.

Debugging Workflow

For 502:

  1. Check the upstream process — is it running? Crash logs?
  2. curl localhost:PORT/path directly from the proxy host — what comes back?
  3. Look at proxy error logs, not access logs (Nginx: /var/log/nginx/error.log)
  4. Check for upstream prematurely closed connection errors

For 504:

  1. Check application logs for the request — does it appear and complete? In how long?
  2. If the backend log shows the request finishing in 75s but the proxy timeout is 60s, the fix is either to speed up the backend or raise the timeout
  3. If the backend has no record of the request, it's probably 502 territory after all
  4. Check database slow-query logs

Don't Just Raise Timeouts

A common but bad fix for recurring 504s is to crank up proxy_read_timeout to 600s. This often masks the real problem (a slow query) and creates new issues (connections held open, thread pool exhaustion). Profile and fix the slow path instead.

Cloudflare's Variants

Cloudflare uses 520-526 for various edge-to-origin problems:

  • 520: empty response
  • 521: web server is down
  • 522: connection timed out
  • 523: origin unreachable
  • 524: a timeout occurred (the closest analog to 504)

Real-World Use Case

A Cloudflare-fronted API showing 504 for one specific endpoint usually means a slow DB query — first profile the query plan, add an index, and only then consider raising Cloudflare's timeout. A 502 from AWS ALB right after deploying a new version often means the new container is crashing on startup; check ECS task health and logs.

Look Up Any Status Code

Browse all status codes →