Siddhant Deval
Siddhant DevalAuthor
Senior Full-Stack Engineer·Sep 20, 2026·17 min read

Consistency Models & Distributed Coordination: What 'Consistent' Actually Means

Consistency is not a boolean. Linearizability, causal consistency, read-your-writes, and eventual consistency are distinct contractual guarantees — each with a different implementation cost. This article maps the full spectrum to the read-path decisions you make in your ORM, replica config, and cache layer.

Consistency Models & Distributed Coordination: What "Consistent" Actually Means

A database is not a dumb storage box — it is a contract between your write path, your read path, and your consistency guarantees. Every design decision you defer becomes a production incident you eventually own. The most deferred decision in distributed systems is treating "consistent" as a single word. Engineers say "we need consistency" without specifying which consistency: linearizability, sequential consistency, causal consistency, read-your-writes, or eventual. Each is a different contract. Each has a different cost. And your replica configuration, your ORM, and your cache layer are already making this choice for you — whether you know it or not.

Architectural Note

This is Part 2b of the Advanced Database & State Management series. It builds on the isolation level foundation from Part 2a — Isolation & Concurrency Control. The concepts here — consistency models across replicas — are the distributed-system extension of the single-node anomaly taxonomy covered there.

Architectural Note

Cross-series context: The Database Decision Framework article in the Modern Database Paradigms series covers consistency as a workload classification criterion ("choose strong consistency deliberately, not by default"). This article teaches the mechanical meaning of each guarantee so you can operationalize that advice.


1. The Consistency Model Spectrum

Consistency is not a binary — it is a spectrum of named, contractual guarantees. From strongest to weakest:

Linearizability
  └── Sequential Consistency
        └── Causal Consistency
              └── Read-Your-Writes
                    └── Monotonic Reads
                          └── Eventual Consistency  (weakest)

Each level is strictly weaker than the one above it: a system providing linearizability also provides all weaker guarantees. A system providing eventual consistency provides none of the stronger ones unless explicitly configured.

1.1 Linearizability (Strongest)

Every read reflects the most recent write globally, and all operations appear to execute instantaneously in a single, total order — as if there were only one copy of the data.

Write(x=1) → completes at time T
Any Read(x) after T, from any node → must return 1

If Read(x) returns 1, then all subsequent reads from all nodes must also return 1.

Implementation cost: Synchronous replication. Every write must be acknowledged by all replicas before the client receives a response. Latency = max(replica write latency). Under network partition, a linearizable system must refuse writes (CP in CAP terms).

Where you see it: Postgres with synchronous_commit = remote_apply + synchronous standby. ZooKeeper. etcd (Raft consensus).

1.2 Sequential Consistency

All operations appear to execute in some total order that is consistent with the order seen by each individual process — but the global order does not have to match real-time wall clock order.

Process A: Write(x=1), then Write(x=2)
Process B: sees x=1 before x=2 (order preserved per process)

But: Process C may see x=2 before x=1 if it reads from a different replica.

Where you see it: CPU memory models (not databases in practice). Rarely used as a database guarantee.

1.3 Causal Consistency

Operations that are causally related (writes that depend on prior reads) are seen in causal order by all nodes. Concurrent operations (no causal link) may be seen in different orders by different nodes.

User posts comment (Write A)
User reads their comment (Read B — causally depends on A)
User replies to comment (Write C — causally depends on B)

Causal consistency guarantees: any node that shows Write C must also show Write A.
Concurrent writes by unrelated users may arrive in different order at different replicas.

Where you see it: MongoDB causal sessions. CockroachDB follower reads with AS OF SYSTEM TIME. Collaborative editing systems (Google Docs uses a form of causal consistency with Operational Transformation).

1.4 Read-Your-Writes

A user always sees their own writes in subsequent reads — even when reading from a replica.

User writes profile update → Write goes to primary
User immediately reads their profile → Read goes to replica

❌ WITHOUT read-your-writes: replica hasn't caught up → user sees old profile → "why didn't my update save?"
✅ WITH read-your-writes: session routed to primary for reads, or replica waits until caught up

Implementation: Sticky sessions (same replica), primary routing for reads after writes, or synchronous standby with synchronous_commit.

1.5 Monotonic Reads

Once a user has seen a value X, they will never subsequently see an older value than X (from any replica).

User reads x=5 from replica A
User's next request hits replica B (which lags behind replica A)

❌ WITHOUT monotonic reads: user sees x=3 — time appears to go backward
✅ WITH monotonic reads: replica B either catches up or the read is routed to a replica that has seen x=5

1.6 Eventual Consistency (Weakest)

Given no new writes, all replicas will eventually converge to the same value. No guarantee on when. No guarantee on what intermediate reads return.

Write(x=5) to primary
Replica A: returns x=5 immediately (already replicated)
Replica B: returns x=3 (replication lag: 400ms behind)
Replica C: returns x=0 (just started replication)

