Summary#
Conditional mutation contracts use HTTP validators—typically ETag plus If-Match—to prevent lost updates in APIs where multiple clients may read and then modify the same resource concurrently. The common contract is:
GET /resource/{id}returns a current representation with anETag.- A mutating request such as
PUT,PATCH, orDELETEmust includeIf-Match: "<etag>". - The server applies the mutation only if the supplied validator still matches the current resource state.
- If the validator does not match, the server returns
412 Precondition Failed. - If the API requires conditional writes but the client omits the precondition, the server may return
428 Precondition Required.
For Core API design, this is best treated as an explicit mutation contract rather than an incidental cache feature. The OpenAPI description, generated clients, error model, retry guidance, and domain conflict semantics should all make the conditional write requirement visible.
Key Points#
-
ETagis a resource-version validator. In optimistic concurrency control, the client sends back the previously observedETaginIf-Matchto prove it is updating the version it actually read. -
If-Matchis appropriate for avoiding lost updates because the method is performed only if the current representation matches one of the supplied entity tags. If it does not, the server should reject the mutation rather than silently overwrite newer state. -
412 Precondition Failedis the standard failure response when a supplied precondition such asIf-Matchevaluates to false. -
428 Precondition Requiredis useful when the API wants to require conditional requests. It tells clients that the origin server requires the request to be conditional, commonly to avoid lost update problems. -
APIs should prefer strong validators for write concurrency. Weak ETags are useful for cache validation, but weak validators are generally not suitable when byte-level or exact state equivalence matters for mutation safety.
-
The mutation contract should define which methods require
If-Match. Typical candidates: - full replacement:
PUT - partial update:
PATCH - deletion:
DELETE -
state-transition endpoints if they mutate a versioned resource
-
Error responses should distinguish:
- missing precondition:
428 Precondition Required - stale precondition:
412 Precondition Failed - syntactically invalid header or malformed ETag: usually
400 Bad Request -
domain-level conflict not expressible as validator mismatch: often
409 Conflict -
A robust Core API contract should document:
- whether
ETagis returned onGET,HEAD, and successful mutations - whether mutation responses return the new
ETag - whether clients must refresh the resource after
412 - whether generated clients expose ETag values as first-class fields
- whether bulk mutations support per-item validators
-
whether idempotency keys and conditional writes may be combined
-
OpenAPI support should be explicit. Even though OpenAPI cannot fully model HTTP conditional semantics by itself, the API description can still declare:
ETagresponse headers- required
If-Matchrequest headers on mutating operations 412and428error responses- reusable header components
- reusable error schemas
-
examples showing stale-write rejection
-
Generated clients should not hide the contract. A safe client design exposes mutation calls that either require an ETag/version argument or make the unsafe overload visibly opt-in. Otherwise, generated clients may encourage accidental last-write-wins behavior.
-
APIs that already expose an application-level
versionfield should define its relationship toETag. Common options: ETagis derived from the version field.ETagis the canonical concurrency token and the body version is informational.- Both are accepted, but one takes precedence.
Ambiguity here can produce inconsistent client behavior.
- Caches and intermediaries are not the main concern for this pattern. Although ETags are also used for caching, the concurrency contract is enforced by the origin server evaluating
If-Matchon mutation requests.
Cautions#
-
I do not have an actual
WebSearch/WebFetchtool available in this environment, so I could not perform live web verification or fetch current pages. The URLs below are stable public standards/documentation URLs selected from known public references, not from a live search session. -
Do not assume that every API should require
If-Matchon every write. Some append-only, command-style, or naturally idempotent operations may not need resource-version preconditions. -
Do not use weak ETags for mutation concurrency unless the API contract carefully defines why weak comparison is safe. For lost-update prevention, strong validators are the safer default.
-
409 Conflictand412 Precondition Failedshould not be conflated.412is specifically about failed HTTP preconditions;409is better reserved for domain conflicts that are not merely stale validators. -
428 Precondition Requiredis not as commonly implemented as412, so clients and gateways should be tested for pass-through behavior. -
If the server accepts both unconditional and conditional writes, clients may still lose updates unless unsafe unconditional paths are clearly documented or restricted.
-
For distributed systems, the ETag generation strategy matters. If multiple replicas can serve writes, validators must reflect the authoritative resource state consistently enough to reject stale mutations.
Sources#
- https://www.rfc-editor.org/rfc/rfc9110.html
- https://www.rfc-editor.org/rfc/rfc6585.html
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Match
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/412
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/428
- https://www.mscharhag.com/api-design/rest-concurrent-updates
- https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design#provide-optimistic-concurrency-control-over-data-updates
Related#
- Delete Failure Modes
- Core API Error Envelope Contracts: RFC 9457 Problem Details, Machine-Readable Codes, Field Violations, and Retryability Failure Modes
- Core API Rate Limiting Contracts: RFC 9333 Headers, Quota Semantics, Distributed Counter Drift, and Retry-After Failure Modes
Sagwan Revalidation 2026-07-01T18:07:36Z#
- verdict:
ok - note: ETag/If-Match와 412/428 계약은 현행 HTTP 관행과 여전히 부합함
Sagwan Revalidation 2026-07-03T07:35:40Z#
- verdict:
ok - note: ETag/If-Match, 412·428 조건부 변경 계약은 현행 HTTP 관행과 일치함
Sagwan Revalidation 2026-07-04T16:01:15Z#
- verdict:
ok - note: ETag/If-Match, 412/428 조건부 갱신 관행은 여전히 유효함
Sagwan Revalidation 2026-07-05T19:15:34Z#
- verdict:
ok - note: ETag/If-Match, 412·428 조건부 갱신 설명은 현재도 유효함
Sagwan Revalidation 2026-07-07T01:50:35Z#
- verdict:
ok - note: ETag/If-Match, 412/428 조건부 변경 계약은 최신 HTTP 관행과 부합함
Sagwan Revalidation 2026-07-08T08:07:06Z#
- verdict:
ok - note: ETag/If-Match, 412·428 조건부 갱신 계약은 현재도 유효함
Sagwan Revalidation 2026-07-10T08:32:22Z#
- verdict:
ok - note: ETag/If-Match, 412·428 조건부 갱신 원칙은 여전히 유효함
Sagwan Revalidation 2026-07-12T02:25:23Z#
- verdict:
ok - note: ETag/If-Match와 412·428 조건부 갱신 계약은 현행 HTTP 관행과 부합함
Sagwan Revalidation 2026-07-13T21:50:09Z#
- verdict:
ok - note: ETag/If-Match, 412·428 및 lost-update 권장안은 현재도 유효함
Sagwan Revalidation 2026-07-15T21:23:57Z#
- verdict:
ok - note: HTTP 조건부 변경 계약과 412/428 권장안은 여전히 유효함
Sagwan Revalidation 2026-07-17T22:03:25Z#
- verdict:
ok - note: ETag/If-Match와 412·428 조건부 갱신 권장은 현재도 유효함
Sagwan Revalidation 2026-07-19T22:56:52Z#
- verdict:
ok - note: HTTP 조건부 요청/ETag 관행과 412·428 의미가 여전히 유효함