Walk through the difference between HTTP status codes 500, 502, 503 and 504. For each one, say who is failing and what the code tells the caller.
answer
- 500 = I broke
- 502 = upstream gave garbage
- 503 = up but not serving, Retry-After
- 504 = upstream too slow
- 502/504 always come from the middle hop
basics
~20 s500: the origin server hit an unhandled error. 502: a gateway got an invalid or unusable response from upstream. 503: the server is reachable but temporarily unable to serve. 504: a gateway timed out waiting for upstream.
solid answer
~50 sAll four are 5xx, so the server side takes the blame and the request itself is presumed valid. - **500 Internal Server Error** — a generic unhandled failure inside the origin: an exception, a bad query, a null dereference. It says "I broke" and nothing more. - **502 Bad Gateway** — emitted by an intermediary (proxy, load balancer, CDN). It reached upstream but got something unusable: connection refused or reset, a malformed or truncated response, protocol garbage. - **503 Service Unavailable** — the server is up but deliberately not serving right now: overload, exhausted pools, draining during a deploy, an open circuit breaker, maintenance. It is explicitly temporary and is the code that pairs naturally with `Retry-After`. - **504 Gateway Timeout** — also from an intermediary: upstream accepted the connection but did not answer within the configured timeout. Operationally, 502 and 504 point at the hop between proxy and origin, 500 points at origin code, and 503 points at capacity or lifecycle.
code
http · 6 linesHTTP/1.1 504 Gateway Timeout
Server: nginx
Date: Tue, 12 Aug 2026 10:14:22 GMT
Content-Type: text/html
Content-Length: 167
Connection: keep-alivego deeper
Recall the four codes and their one-line meanings, and that 5xx blames the server while 4xx blames the client.
Explain which component emits each code, name concrete causes for 502 versus 504, and know that 503 is the one that carries Retry-After.
Use the codes as a triage signal — map a spike of each to the layer to investigate — and reason correctly about retry safety and possible partial side effects.
Frame it as an observability and contract decision: what each service is required to emit under overload versus defect, how that drives client retry and circuit-breaker policy, and how error budgets are attributed across hops.
## Why the class matters before the code HTTP status codes are grouped by their first digit. The 5xx class means the server is aware it has erred or is incapable of performing the request; the request itself is presumed well-formed. That is the fundamental split from the 4xx class, where the client sent something wrong. The practical consequence: a 4xx normally means "do not send that again unchanged", while a 5xx often means "the same request might succeed later". Within 5xx, the individual code is a blame assignment — it tells you which component to go look at. ## 500 Internal Server Error 500 is the catch-all. It is what a framework returns when an exception escapes your handler. It carries no diagnostic information to the client by design — leaking a stack trace in a 500 body is an information-disclosure bug. Because 500 is generic, a spike of 500s almost always means "go read the origin's application logs"; the code itself will not narrow it down. A 500 is also, importantly, ambiguous about side effects. The request may have been half-applied — a row written before the failure, a message published. Clients must not assume nothing happened. ## 502 Bad Gateway 502 is only meaningful from an intermediary: a reverse proxy, an API gateway, a load balancer, a CDN edge. It means the intermediary acted as a gateway, forwarded the request, and could not obtain a valid response. Real causes: the origin process is not listening (connection refused), the origin crashed mid-response (connection reset), the origin returned bytes that are not valid HTTP, or a response header block exceeded the proxy's buffer limits. In every case the failing hop is between the proxy and origin, not the client. A useful mental test: if your application code never ran, the caller should not be seeing 500 — 502 is the honest code. ## 503 Service Unavailable 503 says: I am here, I understand you, I am choosing not to serve right now, and this is temporary. Legitimate triggers include load shedding when a queue or thread pool is saturated, a health check failing so the instance is draining, a graceful shutdown during a rolling deploy, a tripped circuit breaker in front of a sick dependency, and planned maintenance. 503 is the only 5xx that routinely carries `Retry-After`, because it is the only one where the server has a defensible opinion about when to come back. A load balancer with zero healthy backends typically synthesizes a 503 as well — there is nothing to forward to, which is different from forwarding and getting garbage. ## 504 Gateway Timeout 504 is the intermediary's timeout. The connection to upstream succeeded, the request was sent, and no complete response arrived before the proxy's read timeout expired. The classic driver is a slow dependency behind the origin — a locked database, a saturated downstream, a request doing far more work than the timeout budget allows. 504 is the most dangerous code for correctness reasoning: the origin may still be working on the request and may complete it after the client has already given up. Blind retries on 504 for a non-idempotent operation are how you get duplicate charges and duplicate orders. ## Reading them as a signal A quick triage table candidates should be able to produce: - Mostly 500 → origin application defect; read origin logs and traces. - Mostly 502 → origin is crashing, restarting, or not listening; check process health and deploy timing. - Mostly 503 → capacity, health checks, or lifecycle; check pool saturation, autoscaling and rollout state. - Mostly 504 → latency, not availability; check dependency latency and timeout budgets down the chain. ## Retry semantics 503 with `Retry-After` is the clearest retry invitation. 502 is usually retryable because the request very likely never reached application logic. 500 and 504 are the risky ones: application code did run and may have committed. The safe rule is that retry safety comes from the method's idempotency and any idempotency mechanism you built, not from the status code alone — the status only tells you whether retrying has any hope of succeeding.
- Is it safe for a client to automatically retry a 502 or a 504?A 502 is usually safe because the response was invalid or the connection failed, which strongly suggests application logic never completed — though it is not a guarantee. A 504 is the opposite: the origin accepted the request and may still be processing it, so a retry can duplicate the effect. Retry safety ultimately comes from the method being idempotent or from an idempotency mechanism you built, not from the status code.
- Your application logs show a clean 200 for a request, but the caller received a 502. How is that possible?The origin began a valid response and then the connection between proxy and origin broke — the process was killed mid-write during a deploy, the response exceeded the proxy's header buffer, or a keep-alive connection was closed by the origin at the moment the proxy reused it. The application considered the request handled and logged 200 before the bytes reached the proxy intact. This class of bug is usually found by correlating proxy access logs and origin logs on a shared request id.
- When should application code return 500 versus 503?Return 500 when the failure is a defect you did not anticipate — an escaped exception, corrupt state, a bug. Return 503 when the unavailability is a known, temporary, capacity- or lifecycle-driven condition you are deliberately signalling: shedding load, draining, an open circuit breaker, or maintenance. The difference is actionable: 503 invites the caller back, 500 tells them the attempt is unlikely to help until someone fixes something.
Ordering at a restaurant: 500 is the kitchen setting the dish on fire; 502 is the waiter coming back with an unreadable slip from the kitchen; 503 is the host saying "we're full, try in 20 minutes"; 504 is the waiter giving up after the kitchen never plated anything.
saying these in an interview costs you the question
- Saying 502 and 504 are "the same thing, a proxy error" without distinguishing invalid response from timeout.
- Claiming every 5xx is safe to retry because "the request never went through".
- Returning 500 for planned maintenance or overload instead of 503.
- Putting exception messages or stack traces into 500 response bodies.
- Asserting only the origin server can emit 5xx, when 502/503/504 are typically synthesized by intermediaries.