All three will return x=5 eventually — but "eventually" may mean seconds or minutes.

Eventual consistency does not mean "consistent eventually." It means "eventually identical" — with no bound on time and no guarantees about intermediate states.

Consistency model spectrum from linearizability (strongest) to eventual consistency (weakest), with real-world database/config examples at each level
Consistency model spectrum from linearizability (strongest) to eventual consistency (weakest), with real-world database/config examples at each level

2. CAP Theorem: What It Actually Forces

The CAP theorem states: a distributed system can provide at most two of three guarantees simultaneously:

  • Consistency (linearizability)
  • Availability (every request gets a response)
  • Partition tolerance (the system continues operating despite network partitions)

Since partition tolerance is not optional in any real distributed system (networks fail), the real choice is:

Under partition Behavior Designation
Refuse writes to preserve consistency Returns error / timeout CP
Accept writes to remain available May return stale data AP
CP systems (choose consistency under partition):
  PostgreSQL primary + synchronous standby
  CockroachDB (SERIALIZABLE + Raft)
  ZooKeeper, etcd, Consul

AP systems (choose availability under partition):
  Cassandra (tunable consistency — default is AP)
  DynamoDB (eventual consistency by default)
  CouchDB
  DNS
Crucial Requirement

CAP only describes behavior during a network partition. Most of the time, there is no partition — the system operates normally. CAP does not describe the everyday tradeoff. PACELC does.


3. PACELC: The Everyday Tradeoff CAP Misses

PACELC extends CAP to include latency as a first-class dimension:

If Partition (P): choose between Availability (A) and Consistency (C)
Else (E — normal operation): choose between Latency (L) and Consistency (C)

Every database makes this choice on every write, even without a partition:

Database Under Partition Normal Operation PACELC Class
DynamoDB (default) AP — stays available EL — optimizes latency PA/EL
Cassandra (ONE) AP EL PA/EL
Postgres (sync standby) CP — refuses writes if standby down EC — pays replication latency PC/EC
CockroachDB CP EC PC/EC
MongoDB (majority write) CP EC PC/EC
Cassandra (QUORUM) PA EC PA/EC
CAP vs PACELC system classification matrix showing partition behavior, normal-operation tradeoff, and real-world database examples
CAP vs PACELC system classification matrix showing partition behavior, normal-operation tradeoff, and real-world database examples
Mental Model Check

CAP is a failure-mode lens. PACELC is an operational lens. When your architect says "we need high availability," ask: "High availability under partition, or low latency under normal operation?" These are different requirements with different database configurations.


4. Eventual Consistency at the Code Level

"Eventual consistency" is not an abstraction you configure once and forget. It produces concrete, user-visible behaviors that your read path must be designed to handle.

4.1 The Read-Your-Writes Violation

TYPESCRIPT
// ❌ Classic read-your-writes bug in a Node.js API
// Primary is in us-east-1. Read replica is in us-west-2 (400ms replication lag).

async function updateUserProfile(userId: string, name: string) {
  await db.primary.query(
    'UPDATE users SET name = $1 WHERE id = $2', [name, userId]
  );

  // Immediately read back — goes to replica (load balancer routes reads)
  const user = await db.replica.query(
    'SELECT name FROM users WHERE id = $1', [userId]
  );

  return user; // ← Returns OLD name. User sees "your change didn't save."
}
TYPESCRIPT
// ✅ Option 1: Route the post-write read to the primary
async function updateUserProfile(userId: string, name: string) {
  await db.primary.query('UPDATE users SET name = $1 WHERE id = $2', [name, userId]);
  const user = await db.primary.query('SELECT name FROM users WHERE id = $1', [userId]);
  return user; // Always consistent — reads from the source of truth
}

// ✅ Option 2: Return the data you wrote — no read needed
async function updateUserProfile(userId: string, name: string) {
  await db.primary.query('UPDATE users SET name = $1 WHERE id = $2', [name, userId]);
  return { id: userId, name }; // You already know what you wrote
}

4.2 Monotonic Reads Violation

TYPESCRIPT
// ❌ User's requests routed to different replicas by a round-robin load balancer
// Replica A is ahead of Replica B by 2 seconds of replication lag

// Request 1 → Replica A: messages.count = 15
// Request 2 → Replica B: messages.count = 12  ← went backward!
// User sees message count decrease. Appears as a UI bug.

// ✅ Sticky sessions: pin each user to one replica for the duration of a session
// All of user's reads go to the same replica — monotonic reads guaranteed
// (unless that replica restarts, in which case you re-pin)

4.3 CRDTs: Eventual Consistency Without Conflict

For collaborative features where multiple users write concurrently and conflicts must merge automatically, Conflict-Free Replicated Data Types (CRDTs) are the production primitive.

Counter CRDT: increment-only counter that merges correctly across replicas
  Node A: count=5, Node B: count=3 (both incremented from count=2)
  Merge: max(5,3) = 5 ✅  (OR: each node tracks its own increments → sum on read)

