← Concepts

阅读中文版本

Conditional Requests

Conditional requests let clients revalidate or safely modify resources using validators such as ETag and Last-Modified, avoiding wasted bandwidth and lost updates.

api

Definition

A conditional request carries a precondition, such as If-None-Match or If-Match, that the server evaluates against the current representation before doing any work, enabling cache revalidation and optimistic concurrency control.

Context and scope

Use it for cacheable reads that change occasionally, and for writes where two clients might update the same record concurrently.

Common misconceptions

  • Conditional requests are only about caching; If-Match also prevents lost updates
  • A 304 response is an error; it is a successful validation with no body
  • Last-Modified is as precise as an ETag; it has one-second resolution and weaker semantics

Anti-patterns

  • Returning 200 with the full body when the client already has the current version
  • Using If-Match with a validator that changes on every request
  • Treating 412 as a server failure instead of a recoverable conflict

Related concepts

Related examples

Authoritative source

https://www.rfc-editor.org/rfc/rfc9110.html#section-13

Validators and preconditions

HTTP conditional requests rely on validators attached to a representation. An ETag is an opaque string that changes when the representation changes; Last-Modified is a timestamp. The client sends one back in a precondition header, and the server decides whether the stored representation still matches before transferring bytes or applying a write.

How it works

For reads, If-None-Match: "v42" asks for the resource only if it is not that version. A match produces 304 Not Modified with no body, so the client reuses its copy. If-Modified-Since does the same with dates, but only when no ETag is available.

For writes, If-Match: "v42" requires the current version to match. If another writer already produced v43, the server returns 412 Precondition Failed and the client can refetch, merge, and retry. This is optimistic concurrency: no locks, just a compare-and-swap on the representation.

When to use it

Use conditional GETs for feeds, configuration, and detail pages that are read often but change rarely. Use conditional writes for edit forms, inventory decrements expressed as replacement, and any read-modify-write flow where silent overwrites are unacceptable. Purely additive or idempotent operations often need no precondition.

Trade-offs

ETags cost storage or computation, and weak validators (marked W/) cannot guard writes because they permit semantically equivalent but byte-different representations. Last-Modified is cheap but coarse and unreliable across replicas. A 304 saves bandwidth but still costs a round trip, so very short TTLs can be faster with no validation at all.

Example and misconceptions

A client caches a profile with ETag: "v42", then sends If-None-Match: "v42" and receives 304, saving the payload. A second client edits the same profile with If-Match: "v42" and gets 412 after the first save, preventing a lost update.

The frequent misconception is that 304 means failure. It is a successful, bodyless validation, and clients must merge its updated headers into the stored response.

Related concepts: ETag, HTTP Caching, and Optimistic Concurrency.