Skip to main content
📐System Design Fundamentals

Consistency Models in Distributed Systems: A Complete Guide

In a distributed system, data is replicated across multiple nodes for fault tolerance and performance. But replication creates a fundamental question: when...

📖 10 min read

Consistency Models in Distributed Systems: A Complete Guide

In a distributed system, data is replicated across multiple nodes for fault tolerance and performance. But replication creates a fundamental question: when a write happens on one node, when do other nodes reflect that change? The answer depends on the consistency model the system implements.

Consistency models define the rules for how and when updates become visible to readers. Choosing the right model is one of the most important decisions in system design, directly impacting latency, availability, and user experience.

Why Consistency Models Matter

Imagine you update your profile picture on a social media platform. If you immediately refresh the page and see your old picture, that is a consistency issue. Whether this matters depends on context. For a social media profile, a few seconds of staleness is acceptable. For a bank account balance after a transfer, it is not.

Different parts of the same system often need different consistency guarantees. Understanding the spectrum of consistency models lets you make targeted trade-offs rather than applying one-size-fits-all solutions.

The Consistency Spectrum

Model Guarantee Latency Availability
Linearizability Strongest — real-time ordering Highest Lowest
Strong Consistency All reads see latest write High Lower
Sequential Consistency Global order, not real-time Medium-High Medium
Causal Consistency Causally related ops ordered Medium Medium-High
Read-Your-Writes See your own writes Low-Medium High
Monotonic Reads Never see older data after newer Low High
Eventual Consistency Will converge eventually Lowest Highest

Linearizability

Linearizability is the strongest consistency model. It guarantees that every operation appears to take effect instantaneously at some point between its invocation and its completion. All operations are totally ordered, and this order is consistent with real-time ordering.

Timeline Example:

Client A: write(x=1) ----[start]--------[end]----
Client B:              read(x) --[start]---[end]--

With linearizability:
  Client B MUST see x=1, because Client A's write
  completed before Client B's read started.

Without linearizability:
  Client B might see x=0 (old value), because
  the system hasn't propagated the write yet.

Use cases: Distributed locks, leader election, any operation where real-time order matters.

Cost: Requires coordination between nodes, adding latency. During network partitions, a linearizable system must sacrifice availability (per the CAP theorem).

Implementations: Zookeeper, etcd, Google Spanner (using TrueTime).

Strong Consistency

Strong consistency guarantees that any read returns the result of the most recent write. It is often used interchangeably with linearizability in casual conversation, but technically it is slightly weaker — it does not require the real-time ordering guarantee.

In practice, strong consistency means all replicas agree on the order of operations. When a write is acknowledged, all subsequent reads from any node will see that write.

Example: Bank Account Transfer

Account A: $1000    Account B: $500

Transfer $200 from A to B:

1. BEGIN TRANSACTION
2. UPDATE accounts SET balance = balance - 200 WHERE id = 'A'
3. UPDATE accounts SET balance = balance + 200 WHERE id = 'B'
4. COMMIT

After commit, ANY query from ANY node shows:
  Account A: $800    Account B: $700

No node ever shows intermediate states like:
  Account A: $800    Account B: $500  (money disappeared!)

Implementations: PostgreSQL (single-node), MySQL with synchronous replication, MongoDB with readConcern "linearizable".

Sequential Consistency

Sequential consistency guarantees that all operations appear to execute in some sequential order, and the operations of each individual process appear in the order specified by the process. However, this order does not need to match real-time.

The difference from linearizability: two operations that happen concurrently in real time can be ordered in any way, as long as the ordering is consistent across all observers.

Example:

Client A: write(x=1)   then  write(x=2)
Client B: write(x=3)   then  write(x=4)

Valid sequential orderings:
  x=1, x=3, x=2, x=4 → final value: 4
  x=3, x=1, x=4, x=2 → final value: 2
  x=1, x=2, x=3, x=4 → final value: 4