Set CRDT (G-Set): grow-only set
  Node A: {a, b, c}, Node B: {b, d}
  Merge: {a, b, c, d} ✅

LWW-Register (Last-Write-Wins): uses timestamp to resolve conflicts
  Node A: x=5 at T=100, Node B: x=3 at T=120
  Merge: x=3 (T=120 wins) — silently discards Node A's write
Performance / Safety Warning

Last-Write-Wins (LWW) is the default conflict resolution in Cassandra, DynamoDB (conditional writes aside), and many event-streaming systems. LWW silently discards concurrent writes — the losing write is gone with no error. For financial data, user-generated content, or any field where concurrent writes are meaningful, use CRDTs or application-level conflict resolution instead.


5. Distributed Coordination: Why 2PC Fails and What Replaces It

When a write must span multiple services or databases, you need a coordination protocol.

5.1 Two-Phase Commit (2PC) and the Blocked-Participant Problem

Phase 1 — Prepare:
  Coordinator → all participants: "Can you commit?"
  Participants → Coordinator: "Yes, prepared" (locks resources)

Phase 2 — Commit:
  Coordinator → all participants: "Commit"
  Participants commit and release locks

The failure mode: If the coordinator crashes after Phase 1 but before Phase 2, all participants are in "prepared" state — resources locked, waiting indefinitely for a commit or abort signal that never comes.

Coordinator CRASHES after receiving all "prepared" responses.
All participants: resources locked. Cannot commit. Cannot abort.
Cannot make progress without coordinator recovery.
← This is the blocked-participant problem.
Performance / Safety Warning

2PC is not used as a general application-level distributed transaction mechanism in modern distributed systems precisely because of this failure mode. CockroachDB and Spanner use it internally with Raft-based recovery guarantees — but you do not implement 2PC in your application code.

Architectural Note

Cross-series reference: The Cloud-Native & Distributed SQL: CockroachDB article in the Modern Database Paradigms series covers how CockroachDB handles distributed transactions internally using Raft consensus — the production alternative to application-level 2PC.

5.2 Saga Pattern: The Application-Level Alternative

A Saga decomposes a distributed transaction into a sequence of local transactions, each of which publishes an event or message. If any step fails, compensating transactions undo the preceding steps.

Order placement Saga:
  Step 1: Reserve inventory     → (on fail) → Release inventory reservation
  Step 2: Charge payment        → (on fail) → Refund payment
  Step 3: Create shipment       → (on fail) → Cancel shipment
  Step 4: Send confirmation     → (on fail) → Send cancellation email

Each step is a local transaction — ACID within its own database.
No distributed lock held across steps. No coordinator that can block.
Failure at step 3 triggers: cancel shipment + refund + release inventory.
TYPESCRIPT
// Choreography-based Saga (event-driven)
// Each service listens for events and publishes its own

// inventory-service
eventBus.on('order.created', async (event) => {
  const reserved = await inventory.reserve(event.orderId, event.items);
  if (reserved) {
    eventBus.emit('inventory.reserved', { orderId: event.orderId });
  } else {
    eventBus.emit('inventory.failed', { orderId: event.orderId });
  }
});

// payment-service listens to 'inventory.reserved', charges, emits 'payment.completed'
// If payment fails, emits 'payment.failed' → inventory-service compensates

Summary

Concept Rule
Linearizability Every read reflects the most recent global write — requires synchronous replication; most production systems do not need it
Eventual consistency Replicas converge eventually — has no time bound and no intermediate-state guarantees
Read-your-writes Always route post-write reads to the primary, or return the written value directly
Monotonic reads Pin users to a single replica (sticky sessions) or route all reads through primary
CAP under partition CP systems refuse writes to stay consistent; AP systems accept writes and return stale data
PACELC everyday Every write trades latency for consistency even without a partition — PACELC describes this, CAP does not
LWW conflict resolution Silently discards concurrent writes — never use for financial data or user-generated content
CRDTs The correct primitive for collaborative features with concurrent writes — merge automatically without conflict
2PC Blocked-participant failure mode makes it unsuitable for application-level distributed transactions
Saga pattern Decomposes distributed writes into local transactions with compensating rollbacks — no coordinator, no blocking

What's Next

In Part 3, the consistency guarantees established here become the framework for evaluating scaling strategies — partitioning, sharding, and replication topologies each make different consistency commitments, and the quorum formula W + R > N is the mathematical expression of the read-your-writes guarantee in a leaderless system. → Scaling Data: Partitioning, Sharding & Replication

Research & Synthesis Note

This article was developed with AI-assisted deep search, specification cross-referencing, and technical research synthesis.

#Distributed Systems#Consistency#CAP Theorem#Eventual Consistency
Siddhant Deval

Written by Siddhant Deval

Senior Full-Stack Engineer building high-scale architectures, browser performance engineering systems, and SaaS platforms.