← Docs/Recipes
Recipe

Recipe: ETag + If-Match conditional requests

Prevent lost updates with optimistic concurrency using HTTP entity tags and conditional headers.

Overview

When multiple clients mutate the same resource, the last write silently wins unless you guard against it. ETags give each resource version a fingerprint. Clients send that fingerprint back via If-Match. If the resource changed underneath them, the server rejects the write with 412 Precondition Failed.

Server-side pattern

GET /api/resource/42
→ 200 OK
   ETag: "v3-a1b2c3"

PUT /api/resource/42
   If-Match: "v3-a1b2c3"
→ 200 OK  (match — write succeeds)

PUT /api/resource/42
   If-Match: "v3-a1b2c3"
→ 412 Precondition Failed
   (resource is now v4 — reject)

ETag strategies

  • Content hash — SHA-256 of the response body. Strong but expensive for large payloads.
  • Version counter — increment on every mutation. Cheap, precise, ideal for database-backed APIs.
  • Last-modified timestamp — simple but vulnerable to sub-second races.

Client contract

On 412, the client must re-fetch the latest resource, reconcile changes, and retry. Never blindly overwrite — that defeats the guard.