skip to content

questions

4

An HTTP client receives a response with status code 227, which it has never seen before. What should it do with that response, and what general rule about HTTP status code classes governs the decision?

level: juniorimportance: must knowfreq 76%

answer

  1. first digit = the contract
  2. unknown code → x00 of its class
  3. 1 interim, 2 ok, 3 elsewhere, 4 your fault, 5 my fault
  4. extensible: 429/451/103 shipped safely
  5. x00 fallback is not heuristic cacheability

basics

~20 s

Judge it by the first digit. 227 is 2xx, so treat it exactly like 200 OK. HTTP requires clients to understand the five classes (1xx interim, 2xx success, 3xx redirection, 4xx client error, 5xx server error), not every individual code.

solid answer

~50 s

HTTP defines five classes by the first digit: **1xx** interim/informational, **2xx** success, **3xx** redirection, **4xx** client error, **5xx** server error. RFC 9110 says a client must understand the *class* and must treat an unrecognized code as equivalent to the **x00** code of that class. So 227 is handled as 200, 499 as 400, 599 as 500. Two consequences. First, this is what makes status codes extensible — 429 and 451 shipped without breaking older clients. Second, client code must never switch exhaustively on exact codes with no default: branch on the range, then special-case the handful you actually act on (301, 401, 429, 503). Caveat: the x00 fallback governs *handling*, not caching. An unrecognized code is not heuristically cacheable just because 200 is; it may be stored only if the response carries explicit freshness information.

go deeper

for a junior

Name the five classes correctly and say that an unknown code is handled as the x00 of its class — 227 behaves like 200.

for a middle

Add why the rule exists (forward compatibility for new codes) and show range-based handling with a default branch instead of an exhaustive switch.

for a senior

Tie class to operational policy: retry only 5xx and 429, alerting and SLOs keyed on class, and the caching caveat that unknown codes are not heuristically cacheable.

for a principal

Frame status class as the machine-readable contract between service and every intermediary, and argue why 200-with-error-body breaks caching, retries and observability across the whole fleet.

## The five classes Every HTTP response begins with a three-digit status code. The first digit places it in a class; the other two digits only distinguish codes inside that class. - **1xx (informational / interim)** — the request was received and processing continues. A 1xx is not a final response: another response follows on the same exchange. Examples: 100 Continue, 101 Switching Protocols, 103 Early Hints. - **2xx (successful)** — the request was received, understood and accepted. 200 OK, 201 Created, 202 Accepted, 204 No Content, 206 Partial Content. - **3xx (redirection)** — further action is needed to complete the request, usually another request to a different URI. 301, 302, 304, 307, 308. - **4xx (client error)** — as far as the server can tell, the fault is in the request: bad syntax, missing or invalid credentials, unsupported method, failed precondition. Repeating the identical request will fail again. - **5xx (server error)** — the request looked valid but the server failed or refused to fulfil it. The same request may succeed later, which is why 5xx is the retryable class. ## The treat-unknown-by-class rule RFC 9110 states that a client MUST understand the class of any status code and MUST treat an unrecognized status code as equivalent to the **x00** code of that class. Unknown 2xx becomes 200, unknown 3xx becomes 300, unknown 4xx becomes 400, unknown 5xx becomes 500. That rule is the extension mechanism of the protocol. It is why 429 Too Many Requests, 451 Unavailable For Legal Reasons and 103 Early Hints could be introduced years after HTTP/1.1 shipped without a flag day: an old client that has never heard of 429 still classifies it as a client error and does not crash. The historical counter-example is 308 Permanent Redirect — clients that did not know it fell back to 300 Multiple Choices, which is exactly the safe, non-following behaviour the rule intends. The one important exception is caching. RFC 9111 lets a cache guess freshness heuristically only for codes explicitly defined as cacheable by default (200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501). An unrecognized code inherits handling from x00 but **not** heuristic cacheability: it can only be stored if the response says so explicitly with freshness information. ## What this means in code Write handling as ranges plus overrides, never as an exhaustive enumeration: - `code / 100 == 2` → success path. - `code / 100 == 5` → retry with backoff (plus the specific 429 and, where documented, 408). - `code / 100 == 4` → do not retry blindly; fix the request. 401 and 403 get their own branches. - Anything unmatched logs the raw code so an unknown code is observable rather than silently mapped. The wild is full of non-registered codes that only this rule makes safe: nginx's 444 and 499, Cloudflare's 520–527, Microsoft's 440, the joke 418. None of them are in any HTTP RFC as usable status codes, yet a correct client behaves sensibly by class. ## The classic violation APIs that answer `200 OK` with `{"status":"error"}` in the body defeat everything above: intermediaries cache the error, clients take the success branch, retry logic never fires, and dashboards built on status class report a perfectly healthy service. The mirror-image mistake is misattributing the class — returning 5xx for malformed client input, which burns error budget for a fault the server did not commit, or 4xx for an internal failure, which hides real outages.

  • Which classes are safe to retry automatically, and why?
    5xx is the retryable class: the request was understood but the server failed transiently, so the same request may succeed later. 429 is the other standard retry signal, ideally honouring Retry-After. 4xx generally must not be retried unchanged because the request itself is the problem; retrying it just amplifies load during an incident.
  • Why does an unrecognized status code not inherit the cacheability of its x00 code?
    Handling and storage are separate rules. RFC 9111 allows heuristic freshness only for a fixed list of codes defined as cacheable by default. Guessing that an unknown 2xx is as cacheable as 200 could make a cache serve a stale response for a semantic the cache does not understand, so an unknown code needs explicit freshness information before it may be stored.

saying these in an interview costs you the question

  • Claiming a client must know every status code or reject the response
  • Aborting or throwing on any unrecognized code instead of falling back to x00
  • Retrying 4xx responses unchanged because 'the request failed'
  • Returning 200 with an error body and calling it a design choice
  • Assuming an unknown 2xx is cacheable just because 200 is

context

open as a page

What is an HTTP 1xx interim response, and how does an exchange that includes 100 Continue or 103 Early Hints differ from an ordinary request/response pair?

level: middleimportance: should knowfreq 40%

basics

~20 s

A 1xx is a non-final response: status line plus headers, never a body, and a final response still follows on the same exchange. 100 Continue tells a client waiting with Expect: 100-continue to send its request body; 103 Early Hints sends preload links before the real response.

open as a page

Which HTTP status codes are defined to carry no response content, and what goes wrong on the wire if a server writes body bytes with a 204 No Content or 304 Not Modified?

level: middleimportance: should knowfreq 50%

basics

~20 s

All 1xx responses plus 204 No Content, 205 Reset Content and 304 Not Modified never carry content; neither does any response to HEAD. Extra body bytes desynchronize an HTTP/1.1 connection: the recipient reads them as the start of the next response.

open as a page

An HTTP/1.1 response starts with a line like 'HTTP/1.1 404 Not Found'. What happened to that trailing reason phrase in HTTP/2 and HTTP/3, and what breaks in software that depends on it?

level: seniorimportance: nice to knowfreq 28%

basics

~20 s

HTTP/2 and HTTP/3 dropped reason phrases entirely: a response carries only the three-digit :status pseudo-header. Anything that read, logged, asserted on, or smuggled information through the phrase gets nothing — clients synthesize a phrase from a lookup table or leave it empty.

open as a page