An HTTP origin can refuse a PUT or DELETE before applying it when the request carries If-Match and the selected representation no longer has an accepted entity tag. The condition converts a representation validator into a write precondition: a client can say that a mutation is valid only against state matching a version it previously observed.

This mechanism addresses a specific concurrency boundary. It can prevent one client from silently replacing resource state after another client has changed the selected representation. It does not turn HTTP into a transaction protocol, lock the resource between requests, or guarantee that an entity tag represents every piece of application state involved in a mutation.

The precondition is evaluated at the origin

Suppose a client retrieves a representation and receives a strong entity tag:

HTTP/1.1 200 OK
ETag: "rev-41"
Content-Type: application/json

{"status":"draft","owner":"sam"}

A later replacement can carry that validator:

PUT /documents/17 HTTP/1.1
If-Match: "rev-41"
Content-Type: application/json

{"status":"approved","owner":"sam"}

For If-Match, the origin server compares the supplied entity tags with the entity tag of the current selected representation using the strong comparison function. If none matches, the condition is false and the requested method must not be performed under the normal failed-precondition path. A 412 Precondition Failed response can expose that conflict to the client.

The important boundary is evaluation before the method is applied. A client does not acquire ownership of "rev-41" when it receives the earlier response. Another actor remains free to change the resource. The later request succeeds only if its precondition still holds when the origin evaluates it.

This is optimistic concurrency at the HTTP interface: proceed without holding a cross-request lock, then reject a mutation whose observed basis has become stale.

Strong comparison matters for mutation guards

HTTP distinguishes strong and weak entity tags. A weak validator can indicate semantic equivalence suitable for some cache validation cases even when representation data is not byte-for-byte stable. If-Match instead requires strong comparison because its purpose can include preventing a state-changing method from being applied after representation data has changed.

That rule creates a practical constraint. A weak entity tag such as:

ETag: W/"rev-41"

cannot satisfy strong comparison against another tag. An API that intends to expose If-Match as a mutation guard therefore needs validators with semantics compatible with strong validation for the selected representation.

The validator also needs a sound relationship to the state being protected. An opaque tag is sufficient at the protocol level; clients do not need to decode it. But if an implementation emits the same strong entity tag for two representation states that differ in representation data, the validator no longer satisfies the strong-validator requirements that make the precondition meaningful.

A database revision number, content digest, or internal version identifier can participate in an entity-tag implementation, but HTTP does not prescribe one storage scheme. The server remains responsible for assigning validator values with the required semantics.

A stale write becomes an explicit branch

Consider two clients that both retrieve version "rev-41".

client A reads "rev-41"
client B reads "rev-41"

client A PUT If-Match: "rev-41"
origin stores new state and emits "rev-42"

client B PUT If-Match: "rev-41"
precondition no longer matches

Without a write precondition, client B’s request might replace the state written by client A if the resource’s method semantics permit that replacement. With If-Match, the stale basis is visible to the origin before the second mutation is applied.

This changes the failure mode from silent overwrite to an explicit protocol result. It does not prescribe conflict resolution. After a failed precondition, an application might fetch current state, abandon its attempted mutation, present a conflict to a human, or compute another request. Those policies sit above the HTTP precondition itself.

The distinction also keeps retries precise. Repeating the same stale conditional mutation does not make its condition current. A retry strategy that blindly resends If-Match: "rev-41" after the resource has moved to "rev-42" preserves the conflict rather than resolving it.

The entity tag guards a selected representation, not an arbitrary database transaction

An entity tag is associated with a representation of a target resource. Application writes can have a broader footprint.

A request to /documents/17, for example, might update the document row, append an audit record, modify a quota counter, and publish an event. If-Match specifies a condition concerning the selected representation; it does not define atomicity across those internal effects. The application and its storage systems still determine whether the operation is transactional, partially applied, compensating, or otherwise coordinated.

This boundary becomes especially important when representation state is derived from several records. If the entity tag changes only when one primary row changes, but the rendered representation also depends on related rows, the validator might not track every representation-data change. Conversely, a validator derived from the complete selected representation can change when any represented component changes, potentially rejecting writes that only depend on a smaller subset.

Neither choice is supplied automatically by HTTP. The validator design determines the granularity of the conflict signal.

The same issue appears with content negotiation. A resource can have multiple representations selected by request metadata. Conditional semantics assume a stable mapping from requests to selected representations when validators are used this way. Servers that vary representations need validator generation and selection behavior consistent with that model.

If-Match: * expresses existence, not version identity

The wildcard form has different semantics:

If-Match: *

For an origin server, this condition is true when the target resource has at least one current representation. It does not assert that the resource still has a particular version.

That makes the wildcard useful for operations that require current existence but do not need to bind the request to one previously observed entity tag. It cannot replace a specific validator when the intended rule is “apply this mutation only if the representation is still the one I saw.”

The inverse wildcard pattern appears with If-None-Match: *. On an unsafe method such as PUT, it can express a create-only condition: apply the method only when no current representation exists. The two forms therefore protect different boundaries.

If-Match: *       require an existing representation
If-Match: "v7"    require a matching current representation
If-None-Match: *  require no current representation

These conditions are protocol-level predicates. Their usefulness depends on the target resource semantics matching the application’s notion of existence and identity.

Date validators have a different precision boundary

If-Unmodified-Since can also guard a state-changing request when an entity tag is unavailable. Its condition is based on the selected representation’s modification date. HTTP gives If-Match precedence when both fields are present, treating the entity-tag condition as the more accurate replacement.

Modification times carry constraints that entity tags can avoid. Timestamp resolution can be coarser than the rate of state changes, clock-related semantics belong to the origin server, and a date describes time rather than an opaque representation identity. Those properties can make a date validator less precise for detecting closely spaced changes.

A strong entity tag does not require a timestamp interpretation. It only needs to obey the validator semantics defined by HTTP. That separation lets an origin use a monotonic revision token or another opaque scheme without exposing its internal clock as the concurrency token.

Conditional writes do not create cross-resource isolation

A successful If-Match check says something narrow: at evaluation time, the selected representation met the supplied precondition and the origin proceeded according to the request semantics. It does not establish serializable isolation across several resources.

Two conditional requests against different resource identifiers can both pass even when the application considers their combined effects conflicting. Protecting an invariant such as “only one active lease exists across this collection” requires a coordination boundary that represents that invariant. Per-resource entity tags alone do not create it.

Even on one resource, server implementation matters. The check and the protected state transition need an internal concurrency mechanism that preserves the precondition’s meaning. If an application reads a version, releases all coordination, then later writes without ensuring that the version is still current, a race inside the origin can defeat the intended guard despite correct-looking HTTP headers.

A typical implementation maps the precondition to an atomic storage predicate, a transaction with suitable locking or isolation, or another compare-and-set mechanism. HTTP defines the external condition; the origin must connect it to an internal mutation boundary that cannot be invalidated between comparison and write.

Preconditions expose conflicts without defining merge semantics

If-Match is valuable precisely because its guarantee is limited. It carries observed representation state back to the origin and makes method execution conditional on that state still matching. That is enough to transform a class of accidental overwrites into detectable conflicts.

Everything after detection remains application policy. A server can return a failed-precondition response, while the client decides whether current state makes its intended change obsolete, compatible, or in need of human arbitration. The protocol does not infer field-level independence, merge JSON objects, preserve intent, or rank competing writes.

This separation keeps the HTTP mechanism composable. Entity tags identify representation state under validator rules; If-Match turns those validators into origin-evaluated preconditions; application semantics determine what a conflict means beyond that boundary.