The problem: Snip in two regions
Snip now serves Europe from Frankfurt and the Americas from Virginia. Each region has replicas of the links database,
and changes are copied between them in about 100 ms, usually. An owner in Berlin edits x7Kp to point at the summer
sale, then opens the dashboard, which happens to read from a replica that hasn't caught up. Their edit has vanished.
They refresh, land on a different replica, and it's back. Refresh again: gone.
Every replicated system answers the question "what can a reader see after a write?" The answers are called consistency models, and choosing one per feature is a design decision, not a database setting you leave at the default.
The ladder
From strongest to weakest, with what each means for Snip's users:
| Model | The promise | Snip example |
|---|---|---|
| Linearizable | The system behaves as if there were one copy: once a write completes, every later read, anywhere, sees it | Claiming a custom short code: two owners must never both get summer |
| Sequential | Everyone sees all operations in the same order, though maybe late | (Rarely chosen on its own) |
| Causal | If one change could have caused another, everyone sees them in that order | A reply to a comment never appears before the comment |
| Read your writes | You always see your own changes | The Berlin owner sees their edit at once |
| Monotonic reads | Once you've seen a value, you never see an older one | The edit doesn't flicker in and out on refresh |
| Eventual | If writes stop, all replicas eventually agree | Click counts in the dashboard |
The first two are about all readers; read-your-writes and monotonic reads are session guarantees, about what one user sees. Eventual consistency, in Werner Vogels's definition, guarantees only that if no new updates are made, "eventually all accesses will return the last updated value", which says nothing about what you see in the meantime.
What survives a partition
Stronger models need replicas to coordinate, and coordination needs the network. Jepsen's summary of the models is blunt:
- Linearizable and sequential cannot stay available on both sides of a network split. One side has to refuse.
- Causal and read-your-writes are sticky available: they keep working during a split as long as each client keeps talking to the same replica.
- Monotonic reads and eventual consistency can be totally available: any reachable replica can answer.
That's the real trade behind the CAP theorem (08.03 CAP and PACELC, without the myths), and it's also a latency trade: even with no partition, a linearizable read across regions waits for a cross-region round trip, around 100 ms between Frankfurt and Virginia.
Getting the session guarantees cheaply
Most of what users notice is fixed by the two session guarantees, without making the whole system linearizable:
- Read your writes: after an owner writes, send their reads to the primary (or to a replica that has caught up to their write's position) for a few seconds. Snip stores "last write at log position 1,840,221" in the owner's session; a replica serves them only if it's applied at least that far (04.07 Replication: leaders, followers and lag).
- Monotonic reads: pin each user to one replica (by hashing their ID), so refreshes don't bounce between replicas with different lag.
4 messages. Use Next and Back to follow them in order.
Text version
- Owner in Berlin → Replica 1 (caught up): GET x7Kp — The first read goes to a replica that has the edit.
- Replica 1 (caught up) → Owner in Berlin: summer sale (reply) — The owner sees their new destination.
- Owner in Berlin → Replica 2 (300 ms behind): GET x7Kp — The refresh is load-balanced to a different replica, still behind.
- Replica 2 (300 ms behind) → Owner in Berlin: spring sale (reply) (fails) — Time appears to go backwards: the old destination is back. Pinning the user to one replica stops this.
Choosing per feature
Strong consistency is expensive, so spend it where a wrong answer is costly:
- Uniqueness, money, permissions: linearizable. Snip claims custom codes with a single leader for that key (or consensus, 08.06 Consensus and Raft, intuitively), and accepts that claiming a code fails during a partition.
- A user's own data: read your writes and monotonic reads.
- Counters, feeds, analytics: eventual, with staleness you've agreed (06.04 Invalidation and staleness).
Seen in production
Jepsen
ReferenceConsistency models
Jepsen arranges models in a hierarchy: for single objects, linearizable implies sequential, which implies causal, which in turn implies the weaker session guarantees such as read your writes and monotonic reads. It defines a linearizable system as one where every operation appears to take place atomically, in an order consistent with real time, and notes that models at or stronger than sequential cannot be totally available, while read your writes and causal consistency can be sticky available.
What we foundA map of consistency models, with which ones can stay available during a network partition.
Consistency Models (Jepsen)jepsen.io ↗Amazon
DocsS3
S3 now provides strong read-after-write consistency for all GET, PUT and LIST operations and for changes to object tags, ACLs and metadata: after a successful write, overwrite or delete, any later read gets the latest version. The page says this comes without changes to performance or availability, and at no additional cost.
What we foundStrong read-after-write consistency at enormous scale, with no extra cost or speed penalty.
Amazon S3 Strong Consistencyaws.amazon.com ↗Snip lets owners claim custom codes like snip.link/summer. Two owners in different regions claim 'summer' at the same moment. Which model does the claim need?
Recap
Interview questions
Explain strong versus eventual consistency. What's in between?