If-Match: safe updates and the lost update problem
If-Match tells the server to perform the request only if the resource still matches the entity tag the client holds. If somebody else wrote first, the answer is 412 Precondition Failed.
At a glance
- Direction
- Request only, and it is most useful on writes rather than reads.
- Defined in
- RFC 9110
- When absent
- The write proceeds unconditionally and silently overwrites whatever was there.
- Result on mismatch
- 412 Precondition Failed, and the request is not performed
- Comparison
- Strong, so weak W/ prefixed tags never satisfy it
- If-Match: *
- Succeeds if the resource exists at all, and fails with 412 if it does not
- Pattern name
- Optimistic concurrency control, also called optimistic locking
In detail
The lost update problem is simple to describe and easy to ship: two clients read the same record, both edit it, and the second write silently erases the first. If-Match closes that window by making the write conditional on the version the client actually read. The server compares the tag, and if the resource has moved on it refuses rather than overwriting.
Comparison is strong here, unlike the weak comparison used for caching. A write must land on exactly the representation the client saw, so a weak tag, which only promises equivalence, is never good enough. A server that issues only weak tags therefore cannot support conditional writes without also issuing strong ones.
The 412 response is not an error to hide from the user. It is the signal that somebody else changed the record, and a good client turns it into a refresh with a visible message rather than a retry. Retrying the same request blindly reproduces exactly the overwrite the header exists to prevent.
The wildcard form is a different question: it asks whether anything exists at this URL. If-Match: * on a PUT means update but do not create, and it pairs with If-None-Match: *, which means create but do not update. Together they cover both halves of an idempotent write API without any extra endpoint.
Examples
PUT /documents/17 HTTP/1.1
If-Match: "v9"
Content-Type: application/json
HTTP/1.1 412 Precondition FailedThe stored resource is no longer at v9, so the write is refused and nothing is changed.
PATCH /settings/theme HTTP/1.1
If-Match: *Things that catch people out
- 412 means nothing happened. Client code that treats it as a transient failure and retries without refetching will overwrite the other writer's change on the second attempt.
- Weak tags never satisfy If-Match, so an API that only issues W/ prefixed tags cannot offer conditional writes, no matter what the client sends.
- Do not confuse it with If-None-Match. One protects a write against a change; the other avoids downloading a body you already have.
Try it: HTTP Headers Checker
Check a live URL or paste headers you already have. It grades six security headers from A+ to F and lists every other header the response returned.
HTTP Headers Checker
LOCAL · Browser-OnlyView HTTP response headers for any URL
Enter any website URL to fetch and analyze its HTTP response headers. We'll automatically add https:// if needed.
Why Check Security Headers?
Security headers protect your website against common attacks like XSS, clickjacking, and MIME sniffing. They're set by your web server and cost nothing to implement. Missing security headers are one of the most common findings in security audits.
Related HTTP headers
All http headers →ETag: version identifiers for conditional requests
How an ETag is compared, when to use a weak tag, how it drives 304 responses and 412 conflicts, and why compression changes the tag a server sends.
If-Unmodified-Since: a date based conditional write
How If-Unmodified-Since guards a write with a timestamp instead of an entity tag, when servers ignore it, and why an ETag is the stronger guarantee.
If-None-Match: asking whether anything changed
How If-None-Match produces a 304, why it uses weak comparison, how it overrides If-Modified-Since, and its second job preventing duplicate creates.
Authorization: credentials on a request
How the Authorization header is structured, how Basic and Bearer differ, why it is dropped across a cross-host redirect, and how it interacts with caching.
Pragma: a deprecated header still copied everywhere
What Pragma: no-cache ever did, why it only applied to requests, why it is deprecated in RFC 9111, and whether there is any reason to keep sending it.
Date: when the response was generated
What the Date header records, the exact GMT format required, how caches use it with Age and max-age, and the one case where a server may omit it.
Tools for this
- HTTP Request Builder Free online HTTP request builder - build and test HTTP requests with custom headers and body
- HTTP Headers Checker Free online HTTP headers checker - view HTTP response headers for any URL