Invalid: x=2, x=1, x=3, x=4
  (violates Client A's order: write(x=1) must come before write(x=2))

Causal Consistency

Causal consistency preserves the order of causally related operations. If operation B was influenced by (or depends on) operation A, then all nodes must see A before B. But operations that are not causally related (concurrent operations) can be seen in any order.

Example: Social Media Comments

Alice posts:  "Who wants to grab lunch?"        (Post P1)
Bob replies:  "I'm in! Where?"                  (Post P2, caused by P1)
Carol posts:  "Great weather today!"             (Post P3, independent)

Causal consistency guarantees:
  Every user sees P1 before P2 (P2 was caused by P1)
  P3 can appear anywhere — before P1, between P1 and P2, or after P2

Invalid ordering: Seeing P2 before P1
  (A reply cannot appear before the original post)

Causal consistency is a powerful middle ground. It provides intuitive ordering for related operations without the cost of global coordination. It works well in AP systems because it does not require all nodes to agree on the order of unrelated operations.

Implementations: MongoDB (since v3.6 with causal sessions), COPS (research system), Riak with causal context.

Read-Your-Writes Consistency

Read-your-writes (also called session consistency) guarantees that a process always sees its own writes. If you update your profile name to "Alice", you will always see "Alice" when you read your profile — you will never see your old name after updating it.

However, other users might still see your old name for a while. This is a weaker guarantee than strong consistency but stronger than pure eventual consistency.

Example: User Profile Update

Alice updates her display name:
  write(name="Alice Smith")

Alice's subsequent reads:
  read(name) → "Alice Smith"  ✓ (always sees her own write)

Bob's reads (at the same time):
  read(name) → "Alice S."     (might still see old value)
  read(name) → "Alice Smith"  (eventually sees new value)

Implementation techniques:

  • Route all reads for a user to the same replica that accepted their write
  • Track a logical timestamp for each client and only serve reads from replicas that are at least as up-to-date
  • Cache writes locally and merge with read results

Use cases: User profiles, settings pages, any interface where the user expects immediate feedback on their own actions.

Monotonic Reads

Monotonic reads guarantee that if a process reads a value, it will never subsequently see an older value. Once you have seen the future, you never go back to the past. Without this guarantee, a user could refresh a page and see older data than what they saw before.

Example: Follower Count

Reality: follower_count increases from 100 → 101 → 102

With monotonic reads:
  read() → 100
  read() → 101
  read() → 101  (acceptable: same or newer)
  read() → 102

Without monotonic reads:
  read() → 101
  read() → 100  ✗ VIOLATION: went backwards!
  read() → 102

This happens when different reads hit different replicas
that are at different replication lag states.

Implementation: Stick reads to a specific replica (sticky sessions), or track the latest version seen and only accept reads from replicas at that version or newer.

Eventual Consistency

Eventual consistency is the weakest consistency model. It guarantees only that if no new writes are made, all replicas will eventually converge to the same value. There is no bound on how long "eventually" takes, though in practice it is usually milliseconds to seconds.

Example: Like Counter on Social Media

User clicks "Like" → write goes to Node A

Node A: likes = 1001
Node B: likes = 1000  (hasn't received update yet)
Node C: likes = 1000  (hasn't received update yet)

After replication (milliseconds to seconds):
Node A: likes = 1001
Node B: likes = 1001  ✓ converged
Node C: likes = 1001  ✓ converged

Eventual consistency offers the best performance and availability because writes can be acknowledged immediately without waiting for replication. It is the default model for many NoSQL databases and is suitable when temporary staleness is acceptable.

Implementations: Amazon DynamoDB (default), Apache Cassandra (default), DNS, Amazon S3.

Real Databases and Their Consistency Models

Database Default Model Configurable Options
PostgreSQL Strong (single-node) Streaming replication adds async/sync options
MySQL Strong (single-node) Group Replication supports multi-primary
MongoDB Strong (readConcern: majority) Causal consistency with sessions, linearizable reads
Cassandra Eventual Tunable: ONE, QUORUM, ALL, LOCAL_QUORUM
DynamoDB Eventual Strongly consistent reads (optional, 2x cost)
Google Spanner Linearizable Bounded staleness reads for lower latency
CockroachDB Serializable Follower reads for stale but fast reads
Redis Eventual (with replication) WAIT command for synchronous replication

Choosing the Right Consistency Model

Decision Guide:

Is this financial data or safety-critical?
  → YES: Strong consistency / Linearizability
  → NO: Continue...

Does the user need to see their own updates immediately?
  → YES: Read-your-writes consistency (minimum)
  → NO: Continue...

Are there causal relationships between operations?
  → YES: Causal consistency
  → NO: Continue...

Is temporary staleness acceptable?
  → YES: Eventual consistency (best performance)
  → NO: Move up the consistency spectrum

In practice, many systems use multiple consistency levels. A social media platform might use strong consistency for authentication, read-your-writes for profile updates, causal consistency for comment threads, and eventual consistency for like counts and view counters.

The Cost of Consistency

Stronger consistency is not free. Each step up the consistency spectrum adds latency and reduces availability:

  • Eventual consistency: Write to one node, respond immediately. Replication happens asynchronously. Latency: 1-5ms.
  • Read-your-writes: Need to route reads to the correct replica or check version numbers. Minor overhead.
  • Causal consistency: Need to track and propagate causal dependencies. Vector clocks or similar mechanisms add overhead.
  • Strong consistency: Must wait for a quorum of replicas to acknowledge writes. Latency depends on quorum size and network distance. Typical: 10-50ms within a region, 100-300ms across regions.
  • Linearizability: Requires total ordering of all operations. May need consensus protocols like Raft or Paxos. Highest latency.

For detailed analysis of these performance trade-offs, see our guide on Latency vs Throughput and Trade-offs in System Design.

Frequently Asked Questions

What is the difference between strong consistency and linearizability?

Strong consistency guarantees all reads see the latest write. Linearizability adds the requirement that operations respect real-time ordering — if operation A completes before operation B starts, then B must see the effects of A. In practice, many systems that claim "strong consistency" actually provide linearizability, and the terms are often used interchangeably in industry (though not in academia).

Is eventual consistency always bad?

Not at all. Eventual consistency is the right choice for many use cases where temporary staleness is acceptable: social media feeds, analytics dashboards, search indices, recommendation engines, and CDN content. It offers the best performance and availability, and most users never notice the brief inconsistency window.

How do I implement read-your-writes in a distributed system?

The simplest approach is sticky sessions — route all reads from a user to the same node that handled their last write. A more robust approach is to include a logical timestamp with each write response and pass it to subsequent read requests. The read handler then only returns data from replicas that are at least as fresh as that timestamp.

Can I mix consistency models within the same database?

Yes, and this is common. Cassandra lets you set consistency level per query. DynamoDB lets you choose between eventually consistent and strongly consistent reads per request. MongoDB offers different read concerns per operation. This flexibility lets you optimize each query for its specific needs.

What happens when consistency guarantees are violated?

The impact depends on the application. Stale data on a social feed is mildly annoying. A stale inventory count might lead to overselling. A stale bank balance could lead to overdrafts. In safety-critical systems, consistency violations could endanger lives. Always match the consistency model to the consequences of reading stale data.

Related Articles