Strong vs eventual consistency
Published
The moment you keep more than one copy of data, on replicas, in a cache, in another region, the copies can disagree for a while. Consistency is the promise you make about what a reader can see during that while.
Strong consistency: once a write is acknowledged, every read anywhere returns it (or something newer). The system behaves as if there were one copy. Eventual consistency: if writes stop, all copies will agree eventually, but a read right now might return an older value.
A cricket scoreboard explains it. The scorer's book is the leader. The big screen in the stadium, the TV graphic and the app on your phone are copies. Eventually they all say 287/4, but for a few seconds the app may still say 283/4. For a score, nobody minds. For your bank balance, everybody does.
You edit your Instagram bio, tap Save, and the page reloads showing your old bio. A few seconds later it shows the new one. What happened, and is it a bug?
See it happen#
You live in Delhi and change your display name. The leader is in Mumbai and copies the change to two followers asynchronously. Move the sliders and switch policies.
The thing to notice: staleness is not a defect of one policy. It is what asynchronous replication is. Every policy either accepts it, routes around it, or pays at write time to remove it.
The guarantees in between#
"Strong or eventual" is a spectrum, and most real needs sit in the middle:
- Read your writes: you always see your own changes, even if others see them later. Fixes the Instagram bio case, which is a classic eventual consistency symptom.
- Monotonic reads: you never see time go backwards. Without it, refreshing twice can show the new value, then the old one, if the second read hits a staler replica. Pinning a user to one replica gives you this.
- Causal consistency: if B was written because of A (a reply to a comment), nobody sees B without A.
- Linearizable (the precise name for the strong end): every operation appears to happen at one instant, in an order that respects real time.
Read your writes and monotonic reads are cheap and fix most user visible weirdness. Ask for them before asking for full strong consistency.
What strong costs#
To make a write visible everywhere before acknowledging it, the system has to coordinate: wait for a quorum of replicas, or route every read to one leader. That costs latency (a round trip to other replicas, possibly in other regions) and availability (if enough replicas are unreachable, the system must refuse rather than risk a stale answer). That is the CAP theorem's trade during a network partition, and PACELC's addition: even with no failure, you trade latency for consistency. Both are covered properly in CAP theorem and replication and quorums.
Amazon's Dynamo paper (2007) describes a cart designed to always accept writes, even during failures, because refusing "add to cart" loses sales. Concurrent versions of a cart are merged later by taking the union of items. The documented side effect: an item you deleted could occasionally reappear. Amazon judged a resurrected item cheaper than a refused one. That is a business decision dressed as a database setting.
Choosing per feature, not per system#
The senior move is to stop asking "is our system consistent?" and decide per piece of data:
| Choice | What you gain | What you pay | Pick it when |
|---|---|---|---|
| Strong | No anomalies to reason about. Read always reflects the last acknowledged write. | Higher latency, lower availability during failures, harder to scale across regions. | Money and balances, inventory at the moment of sale (the last Tatkal seat), unique usernames, locks and leader election. |
| Read your writes / monotonic | Users never see their own change vanish or time go backwards. Cheap. | Other users may still see older data for a moment. | Profiles, settings, posts and comments: almost every user facing edit. |
| Eventual | Fast local reads, writes accepted anywhere, survives partitions. | Stale reads, and concurrent writes need a merge rule. | Like counts, view counts, feeds, recommendations, search indexes, analytics, caches. |
Many databases let you choose per request. DynamoDB reads are eventually consistent by
default, and ConsistentRead: true gives a strong read for twice the read capacity cost.
Cassandra lets each query pick a consistency level, ONE, QUORUM or ALL. MongoDB has
read and write concerns. Postgres read replicas are asynchronous, so reading from them is
eventually consistent unless you route the writer's next reads to the primary. Google Spanner
offers strong consistency across continents by waiting out clock uncertainty with TrueTime,
which is why it costs what it costs.
- DynamoDBEventual by default, ConsistentRead for strong
- CassandraTunable per query: ONE, QUORUM, ALL
- PostgreSQLStrong on the primary, async replicas lag
- MongoDBreadConcern and writeConcern
- Google CloudSpanner: strong across regions via TrueTime
- RedisAsync replication, replicas can lag
In the interview#
Checkpoint#
1. You save a new bio and the reload shows the old one. What is the likely cause?
2. What does strong consistency cost?
3. Refreshing a page shows a new value, then the old value again. Which guarantee is missing?
- Strong: every read sees the latest acknowledged write. Eventual: copies converge later.
- In between: read your writes, monotonic reads, causal. Cheap and usually enough.
- Strong costs latency and availability. CAP during failures, PACELC always.
- Decide per piece of data: money and uniqueness strong, counters and feeds eventual.
- Async replicas mean stale reads. Route the writer to the primary briefly.
Once data has more than one copy, consistency is the promise about what readers see while copies disagree. Strong consistency, or linearizability, means every read after an acknowledged write sees it, as if there were one copy; it requires coordination, so it costs latency and, during partitions, availability. Eventual consistency means copies converge once writes stop, so reads are fast and local but may be stale, and concurrent writes need a merge rule. In between are cheap guarantees that fix most user visible problems: read your writes, monotonic reads and causal consistency. I decide per piece of data rather than per system: balances, inventory at the point of sale and unique names are strong; likes, feeds, search and analytics are eventual; user edits get read your writes by routing the writer's reads to the primary for a short window. Databases like DynamoDB, Cassandra and MongoDB let me choose per request.