Contention
A permission model can't stop two people booking the same 3pm slot. Preconditions can, and each one is an argument on a call you already make.
A 409 conflict is the mechanism working.
Catch it and tell the user the slot, stock, or edit was taken, rather than retrying it
away.
Uniqueness with keyed creates
Derive the key from the thing that must be unique. The second writer gets a 409; your
own retry returns your record back (existing: true); deleting the record
frees the key.
await bookings.create({ who: email }, { key: "slot:2026-07-15T15:00" })
Limited stock: N units anyone can buy
Claim units with keyed creates, and on conflict try the next unit. When every unit is taken, the item is sold out. This is race-proof under every safety rule, because writes on other users' records are never allowed.
await orders.create({ item: 42 }, { key: "unit:item42:1" }) // then :2 … :N
Counters: the server does the math
Atomic ops run against current state on the server. Breaching the floor or ceiling → 409, record untouched.
await products.update(id, { stock: { decrement: 1, floor: 0 } })
An object in a patch is an atomic op ONLY when its keys are exactly
increment|decrement (+ optional
floor|ceiling), all numbers. Anything else is stored as plain
data.
Shared editing with versions
Pass back the version you read. A stale save gets a 409 instead of silently clobbering someone's edit, so re-read, reapply, and retry.
await pages.update(id, { body }, { ifVersion: page.version })
Compound: one-per-user AND limited
A booking that must be unique and capped per user wants two keyed creates: claim the resource first, then the per-user cap. If the second 409s, delete the first, which frees its key:
const slot = await bookings.create({ when }, { key: "slot:" + when })
try {
await quotas.create({ ref: slot.id }, { key: "user-day:" + user.userId + ":" + day })
} catch (e) {
if (e.code === "conflict") { await bookings.delete(slot.id) } // give the slot back
throw e
}
Never find-then-create, never compute counters
client-side. Both race, and both fail only when real users collide, which is exactly
when it matters. Keys are 1–120 chars of letters, numbers, and
: _ . @ / -.