Overview
Eventual consistency guarantees that if no new updates are made, all replicas will eventually return the same value. It allows replicas to be temporarily different, which lets systems accept writes during partitions and serve reads from the nearest replica without waiting for coordination.
The cost is anomalies the application must tolerate or hide: stale reads, reading your own write and not seeing it, out-of-order updates, and conflicting concurrent writes. Well-designed eventually consistent systems add session guarantees, idempotent and commutative updates, and conflict resolution strategies.
When the mayor announces something, some people hear it immediately and others hear it an hour later from neighbors. For a while, people disagree, but eventually everyone knows the same news.
When to use it
- Feeds, likes, view counts, recommendations.
- Multi-region systems that must stay fast and available.
- Asynchronous pipelines between microservices.
- Caches, search indexes, and read models.
Where it shows up in interviews
Recognize it when: search index or cache updated after the DB.
- Design product search
- Design a notification feed
Recognize it when: users write in different regions.
- Design a global social network
- Design a collaborative app
Where it is used in real software
Record changes propagate as caches expire, which can take minutes to hours.
Replicate across regions asynchronously with last-writer-wins conflict resolution.
Order service publishes OrderPlaced; shipping and analytics update their own data seconds later.
Key terms
- Convergence
- Replicas reach the same state once updates stop.
- Stale read
- Reading an older value from a lagging replica.
- Last-write-wins
- Resolve conflicts by highest timestamp; simple but can lose updates.
- CRDT
- Data types that merge concurrent updates deterministically.
- Anti-entropy
- Background comparison and repair of replicas.
How it works, step by step
- 1Write locally
Accept the write at the nearest replica.
- 2Propagate asynchronously
Replication stream, gossip, or events.
- 3Detect conflicts
Versions or vector clocks identify concurrent updates.
- 4Resolve conflicts
LWW, merge function, or CRDT.
- 5Hide anomalies in the product
Optimistic UI, read-your-writes routing, 'processing' states.
Conflict resolution strategies
Two regions update the same record concurrently
| Strategy | How | Risk |
|---|---|---|
| Last-write-wins | Keep highest timestamp | Silently drops one update |
| Merge function | Application merges (union of cart items) | Deleted items can reappear |
| CRDT | Mathematically mergeable types (counters, sets) | Limited data types |
| Ask the user | Show both versions | Poor experience at scale |
NOWStrategy: Last-write-wins | How: Keep highest timestamp | Risk: Silently drops one update
Choose per data type: counters and sets as CRDTs, profile fields with LWW, and money never eventually consistent without a ledger.
Implementation
// Grow-only counter: each node increments its own slot; merge takes the max per nodetype GCounter = Record<string, number>; const increment = (c: GCounter, nodeId: string, by = 1): GCounter => ({ ...c, [nodeId]: (c[nodeId] ?? 0) + by }); const merge = (a: GCounter, b: GCounter): GCounter => { const out: GCounter = { ...a }; for (const [node, n] of Object.entries(b)) out[node] = Math.max(out[node] ?? 0, n); return out;}; const value = (c: GCounter) => Object.values(c).reduce((s, n) => s + n, 0); let us = increment({}, "us-east", 3);let eu = increment({}, "eu-west", 2);us = merge(us, eu); eu = merge(eu, us);console.log(value(us), value(eu)); // 5 5: replicas converge regardless of merge orderComplexity and performance
Longer during partitions.
Commutative, associative, idempotent.
Trade-offs
Eventual consistency keeps systems fast and available but pushes complexity into application logic.
LWW is easy but loses data; merges and CRDTs preserve intent but constrain data models.
Variants and related techniques
Stronger: preserves cause-effect order.
Replicas that received the same updates are identical immediately (CRDTs).
Common mistakes
- Users not seeing their own changes.
Fix: Provide read-your-writes via sticky routing or version tokens.
- Relying on wall-clock timestamps for ordering.
Fix: Clock skew reorders writes; use logical or hybrid clocks.
Interview questions
When is eventual consistency acceptable?
When temporary staleness does not break invariants or harm users: social counts, feeds, recommendations, search indexes, analytics. Not for balances, inventory decrements, or uniqueness constraints without extra safeguards.
How do you resolve conflicting writes?
Detect concurrency with versions or vector clocks, then use last-write-wins for simple fields, domain-specific merges (union of cart items), or CRDTs for counters and sets.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Implement a PN-counter CRDT | Medium | Merge rules. |
| Design a multi-region shopping cart | Hard | Conflict handling. |