HTTP Semantics: Methods, Status Codes & Caching Headers
Use safe/idempotent method semantics to drive retries and caching, conditional GETs with ETag for cheap 304s, and ETag + If-Match for optimistic concurrency.
Decades of distributed-systems thinking, already encoded
HTTP already encodes decades of distributed-systems thinking about safety, idempotency, caching, and concurrency. Using its semantics correctly gets you free caching and safe retries; ignoring them silently loses data.
Methods: safe and idempotent are orthogonal
Safe means read-only (no server state change): GET and HEAD. Idempotent means repeating it
lands the same final state: GET, HEAD, PUT, DELETE. POST is neither safe nor
idempotent, PATCH generally is not idempotent. This directly drives retry behavior: an
intermediary or client can safely auto-retry GET/PUT/DELETE after a network blip, but
must not blindly auto-retry POST (that is what idempotency keys are for). Safe methods are also
the cacheable ones.
A network blip cuts the connection before the response arrives, so the client cannot tell whether the server did the work. Sort each call by whether the client can safely fire it again.
Status families are a contract with the client:
2xxsuccess:200OK,201Created (return aLocationheader pointing at the new resource),204No Content.3xx: redirects and, importantly,304 Not Modifiedfor conditional requests.4xxclient error:400,401,403,404,409conflict,422unprocessable,429rate limited. Do not retry these blindly.5xxserver error:500,503. Retry with backoff.
Read caching: Cache-Control plus a validator
On a GET you send Cache-Control (max-age for private/browser caches, s-maxage for
shared/CDN caches, no-store for sensitive data) plus a validator: an ETag (an opaque version
hash) or Last-Modified timestamp. The validator enables the conditional GET: the client sends
If-None-Match: <etag> (or If-Modified-Since), and if nothing changed the server returns
304 Not Modified with no body. That saves bandwidth and origin rendering while keeping the client
current.
Optimistic concurrency: ETag + If-Match
The same ETag gives you optimistic concurrency control, which prevents the lost-update problem.
Two editors both GET a document (ETag v5). Editor A saves with If-Match: v5; the server
sees the current version is still v5, applies the write, and the ETag becomes v6. Editor B
then saves with If-Match: v5; the server sees the current version is now v6, refuses, and
returns 412 Precondition Failed. B is forced to re-read and merge instead of silently clobbering
A's change. This is far cheaper than pessimistic locking and is exactly how you avoid last-write-wins
data loss.
Content negotiation completes the picture: honor Accept and Accept-Language, and set
Vary: Accept, Accept-Encoding on responses so a shared cache does not serve a JSON body to a
client that asked for XML, or a Brotli body to a client that cannot decode it.
Interview nuance: the two high-signal moves are (1) tying method idempotency to retry safety, and (2) describing ETag + If-Match -> 412 as optimistic concurrency to prevent lost updates. Saying "return 200 and last-write-wins" is the wrong turn interviewers listen for.
Recap: use safe/idempotent method semantics to drive retry and caching, add Cache-Control plus ETag for cheap conditional GETs (304), and use ETag + If-Match -> 412 for optimistic concurrency that prevents lost updates.
Apply
Your turn
The task this lesson builds to.
Design the HTTP semantics for a document API: choose methods and status codes for read, create, update, and delete, and explain how you would use ETag, If-None-Match, and If-Match to cache reads and prevent lost updates.
Think about
- Which methods are safe, which are idempotent, and why does that distinction drive retry behavior?
- How do Cache-Control, ETag, and Last-Modified turn a GET into a cheap conditional request?
- How does ETag plus If-Match give you optimistic concurrency, and what status code signals a conflict?
Practice
Make it stick
A second problem on the same idea, so it survives past today.
Design the HTTP concurrency and caching model for Google Docs-style collaborative editing where dozens of users edit the same document simultaneously, edits must not be lost, and reads should be cheap. Explain where simple ETag + If-Match optimistic concurrency is sufficient and where it breaks down, and what you would use instead.
Think about
- What contention level does optimistic concurrency assume, and does the document body meet it?
- Which writes on this product are actually low-contention and ETag-friendly?
- What protocol family merges concurrent edits instead of rejecting them?