Identify Your 5xx Error's Fault Tier: 500, 502, 503, 504
Work through which layer of your stack actually produced the failure before you pick a 5xx code, because each one points debugging to a different team. The 5xx class covers every situation where the server received and understood a request but could not process it due to a fault on the server side. Unlike 4xx errors, 5xx errors are not the client's fault: the same request may succeed on retry if the server condition resolves.
Yet the specific 5xx code matters: 500, 502, 503, and 504 each point to a different layer of the stack and a different team's responsibility, and picking the right one on the first attempt routes debugging efforts to the right place immediately. What follows surveys the four most common 5xx codes, explains when to use each, and covers how to monitor and alert on 5xx error rates effectively.1
Identifying the fault tier
Before choosing a 5xx code, identify which layer of the stack produced the failure, because each code corresponds to a distinct tier of the deployment architecture and routes debugging to a different team. Application code that crashes or throws an unhandled exception produces 500 Internal Server Error. A reverse proxy or load balancer that receives an invalid or empty response from an upstream application produces 502 Bad Gateway. A server that intentionally refuses requests because it is overloaded or undergoing maintenance produces 503 Service Unavailable: the server is functioning correctly but is applying backpressure to protect itself from further degradation.
Debugging by layer
Each 5xx code points to a different log source, so picking the right code on the first attempt saves an average of one to two hours of triage during a production incident. 500 points to application logs: search the application stack trace for the unhandled exception. 502 points to proxy logs and upstream health: check whether the upstream returned an empty or malformed response before the proxy forwarded it. 503 points to capacity metrics and maintenance schedules: confirm whether the server is applying backpressure intentionally. Misidentifying the fault tier delays resolution by sending developers to the wrong log source, which is why every operations runbook should include a status-code-to-log-source mapping table.
500 vs 502 vs 503 vs 504 decision tree
Four questions identify the correct 5xx code for a given failure. Walking through them in order prevents you from defaulting to 500 for every unexpected condition, which is a common anti-pattern that hides the real root cause of server-side incidents and makes post-incident reviews harder because the original error signal has been lost.
Did the application receive the request and execute code but threw an unhandled error? Use 500. Did a proxy receive a response from the upstream that was invalid, empty, or not parseable as HTTP? Use 502 Bad Gateway. Is the server intentionally refusing requests because capacity is exhausted or maintenance is in progress? Use 503 Service Unavailable with a Retry-After header. Did a proxy send a request to the upstream and wait for a response that never arrived within the configured timeout? Use 504 Gateway Timeout.
504 and 502 are both proxy-layer errors but with different root causes: 504 points to latency or performance issues at the upstream, while 502 points to an upstream crash or protocol error. Treating them as interchangeable in dashboards and alerts masks the distinct operational responses required: a 504 spike demands a performance investigation of the upstream service, whereas a 502 spike after a deployment strongly suggests a misconfigured health check or a broken upstream process.2
Monitoring and alerting on 5xx rates
Effective 5xx monitoring uses rate-based alerts rather than absolute counts, because the absolute count of 5xx responses is meaningless without knowing total request volume. A 500 rate above 0.1 percent of total requests is a meaningful threshold for most production APIs, though the right threshold depends on your baseline error rate and the tolerance defined by your error budget. Setting the threshold too low creates alert fatigue during normal traffic fluctuations, while setting it too high delays detection of genuine incidents.
Alert separately on each 5xx code rather than aggregating them into a single server-error metric: a 502 spike after a deployment points to a proxy configuration change, while a 503 spike points to capacity saturation. Use structured logging with request IDs so that each 5xx response in your dashboard links directly to the corresponding server log entry, which reduces the time an on-call engineer spends correlating client reports with internal logs during an active incident.
Aggregating all 5xx codes into a single "server error" metric obscures which layer of the stack is degrading. Tag each log event with the originating service, the upstream dependency name, and the HTTP method to make filtering and grouping possible in your monitoring tool. Without this granularity, a 502 spike from a misconfigured health check and a 504 spike from a slow database query look identical in a blended metric, yet they require completely different remediation steps: one demands a rollback of the proxy configuration, while the other requires a query optimisation or an index addition.
Circuit breakers and 503 responses in microservice architectures
Circuit breakers prevent cascading failures by stopping requests to a failing dependency before they exhaust your application's thread pool or connection pool. When a downstream service starts returning errors or timing out consistently, the circuit breaker opens and your service returns 503 Service Unavailable immediately, without forwarding the request to the failing dependency. This converts a slow degradation into a fast fail, which is easier to detect and handle than requests that stall for seconds before timing out.
Returning 503 from an open circuit, rather than 500, signals to the caller that the failure is temporary and expected to resolve. To stop a slow dependency from cascading into every endpoint, return 503 instead of 500 when the circuit opens. Include a Retry-After header on the 503 to indicate when the circuit will attempt to close again. A standard circuit breaker half-opens after a configured timeout, allowing one test request through. If the test succeeds, the circuit closes and normal traffic resumes; if it fails, the circuit reopens and the timeout resets.
Resilience4j and circuit breaker configuration in Spring Boot
Resilience4j is the standard circuit breaker library for Spring Boot applications. Configure a circuit breaker with a sliding window of 10 requests and a failure rate threshold of 50%: when more than 5 of the last 10 requests fail, the circuit opens. The @CircuitBreaker annotation on a service method automatically intercepts calls and redirects to a fallback when the circuit is open. The fallback method should build and return a 503 response, not throw an exception that would produce a 500.
Error budget and SLO monitoring for 5xx rates
Service Level Objectives express reliability as a percentage of successful requests over a time window. A 99.9% availability SLO means no more than 0.1% of requests can return 5xx responses. Every 5xx response burns a portion of your error budget: the total allowable failures before the SLO is breached. When your error budget is nearly exhausted, teams typically freeze non-emergency deployments and focus on reliability until the budget recovers at the start of the next window.
Setting up SLO monitoring for 5xx responses requires tagging each log event with the originating service, the HTTP method, and the status code class. Track the 5xx rate per service separately rather than aggregating across all services: a 5xx spike in one downstream service should not inflate the SLO for your API service. Tools including Datadog's SLO widget, Google Cloud Monitoring, and Grafana's SLO dashboards all support 5xx-rate-based SLOs with configurable burn rate alerts.3
Burn rate alerts for fast SLO degradation
A burn rate alert fires when the rate of SLO consumption is fast enough to exhaust the error budget before the SLO window ends. A 5xx rate of 2% with a 99.9% monthly SLO burns the budget in approximately 2.5 days rather than the full month. Multi-window burn rate alerts (a short window for fast detection and a longer window for sustained degradation) reduce false positives while ensuring the on-call team is paged early enough to prevent a full budget exhaustion.
Configuring the right burn rate thresholds requires understanding your typical traffic patterns. A service that receives 100 requests per second has a different baseline than one that receives 10,000, so the same absolute 5xx rate represents a different proportion of total traffic. Start with a multi-window configuration: a 5-minute window with a 14.4x burn rate threshold for fast detection of acute incidents, and a 1-hour window with a 6x threshold for sustained degradation. Tune these values after observing your service's normal 5xx variance for at least one full traffic cycle, because setting them too aggressively creates alert fatigue that trains the on-call team to ignore pages.
When to use this
Work through this guide the moment you are triaging a production 5xx incident. Use it to identify which layer of the stack is failing, which team should respond, and which logs to inspect first.
Examples
Application throws an unhandled NullPointerException
Return 500 Internal Server Error. Log the full stack trace and correlate it to the request ID. The client request was valid; the application code failed.
nginx receives a connection reset from the Node.js upstream
nginx returns 502 Bad Gateway to the client. Check nginx error logs for "upstream prematurely closed connection" and correlate with the application restart timestamp.
Application is shut down for a rolling deployment
Return 503 Service Unavailable with Retry-After set to the expected restart time. The load balancer sees the 503 health check response and stops routing traffic to the shutting-down instance.
- 1.
R. Fielding, Ed., M. Nottingham, Ed., and J. Reschke, Ed., "HTTP Semantics," RFC 9110, IETF, June 2022. https://www.rfc-editor.org/rfc/rfc9110.txt
- 2.
Mozilla Developer Network, "HTTP response status codes," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
- 3.
Wikipedia, "Service-level objective," en.wikipedia.org, accessed June 2026. https://en.wikipedia.org/wiki/Service-level_objective