Session guarantees
What does a single client need in order not to see nonsense, and why do infrastructure changes break it?
Four guarantees (Terry and colleagues, from the Bayou system) say what a single client needs in order not to observe nonsense:
| Guarantee | Meaning | Example violation |
|---|---|---|
| Read your writes | After I write, my later reads show my write (or something newer) | I change my name and see the old one |
| Monotonic reads | Once I have seen a value, I never see an older one | The page shows the new name, then the old name |
| Monotonic writes | My writes are applied in the order I issued them | My "set name = A" is overtaken by my later "set name = B" |
| Writes follow reads | A write I make after reading a value is ordered after the write that produced it | My reply appears before the message I replied to |
They are not an arbitrary list. If you apply them across sessions instead of within one, and take the transitive closure (a chain of "depends on"), you get causal consistency. Writes-follow-reads is exactly the cross-session edge. Causality is session guarantees plus transitivity, which is why there are these four and not five.
How they are implemented: give the client a token
Every implementation uses the same move. The server cannot cheaply know who you are or what you wrote. The client knows both. So the state moves to the client and comes back on the next request. This is the token rule. Examples:
- MySQL GTID-based read routing (a GTID is a global transaction identifier; the client remembers the last one it wrote and asks for a replica that has applied it);
- PostgreSQL: compare a write's WAL position (LSN, the position in the write-ahead log) to the replica's replay position;
- MongoDB
afterClusterTime; - Cosmos DB session tokens;
- HTTP ETag with
If-Match.
All have the same shape: a monotone handle to a point in a history, held by the party that needs the guarantee.
A sketch of read-your-writes with a replica in SQL-like pseudo-code:
-- On write (primary), return the log position of the commit:
UPDATE profiles SET display_name = 'Ana' WHERE user_id = 7;
SELECT pg_current_wal_lsn(); -- e.g. '0/5000A10' → client keeps this token
-- On the next read, route to a replica only if it has caught up:
-- replica check: pg_last_wal_replay_lsn() >= '0/5000A10'
-- otherwise: wait a few ms, or read from the primary.Why session guarantees are uniquely dangerous
They are the only guarantees here broken by an infrastructure change rather than a concurrency event. Each of these silently voids the guarantee:
- a load balancer that reroutes the user;
- a client that switches networks;
- a retry that lands in another region;
- a CDN (content delivery network, a cache close to users);
- a second service that reads the same replicas without the token.
None of the people who make these changes know that a consistency decision was in their hands.
Sticky routing (always send this user to the same replica) is the alternative to tokens. It is worse than it looks. It converts a consistency guarantee into a load-balancing constraint, which then fights failover, autoscaling and cell isolation (splitting a service into independent cells so one failure stays small). The cost moves into the topology, where somebody who is optimizing something else will trade it away.
Consistent prefix reads
A reader never observes a state that is not a prefix of the write order: if writes happened in order w1, w2, w3, you may see (w1), (w1, w2) or (w1, w2, w3), but never (w1, w3). None of the four session guarantees imply it. A replicated log gives it for free. Cosmos DB sells it as a level. It is the single-object shadow of read skew from Transactional isolation, and its absence produces the reply-before-the-message bug in cross-partition replication: the reply travels on a faster partition and arrives before the message.