advanced25 min studyLesson 313 in Engineering

Put the precondition inside the object write

Use supported atomic If-Match and If-None-Match writes while treating ETags as opaque validators rather than universal hashes or version histories.

On this page

What you’ll understand

  • Explain the race in a separate read-before-unconditional-write sequence.
  • Distinguish current ETag equality from a unique historical version identity.
  • Handle precondition failures and ambiguous outcomes without blind overwrites.

Reading an object, checking it locally, and later writing unconditionally leaves a race between the check and the update. A supported conditional write places the relevant predicate inside the service's write operation. That can coordinate one key, but the predicate's meaning matters. An ETag comparison concerns the service's current validator, not necessarily a cryptographic content digest, a unique revision counter, or proof that no intervening change occurred. Build the application's invariant around the exact documented condition.

A local check does not reserve the key

Suppose two publishers both read the same manifest, compute different successors, and then PUT them unconditionally. Strong consistency of each individual operation does not prevent one successful write from replacing the other. The application performed no atomic check that the manifest was still the observed state. Serializing the local code in one process does not fix competition from other processes or recovery workers. Move the predicate to a supported conditional API or use another coordination protocol.

In S3 general purpose bucket examples, If-None-Match with the wildcard can create only when the relevant current object does not exist, and If-Match compares the supplied ETag with the current object's validator for supported writes such as PutObject and CompleteMultipartUpload. Permission, signing, and API support still apply. In a versioned bucket, a current delete marker has the documented absence semantics for the create condition; an older retained version does not necessarily block creation of a new current object.

write⁡(k,D)only ifETag⁡current(k)=e\operatorname{write}(k,D)\quad\text{only if}\quad\operatorname{ETag}_{\rm current}(k)=e
This conceptual If-Match operation checks the service's current ETag e within a supported write boundary. The predicate concerns one key and the documented validator; it is not a multi-key transaction or proof that every metadata field and historical revision are unchanged.↔ Scroll wide equations horizontally.

An ETag is not a universal content hash

Treat a returned ETag as an opaque value unless the exact upload and encryption contract documents a stronger interpretation. Multipart uploads and some encryption configurations do not produce a simple whole-object MD5 ETag. Even when an ETag matches a content digest in a particular case, it should not be promoted to a general-purpose version counter. Use an explicit supported checksum field and algorithm for integrity, and an actual version identifier or application revision protocol when historical identity matters.

Equality also has an ABA limitation: if content changes from A to B and back to an ETag-equivalent A, a predicate based only on that current validator may pass despite the intervening history. Some metadata changes can likewise fall outside what the ETag represents. The needed invariant might only be replace these current bytes, in which case that condition can suffice; another invariant may require no intervening revision. State which one the application needs and select evidence that actually expresses it.

e(A)→e(B)→e(A)⇏no intervening updatee(A)\to e(B)\to e(A)\quad\not\Rightarrow\quad\text{no intervening update}
The sequence illustrates a possible content-validator ABA pattern. e denotes a validator under a contract where the returned A representation can have the earlier value again. No claim is made that all ETags are content hashes or that every provider repeats them in this way.↔ Scroll wide equations horizontally.

A rejected condition is information to reconcile

A precondition failure tells the client its expected current state did not satisfy the write predicate. Read the new state and deliberately recompute, merge, or abandon rather than deleting the condition to make a retry succeed. Concurrent deletion and multipart operations have additional documented error cases and recovery requirements, so distinguish a failed predicate from a transport timeout with an unknown outcome. Store operation evidence needed to recognize whether the intended update already became visible.

The probability lab illustrates contention only under a synthetic independent-attempt model. Reset, set both p=0.3 as an assumed probability an attempt loses its precondition race and n=10, predict the number-of-conflicts distribution, then Play or Step. The lab does not execute compare-and-write operations or model retry feedback. Real publishers can synchronize and contend repeatedly, violating independence. Its bars help interpret an assumed failure count; they cannot certify a lock, a unique history, or a safe retry policy.

Prevent a lost counter update under a stated predicate

A single object contains counter 5 with ETag e5. Two clients read it and each proposes 6 using If-Match e5. Assume the first successful content change produces a different ETag e6 and no other writes occur.

  1. The first conditional write sees current e5, succeeds, and changes the counter to 6 with e6. Its predicate and write are one supported service operation.

  2. The second client's e5 predicate no longer matches e6, so it must fail rather than silently overwrite. To apply a second increment, read 6/e6 and conditionally propose 7 under the same rules.

  3. After that deliberate recomputation succeeds, the counter is 7. The reasoning depends on the stated distinct validator after the first change and does not claim immunity to arbitrary ABA histories or cross-key counter invariants.

The result

The rejected stale write exposes competition so the second increment can be recomputed. Retrying its original value unconditionally would discard the intended two-increment semantics.

Explore the model

Interactive lab

Interactive lab · probability

Count assumed conflicts without inventing a lock

Reset, set both synthetic per-attempt conflict probability p=0.3 and independent attempts n=10, predict the conflict-count bars, then Play or Step. No object writes, ETag checks, retry coordination, or provider consistency are simulated.

Count assumed conflicts without inventing a lockThese are exact binomial probabilities for independent trials with one fixed success probability. Playback tours the distribution; it does not resample outcomes. Current readings: Mean · np: 5; Variance · np(1−p): 2.5; Total probability: 1. All parameters are adjustable with the labeled controls below.03581000.070.150.220.3Successes kP(X = k)k = 0 · P = 9.77e-4
Exact probabilityHighlighted outcomeMean np
Mean · np
5
Variance · np(1−p)
2.5
Total probability
1
t = 0 s

These are exact binomial probabilities for independent trials with one fixed success probability. Playback tours the distribution; it does not resample outcomes. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forThe conditional operation enforces the current-state predicate; conflict statistics do not broaden that predicate into a historical guarantee.

Check your understanding

Which is the sound default interpretation of an ETag returned after a multipart object upload?

Try it yourself

A publisher receives a precondition failure while replacing a manifest. A proposed fix removes If-Match and repeats the old payload. Why can that break correctness, and what should the recovery decision use instead?

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

The rejected predicate identifies a competing state change. An unconditional retry abandons the very check intended to protect it.

Compare with the solution

The unconditional retry can overwrite another publisher's accepted manifest and lose its change. Recovery should inspect the current manifest and its validator or explicit revision, determine whether the original operation already happened, and then recompute, merge, or abandon according to the application's invariant. A fresh conditional write can protect that deliberate decision; making the request succeed is not sufficient evidence that its result is correct.

Take it with you

  • Supported conditional writes remove the race between a predicate and a single-key update.
  • ETags are opaque validators, not universal MD5 digests or unique history counters.
  • Precondition failures require deliberate reconciliation rather than unconditional replay.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.