Part 4 · Databases & Data at Scale
Consistency Models: Strong, Eventual and In Between
“Eventually consistent” can mean your own comment vanishes on refresh. Consistency is a spectrum, not a switch: linearizable, causal, session guarantees and eventual — what each promises, how conflicts get merged, and why clocks can't be trusted.
On this page
The Problem
Data is often stored in more than one place. Each stored copy is called a replica. When someone says "it's eventually consistent", it sounds safe. Here is what it can mean in practice:
- You post a comment, refresh, and it's gone. Refresh again and it's back.
- A friend replies to your message, but their reply shows up before your message.
- Your like count says 102 on your phone and 99 on your laptop.
- You change your password, and the old one still works for a minute.
Some of these are fine. Others are serious bugs. What decides it is the consistency model. A consistency model is a set of rules that says what a reader is allowed to see when data has many copies. The last lesson (CAP) talked about "consistent or available". Here you will see that consistency is not just on or off. It is a spectrum (a range), and there are useful stops between the two ends.
The Core Idea
Think about news spreading about a cricket match result.
- Strong consistency is like the stadium scoreboard. Everyone looking at it sees the same score at the same moment. When it changes, nobody can see the old score afterwards.
- Eventual consistency is like the news spreading through WhatsApp groups. Some people find out in seconds, others in minutes. For a while, different people "know" different scores. But if no new runs are scored, eventually everyone ends up with the same, correct score.
- The in-between models are guarantees like "you'll never see an older score after you've seen a newer one" or "you'll always see the score you posted".
Stronger guarantees are easier to think about, but they cost more. They need the servers to talk to each other (coordination), they add delay (latency), and they can stop working during failures. Weaker guarantees are faster and stay available, but developers and users must handle the odd results.
How It Works
The spectrum
1. Linearizability (strong consistency)
Linearizability is a rule that says the system must behave as if there were only one copy of the data. Every operation seems to happen instantly, at one moment between its start and its finish. Think of one shared notebook that everyone reads and writes in turn.
- Once a write completes, every later read, by anyone, anywhere, sees it (or something newer).
- Once any reader sees a new value, no reader can see the old one again.
Needed for:
- uniqueness (usernames, one booking per seat),
- locks and leader election (picking one server as the leader, and never two),
- account balances and money movement,
- "compare-and-set" operations (change a value only if it still has the value you expect, for example "set to 11 only if it is still 10").
How it is done: read from the single leader, or use a consensus protocol. A consensus protocol (such as Raft or Paxos) is a set of steps that lets several servers agree on one value, even if some servers fail. Some systems also use carefully designed quorums. A quorum is a majority of the copies that must answer before an operation counts. Cost: extra messages between servers, and part of the system can become unavailable during a network partition (a break in the network, see CAP).
2. Sequential consistency
Sequential consistency is a rule that says all nodes (servers) see the operations in the same order, and each client's own operations stay in the order the client made them. But the shared order does not have to match real time. It is a little weaker than linearizable. You will mostly meet it in theory and in CPU memory models (the rules for how processor cores see each other's writes).
3. Causal consistency
Causal consistency is a rule that says: if one event caused or depends on another, everyone sees them in that order. Events that are not related can show up in different orders for different people. Example: a reply must never appear before the question it answers.
- “Anyone free for lunch?”
- replicate event 1
- event 1
- Ravi replies “Yes! 1 pm?”depends on event 1
- Causal rule — anyone who sees the reply must already have seen the question
Causal consistency is a good middle choice. It stops the most confusing problems (answers before questions, comments on posts you cannot see). It still allows high availability and speed.
4. Session guarantees (per-client rules)
Session guarantees are small promises made to one client (one user session). They are easy for users to notice. They were described in early research on distributed systems, and many databases and apps use them. Do not mix them up: causal consistency orders events for everyone, while a session guarantee only protects one user's own view.
- Read-your-writes: after you write something, you always see it. (Your comment doesn't vanish after refresh.)
- Monotonic reads: once you've seen a value, you never see an older one later. (Your like count never goes 102 → 99 → 102.)
- Monotonic writes: your writes are applied in the order you made them. (Changing your name to "A" and then "B" never ends up as "A".)
- Writes-follow-reads: if you read something and then write based on it, your write is ordered after what you read. (Your reply is never placed before the post you replied to.)
Lesson 24 showed how to build the first two. Read a user's own data from the leader, and keep each user on the same replica.
5. Eventual consistency
Eventual consistency is a rule with one promise: if no new writes happen, all copies will end up with the same value. Ending up the same is called "converging". The rule does not say when this happens. It also does not say what you see before then.
In practice, "eventually" is usually milliseconds to seconds. During failures or heavy load it can take much longer.
Fine for:
- like and view counts,
- follower counts,
- "last active" status,
- search indexes,
- recommendation lists,
- CDN-cached pages,
- DNS.
How copies converge: handling conflicts
In multi-leader and leaderless systems (lesson 24), two copies can accept different writes to the same data at the same time. This is a conflict. Something must decide the final value. There are four common ways.
Last-write-wins (LWW). This is a rule that gives each write a timestamp and keeps only the write with the latest one.
- ✅ Simple, and used widely (Cassandra uses timestamps this way).
- ❌ Silently discards the other write.
- ❌ Relies on clocks, and clocks on different machines drift apart (see below).
Version vectors (vector clocks). A version vector is a small list of counters, one per node. Each write carries the list, so it records which versions it has already seen. With this list the system can tell if one write came after another, or if the two writes were truly concurrent (made at the same time without seeing each other). Only concurrent writes are real conflicts. They can then be merged, or shown to the app. Amazon's Dynamo used vector clocks to find conflicting cart versions.
CRDTs (Conflict-free Replicated Data Types). A CRDT is a data type built so that any two copies can always be merged automatically. The result is the same whatever order the merges happen in. Examples:
- G-Counter / PN-Counter: a G-Counter only counts up. Each replica counts its own increments, and the total is the sum. Two replicas that both add likes never lose any. A PN-Counter uses two G-Counters (one for adds, one for removes) so it can also count down.
- OR-Set (observed-remove set): a set where you can add and remove items (like cart items). A remove only deletes the adds that the remover had seen, so a new add made at the same time is kept.
- Sequence CRDTs: for collaborative text editing.
CRDTs power features like collaborative editing and offline-first apps, and are available in some databases (for example, Riak, and Redis Enterprise's active-active mode).
Application-level merge. Keep both versions and let the app, or the user, decide. For example: "This document was edited on two devices. Which version do you want to keep?"
Time and ordering: why clocks are tricky
Distributed systems often need to know what happened first. But:
- Physical clocks drift. A physical clock is the normal wall clock on a machine. Servers keep their clocks close using NTP (Network Time Protocol, which copies the time from a trusted server). They can still be off by milliseconds, and sometimes much more. A write with a "later" timestamp might really have happened earlier.
- Leap seconds and clock jumps have caused real outages. A leap second is one extra second that is added to the world clock now and then.
Solutions:
- Lamport clocks: a Lamport clock is a simple counter. It goes up with every event, and it also jumps ahead when a message with a bigger number arrives. This gives an order that respects cause and effect, and it does not use wall-clock time. (Leslie Lamport's classic 1978 paper.)
- Hybrid Logical Clocks (HLC): an HLC joins physical time with a logical counter, so timestamps stay close to real time and still keep cause before effect. Databases like CockroachDB use them.
- TrueTime (Google Spanner): TrueTime is Google's clock service. Special time servers with GPS receivers and atomic clocks give each machine the current time plus an uncertainty range (a few milliseconds). Spanner deliberately waits out that uncertainty before it finishes a commit. This way, timestamps always match real-time order. That is how it offers strong consistency across the globe.
The cost of strong consistency
Strong consistency across continents means waiting for messages to cross oceans. So global systems often keep most data eventually consistent. They make only the critical operations strongly consistent. (These times are typical rough numbers, not fixed rules.)
- +Trivial to implement
- −Silently drops the “losing” write
- −Trusts drifting clocks
- +Detect whether writes were truly concurrent
- •Conflicts go to the app to merge
- +Always merge automatically, in any order
- +Counters, sets, collaborative text
- −Only for data types designed for it
Matching models to features
| Feature | Model it needs | Why |
|---|---|---|
| Bank balance at withdrawal | Linearizable | Must never overspend |
| Username / seat booking | Linearizable (or a unique constraint on one primary) | Only one winner |
| My own profile after editing | Read-your-writes | Users think a save "failed" otherwise |
| Comment threads, chat | Causal | Replies must follow what they reply to |
| Feed scrolling | Monotonic reads | Items shouldn't flicker in and out |
| Shopping cart | Eventual + good merging (CRDT-like) | Always accept adds, merge later |
| Like / view counts | Eventual | Small delays are fine |
| Search results | Eventual | The index updates a second later |
Trade-offs
- Stronger models: simpler reasoning and fewer surprise bugs, but more latency, more coordination, and less availability during failures.
- Weaker models: fast, scalable and highly available, but you must handle stale reads, conflicts and odd orderings in your app and UI.
- Session guarantees and causal consistency are often the best value: they fix what users actually notice, without paying for global strong consistency.
- Conflict handling based on clocks (LWW) is easy, but it can lose data silently. Use it only where losing an update is acceptable.
In the Real World
Collaborative editing. Google Docs has long used a technique called operational transformation, which changes each edit so that edits made at the same time still fit together. Figma has described its multiplayer system as inspired by CRDTs, with a central server that orders the changes. Both let many people edit at once and still end up with the same document.
Amazon's cart and "resurrected" items. In the Dynamo paper, Amazon explains that merging conflicting versions of a cart kept every "add", but that this could occasionally make deleted items reappear. Amazon accepted that trade, because losing an "add to cart" was worse.
Social media counts. Like, view and follower counts on major platforms are eventually consistent. That's why a number can differ slightly between devices or jump after a refresh. For these features, speed and availability matter more than exactness.
Cloudflare's leap-second bug. On 1 January 2017, a leap second made part of Cloudflare's DNS software calculate a negative time difference. The code did not expect this, so it failed and some customers saw errors. It is a real example of why relying on wall-clock time in distributed systems is risky.
Google Spanner's TrueTime. Spanner is one of the few systems offering external consistency (a strong form of linearizability) globally. It's possible because of dedicated time infrastructure and a willingness to wait a few milliseconds on each commit.
Interview Questions
Q1What's the difference between linearizability and eventual consistency?
Linearizability makes a replicated system behave like a single copy: once a write completes, every later read anywhere sees it. Eventual consistency only promises that copies converge if writes stop, with no bound on when and no guarantee about what you see meanwhile.
Q2A user posts a comment, refreshes, and it's gone. Which guarantee is missing, and how do you provide it?
Read-your-writes. Serve the user's own reads from the leader (or a replica that has caught up to their last write position) for a while after they write, or keep the new comment in client state until the server confirms it.
Q3Why is causal consistency often called a sweet spot?
It stops the most confusing problems, such as replies before questions and comments on posts you cannot see. It does this without asking every server to agree on every operation, so it stays fast and available even during network partitions.
Q4Why is last-write-wins dangerous?
It relies on timestamps from clocks that drift, so a write that really happened later can lose, and the losing write is dropped with no error. Use it only where losing a concurrent update is acceptable.
Q5What is a CRDT? Give an example.
A CRDT is a replicated data type with a merge that gives the same result in any order and even if it runs twice. (In technical words: the merge is commutative, associative and idempotent.) So each replica can accept writes on its own and they still converge. A G-Counter keeps one count per replica and adds them up, so concurrent likes are never lost.
Q6How does Spanner achieve global strong consistency?
TrueTime gives each server the current time with a known uncertainty range (it uses GPS and atomic clocks). Spanner gives each commit a timestamp and waits out that uncertainty before the commit becomes visible. So timestamp order matches real-time order. The data is also copied with Paxos.
Key Takeaways
- Consistency is a spectrum: linearizable → sequential → causal → session guarantees → eventual.
- Linearizability acts like one copy. It's needed for money, uniqueness and locks, but costs coordination and latency.
- Causal consistency and session guarantees (read-your-writes, monotonic reads) fix the anomalies users notice most, at a lower cost.
- Eventual consistency only promises convergence. Handle conflicts with LWW, version vectors, CRDTs or app-level merges.
- Clocks are unreliable, so use logical clocks, HLCs or TrueTime-style approaches. Match the model to each feature, rather than picking one for everything.
Further Reading
- Designing Data-Intensive Applications by Martin Kleppmann (chapter 9, "Consistency and Consensus")
- The Jepsen website's interactive map of consistency models
- Werner Vogels' article "Eventually Consistent, Revisited"
- Doug Terry's paper "Replicated Data Consistency Explained Through Baseball"
- Leslie Lamport's paper "Time, Clocks, and the Ordering of Events in a Distributed System" (1978)
- The Google Spanner paper (OSDI 2012)
- The crdt.tech website for learning about CRDTs
- The System Design Primer on GitHub (section "Consistency patterns")
Published by Jainik · Last updated · How these lessons are made
Keep learning
Part of the study guide
Related series