What does a store's per-operation atomicity guarantee actually cover for a caller, and what does it leave uncovered?
answer
- one operation, one node
- whole or not at all
- no torn value for readers
- the second operation is a separate unit
- multi-entry atomicity varies by model
basics
~20 sIt covers one operation on one node: applied whole, never observed partway. It does not cover a caller's second operation, entries on another node, or the effect's survival - and multi-entry atomicity depends on the execution model.
solid answer
~40 sThe unit is **one operation, on one node's keyspace**. Within that unit, the store promises the operation is applied completely or not at all and that no other caller sees the entry in between. Outside it, the promise stops dead: your next operation is a separate unit with an unprotected span before it; entries that live on another node are not in the unit at all; and an operation applied atomically is not thereby an effect that survives the node. One case genuinely varies across this class - an operation that touches several entries at once. Under run-to-completion it is atomic because nothing else can execute during it; under per-entry locking it is atomic only where the implementation holds every lock it needs for the whole operation.
go deeper
Recall the unit in one sentence: one operation, applied whole, never observed partway. Anything a caller does in two operations is outside it.
Enumerate the boundary properly - the second operation, other nodes, survival, and the absence of rollback or an isolation level - and explain why a reader still never sees a torn value.
Demonstrate the habit of confirming rather than assuming multi-entry atomicity, since it holds by construction under one execution model and only conditionally under the other.
State the contract this guarantee can and cannot support for the wider system: which invariants may be enforced at the store, which must be enforced somewhere with an isolation level, and what an atomic effect's durability actually is here.
## The unit, stated exactly The free guarantee in this class of store is easy to say and easy to over-extend. Said exactly: **one operation, against the entries it touches on one node, is applied as a whole, and no other caller observes those entries partway through it.** Every word in that sentence is load-bearing, and most disagreements about what an in-memory store guarantees come from dropping one of them. ## What is inside the unit - **No torn value.** A caller reading an entry gets either the value as it was before your operation or the value as it is after. There is no interleaved half-state to defend against, whichever execution model the store uses. - **No lost work inside the operation.** If the operation reads a field, changes it and stores it, the whole of that happens without another operation slipping in, because that is one operation as far as the server is concerned. - **No caller-side coordination needed.** You do not lock, declare or announce anything to get this. It is why so much application code against these stores is written with no concurrency control at all and is nevertheless correct - as long as every change really is one operation. ## What is outside it 1. **Your second operation.** Two operations from one caller are two units, and the span between them is unprotected: other callers' operations execute there. This is the boundary that matters most in practice, and it holds under both execution models. 2. **Ordering against other callers beyond the unit.** The store settles an order for individual operations. It does not preserve any relationship you believed existed between two of yours. 3. **Entries on another node.** Atomicity is a property of one node's keyspace. Where the keyspace is split across nodes, a change spanning entries that landed on different nodes is not one unit; making that work is a placement question, not an atomicity one. 4. **Survival.** "Applied atomically" says the effect is whole, not that it is still there after the node goes away. What a volatile tier keeps across a restart, and what a copy on another machine has at any instant, are separate questions with their own answers. 5. **Anything resembling rollback or an isolation level.** There is no transaction to open here. The operation is the unit and there is nothing to undo, because there is nothing wider to undo it within. ## The case that genuinely varies A single operation that touches several entries at once is the one place where this class does not answer with one voice: | Execution model | A single operation over several entries on one node | |---|---| | One-operation-at-a-time (run-to-completion) | Atomic by construction - no other operation executes during it, so there is nothing to interleave | | Per-entry locking | Atomic only where the implementation holds every lock the operation needs, together, for its whole duration | This is precisely the sort of claim an engineer carries over from the store they know and states as the model. If a design leans on a multi-entry operation being indivisible, that is a property to confirm about the specific store rather than to assume from the class. ## A worked check Take a service that keeps a per-customer usage record as one entry and needs it never to go backwards. Walk the guarantee over it: - A single operation that writes the whole record is atomic - no reader ever sees half of the new record and half of the old. - A read of the record, a decision taken in the service, and a write back are three steps and two operations, so the guarantee covers neither the decision nor the span around it. - If the record were split across two entries that landed on different nodes, no single unit covers both, whatever the execution model. - If the node holding the record is lost, the atomicity of the last write says nothing about whether that write is still anywhere. The exercise is worth doing explicitly for any invariant you intend to rest on this tier, because the guarantee is narrow enough that most real invariants touch at least one of those four edges. ## Saying it in an interview The sentence that demonstrates you have actually run one of these is short: *"one operation is atomic; my read and my write are two operations, so nothing protects the gap - and that is true whether the server runs operations one at a time or locks the entry per worker thread."* Adding the node qualifier ("atomic on this node's keyspace") and the survival qualifier ("atomic is not the same as still there after a restart") is what moves the answer from recited to understood. The converse - the answer to be careful of - is treating per-operation atomicity as a small transaction. It has no rollback, no isolation level to choose, no save point and no scope beyond one node. It is a narrow, very useful, completely non-negotiable promise about a single unit of work, and the engineering value lies in knowing where its edge is.
- Does per-operation atomicity mean a reader can never see a value partway through a change?Within one operation, yes - a reader sees the entry before or after, never a mixture. But a change made as a read plus a write is two operations, and a reader between them sees the old value while the caller believes it has already changed it. The guarantee is about the operation, not about the caller's intent.
- Is an atomically applied operation also a durable one?No, and conflating the two is a common error on a volatile tier. Atomicity says the effect is whole on the node that applied it. Whether it survives a restart, and whether another machine already holds it, are separate properties that this class of store answers in several different ways.
saying these in an interview costs you the question
- Treats per-operation atomicity as a small transaction with rollback.
- Assumes any operation over several entries is atomic on every store.
- Thinks atomic means the effect survives the node failing.
- Extends the guarantee across nodes when the keyspace is split.
- Believes the store preserves the relationship between two of a caller's operations.