Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

Consistency Models

When everyone sees the same thing (or not)

Consistency answers a fundamental question: When you update data in one place, when do other parts of your system see that change?

Think of it like updating a shared document. Do you want everyone to see changes instantly (strong consistency), or is it okay if they see them a few seconds later (eventual consistency)?

Diagram

Consistency isn’t binary—it’s a spectrum from strongest to weakest:

Diagram

Strong consistency guarantees that all nodes see the same data immediately after a write completes.

Diagram

Key Characteristic: The write operation blocks until all replicas confirm. Only then does the client get a success response.

Diagram
AspectStrong Consistency
Data Accuracy✅ Always correct, no stale reads
Write Latency❌ Higher (waits for all replicas)
Availability❌ Lower (if one node is down, writes may fail)
Complexity❌ Higher (need coordination, locks)
Use CasesFinancial systems, inventory, critical state

Eventual consistency allows temporary differences between nodes, but guarantees all nodes will eventually converge to the same state.

Diagram

Key Characteristic: The write returns immediately after updating the leader. Replication happens asynchronously in the background.

Diagram
AspectEventual Consistency
Data Accuracy⚠️ Temporary inconsistencies possible
Write Latency✅ Lower (returns immediately)
Availability✅ Higher (can write even if some nodes down)
Complexity✅ Lower (no coordination needed)
Use CasesSocial media, analytics, non-critical data

Causal consistency preserves cause-and-effect relationships. If event A causes event B, all nodes that see B must have already seen A.

Diagram

Causal consistency uses vector clocks or logical timestamps to track dependencies:

Diagram

Key Characteristic: Events are delivered in causal order, even if they arrive out of order.

Diagram
AspectCausal Consistency
Data Accuracy✅ Preserves logical relationships
Write Latency✅ Lower than strong (no global coordination)
Availability✅ Higher than strong consistency
Complexity⚠️ Medium (need dependency tracking)
Use CasesChat, comments, collaborative editing

Diagram
Use CaseConsistency ModelWhy
Bank balanceStrongCan’t have incorrect balances
Inventory countStrongCan’t oversell products
Social media likesEventualSpeed > exact count
View countsEventualApproximate is fine
Chat messagesCausalNeed logical order
Comment threadsCausalReplies must follow posts
User profilesEventualCan tolerate slight delays

How consistency models affect your class design:

When you need strong consistency, use synchronization primitives:

Strong Consistency with Locks
from threading import Lock
class Account:
def __init__(self, balance):
self._balance = balance
self._lock = Lock() # Ensures atomic operations
def transfer(self, amount, to_account):
# Lock both accounts to prevent race conditions
with self._lock:
with to_account._lock:
if self._balance >= amount:
self._balance -= amount
to_account._balance += amount
return True
return False

Eventual Consistency → Use Version Numbers

Section titled “Eventual Consistency → Use Version Numbers”

For eventual consistency, track versions to detect conflicts:

Eventual Consistency with Versions
class Document:
def __init__(self, content):
self.content = content
self.version = 0 # Track version for conflict detection
def update(self, new_content, client_version):
if client_version != self.version:
# Conflict detected - need merge strategy
raise ConflictError("Version mismatch")
self.content = new_content
self.version += 1
return self.version

For causal consistency, maintain dependency graphs:

Causal Consistency with Dependencies
from typing import List, Set
class Event:
def __init__(self, data, dependencies: List[int]):
self.data = data
self.dependencies = set(dependencies) # Events this depends on
self.id = None # Assigned by system
class EventStore:
def __init__(self):
self.events = {} # id -> Event
self.seen = set() # Events this node has seen
def can_deliver(self, event: Event) -> bool:
# Can only deliver if all dependencies are seen
return event.dependencies.issubset(self.seen)
def deliver(self, event: Event):
if self.can_deliver(event):
self.seen.add(event.id)
# Process event...


Now that you understand consistency models, let’s explore the fundamental theorem that governs these trade-offs:

Next up: CAP Theorem Deep Dive — Learn why you can’t have everything: Consistency, Availability, and Partition tolerance.