HTTP conditional requests and optimistic concurrency
Conditional requests attach a precondition (an ETag validator) to a request so the server can short-circuit a read or reject a stale write. Per RFC 9110 (June 2022), use If-None-Match for cache-efficient reads and If-Match for optimistic concurrency on mutations. This prevents lost updates without server-side locking and is distinct from idempotency keys (which make retries safe).
ETags as validators
- The server MUST return an
ETagresponse header on representations that participate in conditional requests. An ETag is an opaque token identifying a specific resource version. - Strong ETags (
"abc") assert byte-for-byte equivalence; weak ETags (W/"abc") assert only semantic equivalence. The server SHOULD emit strong ETags for write concurrency, sinceIf-Matchuses the strong comparison. - Clients MUST treat ETag values as opaque — do not parse, compare substrings of, or derive meaning from them.
Efficient reads — If-None-Match / 304
- Clients SHOULD send
If-None-Match: <etag>(echoing the ETag from a prior response) on repeat GET/HEAD requests. - If the resource is unchanged, the server MUST return
304 Not Modifiedwith no body, includingETag,Cache-Control, andVaryif present. The client reuses its cached representation. If-None-Matchuses weak comparison and SHOULD be preferred overIf-Modified-Since(1-second granularity) when an ETag exists.
Optimistic concurrency on writes — If-Match / 412
- For PUT/PATCH/DELETE on shared, mutable resources, clients SHOULD send
If-Match: <etag>carrying the ETag they last read. - The server MUST apply the change only if the current ETag matches (strong comparison); otherwise it MUST reject with
412 Precondition Failedand make no change. The client refetches, rebases its edit, and retries. - This is the read-modify-write guard against lost updates: two clients editing the same version cannot both succeed.
If-Match: *requires the resource to exist;If-None-Match: *on a write requires it to NOT exist (create-only, guarding against accidental overwrite).- Mutating endpoints on shared resources SHOULD support
If-Matchand MAY require it (returning428 Precondition Required, RFC 6585) to force callers to opt into concurrency safety.
Boundaries and pitfalls
- Distinct from idempotency keys.
If-Matchrejects a write against a stale version; an idempotency key lets the SAME write be retried safely after a network failure. Use both:If-Matchfor correctness under concurrent edits, idempotency keys for retry safety. See the related guidelines. - Agents MUST NOT strip or blindly default
If-Matchto*to "make the 412 go away" — that reintroduces the lost-update bug it prevents. - Surface
412distinctly from409 Conflict: 412 means the client's precondition failed (refetch and retry); 409 signals a domain-level conflict that may not be resolvable by retry. - Behind proxies/CDNs, ensure ETags are passed through unmodified; some intermediaries rewrite or drop them.