Consistency Patterns
Weak, eventual and strong consistency describe when a write becomes visible to readers. Learn each one, the session guarantees users actually notice, and how quorums (R + W > N) give strong reads from replicated data.
In a nutshell
- Weak: a read may never see a write (fine for live video or game positions).
- Eventual: if writes stop, all replicas converge; meanwhile reads may be stale.
- Strong: every read sees the latest completed write, at the cost of latency and availability.
- With N replicas, writing to W and reading from R with R + W > N guarantees a read overlaps the latest write.
Three levels of consistency
When the same data lives on several machines, a write lands on one of them first. Consistency models describe what readers may see while the write spreads.
| Model | After a write, a read… | Cost | Good for |
|---|---|---|---|
| Weak | may or may not see it, and is not promised to ever | Cheapest, fastest | Live video, voice calls, multiplayer game positions: old data is useless anyway |
| Eventual | may see old data for a while, but all replicas converge if writes stop | Cheap, highly available | Social feeds, likes, DNS, search indexes, product catalogues |
| Strong | always sees the latest completed write | Slower; may be unavailable during partitions | Payments, inventory, account settings, anything you must not get wrong |
Eventual consistency in action
The most common source of stale reads is replication lag: the leader has the write, a follower does not yet. If a user writes to the leader and then reads from a follower, their own change seems to vanish.
Replication lag: "where did my change go?"
All steps The write is safe on the leader, but a read served by a lagging follower shows the old name.
- The user changes their display name. The write goes to the leader.
- The leader confirms the write.
- The page reloads and the read is sent to a follower (reads are spread across replicas).
- The follower has not received the change yet, so it returns the old name. The user thinks the save failed.
- A moment later the change arrives at the follower. Eventually every replica agrees.
Diagram as text
- The user changes their display name. The write goes to the leader.
- The leader confirms the write.
- The page reloads and the read is sent to a follower (reads are spread across replicas).
- The follower has not received the change yet, so it returns the old name. The user thinks the save failed.
- A moment later the change arrives at the follower. Eventually every replica agrees.
Guarantees users notice
Full strong consistency is expensive, but a few weaker guarantees fix most of what users actually see:
| Guarantee | Promise | A common way to provide it |
|---|---|---|
| Read-your-writes | You always see your own changes. | Send a user's reads to the leader for a short time after they write, or track the write's version and wait until the replica has it. |
| Monotonic reads | You never see time go backwards (newer data, then older). | Pin each user to the same replica. |
| Consistent prefix | You see events in the order they happened (an answer never before its question). | Keep related writes in the same partition, in order. |
Quorums: strong reads from replicas
Many replicated stores use quorums. With N replicas, a write succeeds once W replicas have it, and a read asks R replicas and takes the newest value. If R + W > N, every read set overlaps every write set in at least one replica, so the read sees the latest write.
N = 3, W = 2, R = 2
Diagram as text
- Write v7 → Replica 1: W
- Write v7 → Replica 2: W
- Read → Replica 2: R
- Read → Replica 3: R
- W = N, R = 1: fast reads, but a write fails if any replica is down.
- W = 1, R = N: fast writes, slow reads.
- W = R = majority (2 of 3, 3 of 5): a common balance that survives a minority of failures.
- R + W ≤ N: faster and more available, but reads can miss the latest write (eventual consistency).
A quorum read: ask R replicas, keep the newest version
import java.util.*;
class Quorum {
record Versioned(long version, String value) {}
// True when every read set must overlap every write set.
static boolean isStrong(int n, int r, int w) {
return r + w > n;
}
// The newest value among the replicas that answered.
static Versioned read(List<Versioned> answers, int r) {
if (answers.size() < r) {
throw new IllegalStateException("only " + answers.size() + " of " + r + " replicas answered");
}
return answers.stream()
.max(Comparator.comparingLong(Versioned::version))
.orElseThrow();
}
}def is_strong(n, r, w):
"""True when every read set must overlap every write set."""
return r + w > n
def quorum_read(answers, r):
"""answers: (version, value) pairs from the replicas that replied."""
if len(answers) < r:
raise RuntimeError(f"only {len(answers)} of {r} replicas answered")
return max(answers, key=lambda a: a[0])Common mistakes
- Making everything strongly consistent "to be safe" and paying for it in latency and outages.
- Spreading reads across followers without handling read-your-writes, so users think their saves failed.
- Assuming eventual means "within a second". Without monitoring replication lag, "eventually" can be minutes during an incident.
- Using R + W ≤ N and expecting reads to always be current.
Interview questions
Try answering out loud before you open each one.
A user updates their profile and still sees the old one. Why, and how do you fix it?
Reads are probably served by a follower that has not received the write yet (replication lag). Fix it with read-your-writes: route that user's reads to the leader for a short window after a write, or record the write's version and only read from replicas that have caught up to it.
With 5 replicas, what R and W give strong consistency while tolerating 2 failures?
R = 3 and W = 3. R + W = 6 > 5, so read and write sets overlap, and with 5 replicas, 3 are still reachable when 2 are down, so both reads and writes keep working.
When is eventual consistency the right choice?
When a briefly stale value does no harm and availability or speed matters more: counters, feeds, recommendations, caches, search results. Not for balances, stock levels or anything that must not be double-spent.
Check yourself
Related topics
Further reading
- Eventually Consistent Werner Vogels, 2008
- Designing Data-Intensive Applications (chapter 5, Replication) Martin Kleppmann, O'Reilly
Your notes
Saved in this browser as you type.
Finished this topic?
Mark it read to track your progress, then carry on with the next one.