N Noer

HTTP status codes as observability signals for web systems

HTTP status codes help operators separate request errors, resource lifecycle, rate limits, proxy failures, temporary outages, and upstream timeouts.

HTTP status codes are observability signals before they are documentation trivia. You need a reliable way to read the first digit, then a smaller set of codes that shape client behavior, search indexing, caching, retries, and incident response.

The valid range is 100 through 599. If a client sees an unknown code, it should fall back to the class: 4xx behaves like a client-side or request-side error, while 5xx behaves like a server-side or gateway error. Codes outside that range are not valid HTTP status codes.

Read the class first

ClassMeaningFirst place to look
1xxInterim informationUpload negotiation, protocol switching, early hints
2xxSuccessWhether the operation created, accepted, returned, or omitted content
3xxRedirectionLocation, permanence, cache behavior, method preservation
4xxClient or request problemPath, payload, identity, permission, rate limit, resource state
5xxServer or upstream problemApplication errors, gateway, dependency health, timeout budgets

The success codes that matter in APIs

200 OK is fine for a completed request with a representation or result. Use 201 Created when a resource is created and include Location when possible. Use 202 Accepted for background work that has not finished yet. Use 204 No Content when the operation succeeded and a body would add nothing. Use 206 Partial Content for range responses such as resumable downloads and media seeking.

Redirects: permanence and method handling

301 and 308 are permanent redirects; 302 and 307 are temporary. The practical difference is method preservation. Older clients may turn POST into GET after 301 or 302. If the method and body must remain intact, use 307 or 308. Use 303 See Other for the POST/Redirect/GET pattern.

Client-side errors are not all validation errors

400 is for malformed requests. 401 means authentication is missing or invalid; 403 means the server refuses the request even if it understands who the caller is. 404 is missing; 410 is permanently gone. 409 is state conflict. 422 is syntactically valid content that cannot be processed semantically. 429 is rate limiting and should usually be paired with a retry policy.

Server-side errors should point to the real boundary

500 is the generic fallback, but operators need more precision. 502 means a gateway or proxy received an invalid upstream response. 503 means temporary unavailability, maintenance, overload, or dependency failure. 504 means the gateway timed out waiting for upstream. That distinction decides whether clients should retry, operators should inspect an upstream, or crawlers should treat the failure as temporary.

Non-standard codes are operational clues, not protocol design

Nginx 499, Cloudflare 520 through 530, Laravel-style 419, and proxy-style 598/599 appear in real logs. Treat them as platform-specific diagnostics. Do not design a public cross-platform API that depends on their meaning.

Reliability checklist

  • Do not return 200 for every failure.
  • Use 201 with Location, 405 with Allow, 401 with WWW-Authenticate, and 429/503 with Retry-After when appropriate.
  • Use RFC 9457 application/problem+json for consistent error bodies.
  • Never expose stack traces, SQL, file paths, or internal class names in production error bodies.
  • Retry idempotent requests more readily than POST; use idempotency keys when retrying state-changing operations.

A reliable system keeps these boundaries honest: cache, retry, re-authenticate, slow down, fix the payload, follow a redirect, or page an operator.