Skip to main content

Consistency Models

One-line summary: A consistency model is the contract between a distributed store and its clients about when and in what order writes become visible to reads.


๐Ÿงฉ Core Conceptsโ€‹

When data is replicated across nodes (see Replication), reads and writes can race. A consistency model defines what guarantees you get. Stronger models are easier to reason about but cost latency and availability (recall the CAP theorem and PACELC's else-latency-vs-consistency trade-off).


๐Ÿ“ˆ The Consistency Spectrumโ€‹

From strongest (most coordination, highest latency) to weakest (most available, lowest latency):

flowchart LR
Strong["Strong / Linearizable<br/>latest write, global order"]
Seq["Sequential<br/>one global order, not real-time"]
Causal["Causal<br/>cause-before-effect preserved"]
Eventual["Eventual<br/>converges given no new writes"]
Strong --> Seq --> Causal --> Eventual
Strong -. "more coordination / higher latency" .-> Strong
Eventual -. "more available / lower latency" .-> Eventual
ModelGuaranteeCostExample
Strong (Linearizable)Reads always return the most recent write; behaves like a single copy in real timeHighest latency, lowest availabilityetcd, ZooKeeper, Spanner
SequentialAll nodes see operations in the same order, but not necessarily real-time orderHighSome replicated logs
CausalOperations that are causally related are seen in order; concurrent ops may differMediumCOPS, MongoDB causal sessions
EventualIf writes stop, all replicas eventually convergeLowestDynamoDB, Cassandra, DNS

๐Ÿ‘ค Client-Centric (Session) Guaranteesโ€‹

Even under eventual consistency, these per-client guarantees make behavior sane for a single user session:

  • Read-your-writes: after you write a value, your subsequent reads see it (never a stale value you just overwrote). Example: after editing your profile, you see the update immediately.
  • Monotonic reads: once you read a value, you never see an older value on later reads. No "time-travel backwards."
  • Monotonic writes: your writes are applied in the order you issued them.
  • Writes-follow-reads: a write made after reading a value happens-after that value.
sequenceDiagram
participant U as User (one session)
participant R1 as Replica A
participant R2 as Replica B
U->>R1: write(name = "Ada")
R1-->>U: OK
U->>R2: read(name)
Note over R2: Without read-your-writes:<br/>may return old value โŒ
Note over R2: With sticky session /<br/>version tracking: returns "Ada" โœ…

๐Ÿ—ณ๏ธ Quorum Reads & Writes (W + R > N)โ€‹

Dynamo-style stores tune consistency with three numbers:

  • N = number of replicas that store each key
  • W = replicas that must acknowledge a write before it's considered successful
  • R = replicas that must respond to a read before returning

Strong-consistency rule of thumb: if W + R > N, the read and write quorums overlap by at least one node, so every read is guaranteed to see the latest write.

flowchart TD
subgraph N["N = 3 replicas"]
A[Replica 1]
B[Replica 2]
C[Replica 3]
end
W["Write quorum W=2"] --> A
W --> B
R["Read quorum R=2"] --> B
R --> C
B -. "overlap guarantees latest value" .-> R
Config (N=3)W + RProperty
W=3, R=14 > 3Strong; fast reads, slow/less-available writes
W=1, R=34 > 3Strong; fast writes, slow reads
W=2, R=24 > 3Balanced strong consistency (common default)
W=1, R=12 < 3Eventual; fastest & most available, may read stale

๐Ÿ”€ Conflict Resolutionโ€‹

When concurrent writes diverge (common in AP / multi-leader systems), replicas must reconcile:

  • Last-Write-Wins (LWW): keep the write with the highest timestamp. Simple but loses data on true concurrency and depends on clock sync. Used by Cassandra by default.
  • Vector clocks: track causality per replica to detect whether writes are ordered or truly concurrent; concurrent writes are surfaced as siblings for the app (or a merge function) to resolve. Used by Riak / Dynamo.
  • CRDTs (Conflict-free Replicated Data Types): data structures (counters, sets, maps) mathematically designed so concurrent updates always merge deterministically without conflicts. Used by Redis CRDTs, Riak, collaborative editors.
flowchart TD
Conflict{"Concurrent writes<br/>detected?"}
Conflict -->|LWW| L["Pick highest timestamp<br/>โš ๏ธ may drop a write"]
Conflict -->|Vector Clocks| V["Detect causal vs concurrent<br/>expose siblings to app"]
Conflict -->|CRDT| D["Auto-merge deterministically<br/>โœ… no data loss"]

Vector clock exampleโ€‹

Replica A writes: {A:1}
Replica B writes: {B:1} โ†’ concurrent (neither dominates) โ†’ sibling / merge
Replica A reads {A:1,B:1}, writes: {A:2,B:1} โ†’ dominates {A:1} โ†’ supersedes

๐ŸŽ›๏ธ Tunable Consistencyโ€‹

Modern stores let you choose the model per request, dialing between availability/latency and correctness:

StoreHow to tune
CassandraPer-query consistency level: ONE, QUORUM, LOCAL_QUORUM, ALL
DynamoDBConsistentRead: true for strong reads, else eventual
MongoDBwriteConcern (w=majority) + readConcern (majority/linearizable) + readPreference
RiakPer-bucket / per-request n_val, r, w

This lets a single application use strong consistency for money and eventual consistency for analytics/feeds โ€” the right trade-off per operation.


โš–๏ธ Trade-offs / When to Useโ€‹

  • Strong / linearizable: use for correctness-critical data โ€” balances, inventory, locks, unique constraints. Accept higher latency and reduced availability under partitions.
  • Causal: great sweet spot for social apps โ€” preserves "reply appears after the post" without full linearizability cost.
  • Eventual + session guarantees: use for high-scale, latency-sensitive workloads (feeds, carts, telemetry) where users mainly need to see their own actions consistently.
  • Quorum tuning (W+R>N): your lever to move along the spectrum without changing databases.
  • Conflict strategy matters: prefer CRDTs/vector clocks over LWW when losing concurrent writes is unacceptable.

Interview Questionsโ€‹

  • Compare linearizability vs eventual consistency and give examples where each is appropriate.
  • How would you design a shopping cart so users don't lose their items while keeping high availability?
  • Explain how quorum parameters (W, R, N) affect consistency and latency.

Production Checklistโ€‹

  • Define which operations require strong consistency vs eventual consistency and document per-endpoint guarantees
  • Instrument client-centric session guarantees where needed (read-your-writes, monotonic reads)
  • Ensure clocks are reasonably synchronized (NTP) if using timestamp-based conflict resolution
  • Provide clear API documentation stating consistency expectations

Testing & Monitoringโ€‹

  • Run tests that assert client guarantees under leader failover and replication lag
  • Simulate conflicts and verify chosen conflict-resolution strategies (LWW vs vector clocks vs CRDTs)
  • Monitor per-operation latency, error rates, and observed staleness windows
  • CAP Theorem โ€” the C-vs-A trade-off these models refine
  • Replication โ€” leader/follower & quorum mechanics that implement these models
  • Databases โ€” which stores offer which consistency guarantees
  • Message Queues โ€” delivery guarantees (at-least/at-most/exactly-once) as a consistency analog

โ† Back to System Design ยท ยฉ sparshjaswal