PATTERN Cited by 4 sources
Conditional Write (Compare-and-Set on Storage)¶
A conditional write is a storage-layer primitive that performs a
write (typically PUT) only if a precondition on the current state
of the target is satisfied — usually an If-Match against an etag or
version, or an If-None-Match: * for "only if this key doesn't
already exist." It is compare-and-set for objects: the storage
system atomically decides whether to apply the write, eliminating the
read-modify-write race.
Why this pattern matters¶
Without conditional writes, multi-writer coordination on an object store is expensive: customers invent external locking (distributed locks, coordinators, lease servers), version fencing (write-then- verify patterns), or single-writer topologies (one-process- per-bucket / per-prefix). All of these are code the application team owns, maintains, and debugs.
Conditional writes let the storage layer own the atomicity, and let the application express intent directly: "commit this snapshot only if no one else has committed since I read."
S3 context¶
S3 shipped conditional-write enforcement on general-purpose buckets in 2024. Warfield's 2025 post reports the customer reaction:
"In the past year, as we've started to roll out conditional operations we've had a very similar reaction [to the 2020 strong-consistency rollout]."
The "similar reaction" is the code-deletion one: external locking primitives get retired. Compare concepts/strong-consistency.
(Source: sources/2025-03-14-allthingsdistributed-s3-simplicity-is-table-stakes)
Why it needs strong consistency underneath¶
Conditional writes only work if the precondition check sees an up-to-date view of the target. On an eventually-consistent store, the precondition might be evaluated against a stale replica, which undermines the "atomicity" claim entirely. S3's 2020 move to concepts/strong-consistency is therefore a prerequisite for the 2024 conditional-writes rollout — the ordering of those two features is not accidental.
Common applications¶
- Iceberg / Delta / Hudi snapshot commits — the snapshot-pointer update is the atomic moment that makes the table transactional over immutable objects. Conditional writes remove the need for an external catalog lock. See systems/apache-iceberg.
- Leader-election / token-holder files — "I'm the leader, seen version V" — conditional PUT to advance the token fails if someone else advanced it first.
- Time-based single-writer leases — CASAAS. 2025-05-20 Fly.io Litestream revamp uses S3/Tigris conditional writes to enforce one active replication writer per destination, retiring LiteFS's original Consul dependency for the single-leader constraint.
- Idempotent object creation —
If-None-Match: *semantics prevent two writers both thinking they "created" an object. - Versioned configuration stores — atomically advance a config document only if the reader's cached version matches.
Trade-offs¶
- Precondition-failure handling. The client must be prepared to re-read, reconcile, and retry on a failed precondition. Conditional writes don't eliminate coordination cost; they move it out of storage and into application logic, which is the right place for it.
- Write amplification on contention. Hot-key contention translates into retry loops; conditional writes work well for low-to-moderate write contention and poorly for high-contention fan-in (use a queue or a serialisation layer instead).
Seen in¶
- sources/2025-03-14-allthingsdistributed-s3-simplicity-is-table-stakes — S3 conditional writes (2024); framed alongside strong consistency (2020) as a pair of "delete customer code" simplicity features.
-
sources/2025-05-20-flyio-litestream-revamped — second canonical instance on the wiki: Fly.io's 2025-05-20 Litestream redesign uses S3 + Tigris conditional writes to implement the CASAAS time-based replication lease, retiring LiteFS's original Consul dependency for single-leader enforcement. Extends the customer-code-deletion framing beyond catalog-snapshot commits to a new substitution shape: coordination services replaced by object-store CAS. See concepts/distributed-lease for the specialised time-based lease pattern.
-
sources/2026-09-08-databricks-build-durable-agents-with-temporal-and-lakebase — compare-and-set on relational rows as the idempotency mechanism on a durable agent's at-least-once write path. Databricks' underwriting agent writes Lakebase Postgres records from Temporal Activities that may retry, so each guarded write carries a terminal-state predicate: the tool-start upsert targets a stable
tool_call_idand its final predicate only allows an existing nonterminal row to be written back tostarted; if the row is alreadysucceeded/failed, PostgreSQL affects zero rows and raises no error. This is conditional-write applied not to object storage but to relational rows via primary-key/unique-constraint identity + a WHERE-clause state guard, enforcing which transitions are legal. Same discipline covers guarded run and review transitions. Important caveat the article flags: the caller must classify the zero-row result (confirm the stored terminal state) rather than blindly treating it as success. (Source: sources/2026-09-08-databricks-build-durable-agents-with-temporal-and-lakebase) -
sources/2026-09-10-aws-building-resilient-real-time-streaming-workers-with-amazon-dynamodb-leases — conditional write as the enforcement mechanism of a distributed lease on a mutable DynamoDB item. AWS's WebSocket-fleet pattern makes every lease transition a guarded
update_item: acquire usesConditionExpression: "attribute_not_exists(lease_expires_at_ms) OR lease_expires_at_ms < :now"(claim only if unowned or already expired), renew useslease_owner = :w(still mine), release also guards onlease_owner = :w. Racing workers resolve atomically — exactly one wins, the losers getConditionalCheckFailedExceptionand back off — giving single-owner-per-connection without any external lock service. This is the same CAS discipline the S3/Litestream instances apply to object storage, here applied to a per-connection item that colocates lock state (lease_owner,lease_expires_at_ms) with domain state (desired_state,ws_url,last_seq) to save reads. See concepts/distributed-lease for the full lease lifecycle. (Source: sources/2026-09-10-aws-building-resilient-real-time-streaming-workers-with-amazon-dynamodb-leases) -
sources/2026-10-01-cloudflare-announcing-cloudflare-k2-serverless-event-streams — conditional write as the ordering + offset-assignment mechanism of a durable log. Cloudflare K2 builds a partitioned log on R2 and achieves "ordering and strictly incrementing offsets using R2's atomic operations without needing a separate coordination service." This is the same coordination-service-replaced-by-object-store-CAS substitution shape as the Litestream instance (which retired Consul), applied here to log append: the atomic conditional write on R2 is what guarantees two concurrent segment writes can't claim the same offset, so no leader election or external lock is needed to serialise the log.