Strong, eventual, causal — the spectrum of what 'consistent' means.
If you are new here: When engineers say a system is "consistent," they could mean five completely different things. Linearizable, sequential, causal, eventual, and session consistency are all real guarantees — each one weaker than the last, each one cheaper than the last. Getting this vocabulary wrong in a design doc causes real bugs: your mobile team assumes "consistent" means "they see their own write immediately," your SRE assumes it means "ZooKeeper-level atomic," and neither team realizes they're talking about different things.
| Model | One-line intuition | Cost |
|---|---|---|
| Linearizable | Global real-time order — strongest | High latency, low availability under faults |
| Sequential | Everyone agrees on some total order | Slightly cheaper than linearizable |
| Causal | Respects cause-and-effect between related ops | Medium — only tracks dependencies |
| Eventual | Replicas converge when writes stop | Very cheap — no synchronization |
| Session | Read-your-own-writes for one client | Cheap — routing trick, not global sync |
Imagine your team writes a design document that says "the user-profile service is strongly consistent." At the meeting, everyone nods. Six months later, a mobile engineer opens a bug: "After I update my display name, refreshing the app sometimes shows the old name for a few seconds." The engineer who wrote "strongly consistent" meant eventual consistency with read-your-writes. The mobile engineer meant linearizable — same as a single-machine variable.
Nobody lied. They used the same word to mean different things.
This happens constantly in distributed systems. The word "consistent" spans a wide spectrum, and each point on that spectrum has a precise meaning, a real cost, and appropriate use cases. Picking the wrong model for a data type causes either silent data corruption (too weak) or unnecessarily slow, fragile systems (too strong).
In plain terms: "consistent" is not a yes/no property. It's a spectrum. Your job is to name the right point on that spectrum for each piece of data in your system — and then verify your infrastructure actually delivers it.
Linearizability is the gold standard. Under this model, every operation appears to take effect atomically at a single point between when it started and when it completed. All clients see the effects of operations in the same real-time order, as if there were one machine with one memory.
In plain terms: after any write completes, every subsequent read from any node returns that value. There's no "brief window of staleness." It behaves exactly like reading and writing a single variable on a single machine.
Analogy: Think of a bank ATM network. You withdraw $200 in New York. Two minutes later, your partner checks the balance at a London ATM. Linearizability means the London ATM must show the post-withdrawal balance. Showing the old balance — even for a few seconds — would be wrong for a financial ledger.
The cost: to achieve this, nodes must coordinate before answering. A write must reach a quorum and be acknowledged before it's visible. A strongly-consistent read must verify with a quorum that it's seeing the latest value. This adds latency on every operation and means that during a partition, a linearizable system must refuse to answer rather than risk serving stale data.
Tiny example: etcd (used by Kubernetes for cluster state) is linearizable. When a new pod is scheduled, the scheduler writes the assignment to etcd and waits for a quorum acknowledgment. Any other node that reads the pod state from etcd will see the same assignment. This is critical: two schedulers must never simultaneously think they're assigning the same pod.
Sequential consistency is one step weaker. All nodes agree on some total ordering of operations, but that ordering doesn't have to match wall-clock time. If two operations are concurrent (neither happened "before" the other in real time), the system can pick any order — as long as every node agrees on the same order.
In plain terms: think of it as everyone watching a replay of the same movie, where all the scenes appear in the same sequence for all viewers — but that sequence might differ slightly from the original filming order for concurrent scenes.
Analogy: A message board where two users post simultaneously. One post might appear before the other, or vice versa — but crucially, all users see them in the same order. User A in Tokyo and User B in São Paulo both see "Post #1 then Post #2" or both see "Post #2 then Post #1." They never disagree about the order.
Sequential consistency is cheaper than linearizable because you don't need to synchronize wall-clock timestamps across nodes. It's strong enough for many coordination problems where "we all agree on what happened" matters more than "we agree on exactly when it happened."
Causal consistency enforces a simpler guarantee: if operation B was causally related to operation A (Bob replied to Alice's post, which means Bob must have seen Alice's post), then every node will deliver A before B. Operations with no causal relationship can be reordered freely.
In plain terms: the system respects cause and effect. It guarantees that if you saw something and then reacted to it, your reaction will always appear after the thing you reacted to — from every observer's perspective.
Analogy: Imagine a group email thread. Alice sends an email. Bob reads it and replies. The causal consistency guarantee means that anyone receiving Bob's reply will also receive Alice's original email first. But if Carol sends a totally unrelated email at the same time as Alice, the two emails can arrive in any order — they're causally independent.
The cost: you need to track which operations "know about" which other operations. Systems do this with vector clocks or similar metadata attached to every message. This is significantly cheaper than linearizability (no global synchronization needed) but still requires more bookkeeping than eventual consistency.
Concrete sketch: MongoDB's "causally consistent sessions" use this model. Within one session, you'll always see operations in causal order — your writes appear before subsequent reads in that same session. Between sessions, ordering is looser.
Eventual consistency is the weakest common model: if you stop writing data, all replicas will eventually converge to the same value. During active writes, different readers can see wildly different snapshots. There's no guarantee about how long convergence takes or what intermediate states are visible.
In plain terms: given enough time with no new writes, all nodes will agree. During live traffic, you might read stale data, out-of-order updates, or even temporarily missing data.
Analogy: Imagine a company-wide announcement sent via email in batches. Some employees see the message in minutes; some see it hours later. If you stop sending new announcements, everyone eventually has all of them. But for a few hours, asking two employees about the announcement yields different answers.
Where this works beautifully: social feeds, product review counts, "users who liked this" tallies, any metric where showing a slightly stale number is fine and showing the wrong number briefly is acceptable. Facebook's like counter doesn't need to be perfectly atomic — showing "1.2k likes" vs "1,201 likes" has zero impact on user experience.
Where it breaks badly: account balances, inventory counts, idempotency keys, any state that drives irreversible decisions. An eventually consistent inventory system can "sell" the last item to two customers simultaneously.
Session consistency isn't a global property — it's a per-client contract. The most common variant is read-your-writes: after you write a value, your subsequent reads will always return at least that value (or something newer). Another common variant is monotonic reads: once you've read a value, you'll never see an older value in future reads.
In plain terms: within your session, the system behaves coherently from your perspective. You won't post a comment and then refresh the page to find it missing. But other users might still be a few seconds behind.
Analogy: Think of a sticky note you put on a shared whiteboard. You always see your own sticky note because you know you put it there. Someone in the next room might not see it for a minute while the camera feed updates. The guarantee is about your view, not everyone's view.
This is often implemented with a routing trick: read-after-write is implemented by routing a user's reads to the same replica where their writes land, or by propagating a write timestamp in a session cookie and refusing to serve reads from replicas that haven't caught up to that timestamp.
Tiny example: When you update your Twitter bio, the next page load shows your new bio — not the old one. Twitter uses session consistency for profile updates. You'll always see your own latest changes, even if other users see a briefly stale version until replication catches up.
The general rule is: pick the weakest model that satisfies your correctness requirements. Every step up the consistency ladder costs latency, availability, or both.
Here's the practical mapping:
| Data type | Right model | Why |
|---|---|---|
| Bank balance | Linearizable | Stale reads cause overdrafts |
| Session auth token | Session (read-your-writes) | You must see your own login |
| Social feed | Eventual | Lag is invisible to users |
| Forum thread order | Causal | Replies must follow posts |
| Leader election | Linearizable | Two leaders = split brain |
| Like count | Eventual | Approximate is fine |
Notice that most of your data probably falls in the "eventual" or "session" category. A small amount of critical state (financial records, locks, ownership) needs linearizability. Applying linearizability everywhere is over-engineering; applying eventual consistency everywhere causes bugs in the places that matter.
Strong consistency models slow your writes and reduce availability under faults. Weaker models need your application code to handle edge cases — stale reads, missing writes, conflicting versions — that a strongly consistent store handles automatically.
When you write "consistent" in a design doc, replace it with a specific model name. Ask: "Can a user ever see their own write disappear?" (session). "Can two processes simultaneously believe they own a lock?" (linearizable). "Is this counter just for display?" (eventual). Document the model in your API spec and your runbook, and write a test that verifies the model holds under the failure modes your system actually encounters.
Next: Split-Brain Problem — what happens when two nodes simultaneously believe they're the leader.
Linearizable — every op appears in one global order between start and end time; like a single machine illusion.