HTTP 500 vs 502 — Internal Server Error vs Bad Gateway Comparison
http 500 vs 502: 500 is your application crashing, 502 is your reverse proxy unable to reach the upstream. Learn the debugging workflow for each.
Quick Cheat Sheet
| Aspect | 500 Internal Server Error | 502 Bad Gateway |
|---|---|---|
| Who failed? | The application itself | The upstream behind a proxy |
| Issued by | The origin server | A reverse proxy / gateway / load balancer |
| Likely cause | Code bug, unhandled exception | Backend dead, network issue, garbled response |
| Where to look first | Application logs | Proxy logs first, then backend |
What Each Code Means
500 Internal Server Error (RFC 9110 § 15.6.1) is the catch-all "something blew up inside my code" response. An unhandled exception, a divide by zero, a missing template — anything where the application itself produced no useful response.
502 Bad Gateway (RFC 9110 § 15.6.3) is fundamentally different: it's sent by a proxy/gateway (Nginx, ALB, Cloudflare, API Gateway) when it received an invalid response from the upstream server, or couldn't reach it at all.
The Mental Model
If your architecture is:
Browser → Nginx → Node.js app
- Node throws an exception, returns 500 → user sees 500 from Nginx, your app logs the stack trace.
- Node process crashed, Nginx can't connect → user sees 502 from Nginx, your app has no logs at all for this request.
The presence (500) or absence (502) of application logs is often the fastest way to tell them apart.
Common Causes of 502
- Node/Python/Ruby process died (segfault, OOM kill, crash loop)
- Upstream returned malformed HTTP (response truncated, bad status line)
- Connection refused on the upstream port (process not listening)
- Connection reset mid-response
- TLS handshake failure between proxy and backend
Common Causes of 500
- Unhandled exceptions in route handlers
- Database query errors that aren't caught
- Template rendering failures
- Out-of-memory in the application, but the process recovers
- Misconfigured environment variables
Debugging Workflow
For 500:
- Tail your application logs and search for the request ID
- Look for the exception/stack trace
- Reproduce locally with the same input
For 502:
- Check proxy access logs first — is the upstream reachable?
- Check upstream process status (is it running? memory pressure? CPU?)
- Look at upstream logs for the request — if there are none, the proxy never reached you
- Check for TCP-level issues with
tcpdumpor stack traces from the proxy
CDN-Specific Notes
- Cloudflare uses 520-526 for various proxy-failure subtypes. 502 from Cloudflare specifically means "upstream server returned an invalid response."
- AWS ALB returns 502 when target group health checks fail or targets close the connection unexpectedly.
- Vercel returns 502 when serverless functions crash before producing a response.
Why It Matters
Misdiagnosing 500 vs 502 wastes hours: you'll grep app logs for a 502 and find nothing, then assume the bug is somewhere else. Always check which component issued the response first.
Real-World Use Case
If your Vercel-hosted Next.js Route Handler hits an unhandled rejection in async code, you'll see 500 with the error in Vercel logs. If your Lambda function crashes during cold start before invoke, you'll see 502 from API Gateway with nothing in your function logs — the failure is in the gateway-to-Lambda integration.
Look Up Any Status Code
Related Comparisons
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.
HTTP 503 vs 500 — Service Unavailable vs Internal Server Error Comparison
http 503 vs 500: 503 is intentional (overload, maintenance) and includes Retry-After, while 500 is an unintentional crash. Why the right choice affects monitoring and SLAs.
HTTP 502 vs 503 — Bad Gateway vs Service Unavailable Comparison
http 502 vs 503: 502 is an *unintentional* upstream failure detected by a proxy, 503 is an *intentional* unavailability signal from the application. Why this distinction matters for incident triage.
HTTP 408 vs 504 — Request Timeout vs Gateway Timeout Comparison
http 408 vs 504: who timed out, the client or an upstream server? Learn the difference, when each is returned, and how to debug timeouts in Nginx, ALB, and Cloudflare.