Selecting the right status code improves client behavior, caching efficiency, SEO, and observability.
Pick the status class
flowchart TD
A[Request handled successfully]
A -->|Yes| S[2xx]
A -->|No| Q{Client problem}
Q -->|Yes| C[4xx]
Q -->|No| E[5xx]
- 2xx: the server accepted and completed the request.
- 4xx: the request is invalid or not allowed.
- 5xx: the server or an upstream failed to process a valid request.
Success details: 200 vs 201 vs 202 vs 204
flowchart TD
S[2xx] --> K{Created new resource}
K -->|Yes| C201[201 Created]
K -->|No| P{Processing deferred}
P -->|Yes| C202[202 Accepted]
P -->|No| B{Response body present}
B -->|Yes| C200[200 OK]
B -->|No| C204[204 No Content]
- 201 Created: resource was created; include a Location header.
- 202 Accepted: accepted for processing; finish later; provide a status endpoint or webhook if possible.
- 200 OK: success with a representation in the body.
- 204 No Content: success with no body to return.
Conditional responses: 200 vs 304
flowchart TD
P[Conditional request]
P --> J{Representation changed}
J -->|No| N304[304 Not Modified]
J -->|Yes| N200[200 OK]
- 304 Not Modified: client can reuse its cached representation.
- 200 OK: representation changed or no valid validators.
Authentication vs authorization: 401 vs 403
flowchart TD
A[Access failed] --> X{Credentials present and valid}
X -->|No| U401[401 Unauthorized]
X -->|Yes| F403[403 Forbidden]
- 401 Unauthorized: include WWW-Authenticate with the challenge.
- 403 Forbidden: user is authenticated but not allowed.
Validation vs business rules: 400 vs 422
flowchart TD
V[Request invalid]
V --> P{Syntax or schema malformed}
P -->|Yes| B400[400 Bad Request]
P -->|No| B422[422 Unprocessable Content]
- 400 Bad Request: malformed JSON, wrong types, missing required fields.
- 422 Unprocessable Content: syntactically valid but fails business rules or domain validation.
Redirects
See the dedicated guide: Redirects Deep Dive: 301 vs 302 vs 307 vs 308
CDN notes
- 2xx and 3xx are often cacheable when headers allow; 304 reduces origin bandwidth.
- Short defensive caching for select 4xx can protect origins.
- 5xx is usually not cacheable; use retries, shields, multi-origin setups, and stale-if-error where supported.