Lessons
1 · System Design Foundations
2 · APIs and Communication
3 · Capacity Estimation
4 · Core Building Blocks
5 · Databases
- 12Relational Databases and Data Modeling for System Design
- 13Database Indexes and Query Performance: How to Make Reads Fast
- 14Transactions, Isolation Levels and Concurrency Control: Preventing Race Conditions
- 15Database Replication: Primary-Replica, Read Replicas, Lag and Failover
- 16Database Sharding and Partitioning: How It Works and When You Need It
- 17SQL vs NoSQL: Data Models and How to Choose the Right Database
6 · Distributed Systems
- 18Why Distributed Systems Are Hard: Partial Failure, Timeouts and Clocks
- 19CAP Theorem and Consistency Models Explained Without the Myths
- 20Idempotency, Retries and Message Delivery Guarantees
- 21Distributed Transactions: Two-Phase Commit, the Outbox Pattern and Sagas
- 22Distributed Locks, Leases, Leader Election and Consensus
7 · Reliability and Operations
8 · Architecture and Security
9 · Interview Method and Foundation Case Studies
10 · Real-World Case Studies
- 33Design a Notification System: Email, SMS and Push at Scale
- 34Design a Chat System Like a Messaging App
- 35Design a News Feed: Fan-Out, Ranking and the Celebrity Problem
- 36Design Search Autocomplete (Typeahead)
- 37Design a Distributed Job Scheduler
- 38Design a Ticket Booking System Without Overselling
- 39Design a Payment System: Idempotency, Ledgers and Reconciliation
11 · Large-Scale Case Studies
- 40Design a Video Streaming Platform: Upload, Transcoding and Adaptive Streaming
- 41Design a Ride-Hailing System: Location, Matching and Real-Time Updates
- 42Design a Food Delivery Platform: Orders, Restaurants and Delivery Partners
- 43Design an E-Commerce System: Catalog, Cart, Checkout, Inventory and Flash Sales
- 44Design a Web Search Engine: Crawling, Inverted Indexes and Ranking
12 · Interview Readiness
Lesson 19 · Distributed Systems
CAP Theorem and Consistency Models Explained Without the Myths
What "consistent" means when data is replicated, from linearizability through causal and session guarantees to eventual consistency; what the CAP theorem actually says and why "pick two" misleads; PACELC and the everyday latency trade-off; quorum reads and writes; resolving conflicts; and choosing consistency per feature instead of per system.
For
SDE-2 candidates and backend developers who must explain consistency trade-offs precisely, and anyone who has heard 'CAP: pick two' and wants the accurate version.
Level
Before you start
Read Database Replication (article 15), especially replication lag and read-your-writes, and Why Distributed Systems Are Hard (article 18), especially partitions and clocks.
On this page
Key takeaways
- Consistency models describe what readers may see while replicas catch up, from linearizable (behaves like one copy) to eventual (copies converge if writes stop).
- CAP says that during a network partition a replicated system must choose, per operation, between staying linearizable and answering every request; without a partition there is no forced choice.
- PACELC adds the everyday trade-off: even without partitions, stronger consistency usually costs latency.
- With N replicas, write quorum W and read quorum R overlap when W + R > N, but quorums alone do not guarantee linearizability.
- Choose consistency per feature: strong where wrong answers cost money or safety, session guarantees for a user's own data, eventual for counters and feeds.
"CAP theorem: consistency, availability, partition tolerance; pick two." Almost every candidate has heard it, and many repeat it in interviews, then say "so we chose AP" as if that settled the design. It is one of the most misunderstood ideas in the field. The slogan is not exactly wrong, but it hides what the theorem says, when it applies, and the trade-off you actually face every day, which is not about partitions at all.
This article first builds a clear vocabulary for "consistency" when data lives in several places, then states CAP precisely, adds PACELC, works through quorum arithmetic, and ends with the practical skill: choosing a consistency level per feature.
What you will learn
#- What consistency means for replicated data (and how it differs from the C in ACID).
- The main consistency models: linearizable, causal, session guarantees and eventual.
- What the CAP theorem states, and the common myths around it.
- PACELC: the latency-versus-consistency trade-off when nothing is broken.
- Quorums: N, W and R, with a program that checks overlap.
- Resolving conflicts when replicas accept concurrent writes.
- How to choose consistency per feature, with worked examples.
Two meanings of "consistency"
#- In ACID (article 12), consistency means a transaction keeps the database valid: constraints hold.
- In distributed systems, consistency describes what reads may return while copies of the data are being updated: will a reader see the latest write, an older value, or values in a strange order?
This article is about the second meaning. When someone says "eventually consistent", they mean that one.
Consistency models, from strongest to weakest
#A consistency model is a promise about which results reads may return. Jepsen, which tests databases' guarantees, maintains a reference describing many models and how they relate (Consistency models). For system design, five are enough.
Linearizability ("strong consistency")
#The system behaves as if there were a single copy of the data, and every operation takes effect at one instant between its start and finish. Once a write completes, every read that starts afterwards sees it (or a later value), whichever replica serves it (Linearizability).
- Example need: "seat C14 is booked" must be seen by everyone the moment the booking succeeds; a username, once taken, must be taken for everyone.
- Cost: replicas must coordinate on writes (or reads must go to a leader), adding latency, and during a network partition some requests must be refused.
Causal consistency
#Operations that are causally related are seen by everyone in the same order; operations that are unrelated (concurrent) may be seen in different orders by different readers.
- Example need: a reply must never appear before the message it replies to; "unfriend X" followed by "post a private photo" must not let X see the photo.
- Cost: lower than linearizability; the system must track dependencies.
Session guarantees
#Weaker promises scoped to one client's session, which fix the most visible anomalies cheaply:
- Read your writes: a user always sees their own changes.
- Monotonic reads: a user never sees data go backwards in time.
- Monotonic writes: a user's writes are applied in the order they made them.
Article 15 showed how to provide read-your-writes with replica routing.
Eventual consistency
#If writes stop, all replicas eventually converge to the same value. Before then, reads may return stale values, and different replicas may disagree. There is no bound on how long "eventually" takes, though in practice it is usually milliseconds to seconds.
- Example fit: like counts, view counts, follower counts, feed contents, DNS records, cached product descriptions.
- Benefit: replicas can accept and serve requests without waiting for each other, which helps latency and availability.
Model | Promise | Typical use | Cost |
|---|---|---|---|
Linearizable | Acts like one copy, in real-time order | Locks, uniqueness, balances, seat booking, leader election | Coordination latency; unavailable to some clients during partitions |
Causal | Cause before effect, everywhere | Comments and replies, social privacy changes | Dependency tracking |
Read your writes, monotonic reads | A user sees their own changes, never goes back in time | Profiles, settings, a user's own posts | Routing per session |
Eventual | Copies converge if writes stop | Counters, feeds, caches, analytics | Readers can see stale or differing values |
The CAP theorem, stated precisely
#Eric Brewer proposed the idea in 2000; Seth Gilbert and Nancy Lynch proved a formal version in 2002 (Brewer's Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Services). In their terms:
- C (consistency) means linearizability (they call it atomic consistency): every read sees the most recent completed write.
- A (availability) means every request received by a non-failing node gets a non-error response, eventually.
- P (partition tolerance) means the system keeps operating even when the network loses arbitrary messages between nodes.
The theorem: when a network partition occurs, a replicated system cannot guarantee both C and A. A node cut off from the others must either answer (and risk returning stale data or accepting a conflicting write: giving up C) or refuse or wait (giving up A).
A concrete partition
# Region West Region East Replica W ---- link cut ---- Replica E client: "book seat C14" client: "book seat C14"- Choose consistency (CP behaviour): the side that cannot reach a majority refuses the booking ("please try again"). No double booking, but some users get errors.
- Choose availability (AP behaviour): both sides accept their booking. Everyone gets an answer, and after the link heals you discover two bookings for one seat, which must be resolved somehow.
The myths
#Myth | What is accurate |
|---|---|
"Pick any two of three." | Partitions are not optional in a distributed system; networks do fail. The real choice is between C and A during a partition. Brewer himself wrote that the "2 of 3" formulation was always misleading because it oversimplified the tensions (CAP Twelve Years Later). |
"Our system is CP" or "AP", as a fixed label. | The choice can be made per operation, and per kind of failure. A system can refuse writes that need uniqueness while still serving reads of cached data. |
"When there is no partition, we still give something up." | Not according to CAP. Brewer notes that because partitions are rare, there is little reason to forfeit C or A when the system is not partitioned. The trade-off you do face is latency (PACELC, below). |
"AP means no consistency." | AP systems usually offer eventual consistency and often session guarantees; they converge after the partition heals. |
"Availability in CAP means 99.99% uptime." | CAP's availability is a strong, specific property (every non-failing node answers). Practical availability, measured in nines, depends on much more. |
Brewer's article also recommends treating partitions explicitly: detect them, enter a mode that limits risky operations, and recover by reconciling afterwards.
PACELC: the trade-off you face every day
#Daniel Abadi pointed out that CAP says nothing about normal operation, yet the most important trade-off is present all the time (Consistency Tradeoffs in Modern Distributed Database System Design):
If there is a Partition, choose Availability or Consistency; Else, choose Latency or Consistency.
Keeping replicas strongly consistent means waiting for other replicas (often in other zones or regions) before answering. That costs latency on every request, not only during rare partitions. Many systems that relax consistency do so to be fast, not because partitions are common.
Examples from earlier articles:
- Synchronous replication across regions added about 150 ms to every write (article 15): EC, paying latency.
- Asynchronous read replicas answer fast but may be stale: EL.
Quorums
#In leaderless or quorum-based replication (article 15), each piece of data lives on N replicas. A write is considered successful when W replicas acknowledge it; a read asks R replicas and takes the newest version among the answers.
If W + R > N, every set of W replicas overlaps every set of R replicas in at least one node, so every read contacts at least one replica that has the latest acknowledged write. The program below checks this by brute force for N = 3, and also shows how many replicas can be down while writes and reads still succeed.
// File: QuorumDemo.javaimport java.util.ArrayList;import java.util.List;public class QuorumDemo { // Every subset of n replicas with exactly k members, as bit masks. static List<Integer> subsets(int n, int k) { List<Integer> out = new ArrayList<>(); for (int mask = 0; mask < (1 << n); mask++) { if (Integer.bitCount(mask) == k) { out.add(mask); } } return out; } // True if every possible write set shares at least one replica with every possible read set. static boolean alwaysOverlap(int n, int w, int r) { for (int writeSet : subsets(n, w)) { for (int readSet : subsets(n, r)) { if ((writeSet & readSet) == 0) { return false; } } } return true; } public static void main(String[] args) { int n = 3; System.out.println("N = " + n + " replicas"); for (int w = 1; w <= n; w++) { for (int r = 1; r <= n; r++) { System.out.printf("W=%d R=%d overlap guaranteed: %-5s writes survive %d down, reads survive %d down%n", w, r, alwaysOverlap(n, w, r), n - w, n - r); } } }}N = 3 replicasW=1 R=1 overlap guaranteed: false writes survive 2 down, reads survive 2 downW=1 R=2 overlap guaranteed: false writes survive 2 down, reads survive 1 downW=1 R=3 overlap guaranteed: true writes survive 2 down, reads survive 0 downW=2 R=1 overlap guaranteed: false writes survive 1 down, reads survive 2 downW=2 R=2 overlap guaranteed: true writes survive 1 down, reads survive 1 downW=2 R=3 overlap guaranteed: true writes survive 1 down, reads survive 0 downW=3 R=1 overlap guaranteed: true writes survive 0 down, reads survive 2 downW=3 R=2 overlap guaranteed: true writes survive 0 down, reads survive 1 downW=3 R=3 overlap guaranteed: true writes survive 0 down, reads survive 0 downRead the table as a menu of trade-offs:
- W=2, R=2 (a common choice for N=3): reads and writes overlap, and both keep working with one replica down.
- W=1, R=1: fastest and most available, but a read may miss the latest write: eventual consistency.
- W=3, R=1: fast reads that always overlap, but a single replica failure blocks all writes.
- W=1, R=3: fast, very available writes, but any replica failure blocks reads that need the overlap.
What quorums do not guarantee
#Overlap is necessary for reading the latest write, but not sufficient for linearizability. Concurrent writes may be ordered differently on different replicas; a write that reached only some replicas before failing can be seen by some readers and not others; and if conflicts are resolved by "latest timestamp", clock skew (article 18) can choose the wrong winner. Systems add mechanisms such as read repair, versioning and, for linearizable operations, consensus (article 22). Amazon's Dynamo paper also describes sloppy quorums with hinted handoff: when the usual replicas are unreachable, writes go temporarily to other nodes and are handed back later, which favours availability over strict overlap (Dynamo).
Resolving conflicts
#If replicas accept writes independently (AP behaviour, multi-leader replication, or W=1), two replicas can end up with different versions. Options:
Strategy | How | Risk |
|---|---|---|
Last write wins (LWW) | Keep the version with the latest timestamp | Silently discards concurrent writes; clock skew picks wrong winners |
Version vectors plus application merge | Detect concurrent versions; the application merges them | Merge logic per data type; can be complex |
Merge-friendly data types (CRDTs) | Counters, sets and other structures that merge automatically and deterministically | Only some data fits; deletions need care |
Avoid conflicts by design | Route all writes for an item to one place (a single leader or home region per user) | Less availability for that item during partitions |
Amazon's Dynamo paper describes the shopping-cart example: when concurrent versions of a cart appear, they are merged so that added items are never lost, accepting that a deleted item can occasionally reappear (Dynamo). That is a business decision about which mistake is cheaper.
Choosing consistency per feature
#The practical skill is not "is the system CP or AP?" but "what does each operation need?"
Feature | Model needed | Why | Typical implementation |
|---|---|---|---|
Account balance before a debit | Linearizable | Overdrafts and double spends cost money | Single primary with transactions (article 14) |
Seat booking, coupon redemption, unique usernames | Linearizable for the decision | Two winners is a real-world failure | Conditional writes or unique constraints on one primary |
A user's own profile and posts after editing | Read your writes | Users think edits were lost | Primary reads for a short window (article 15) |
Chat messages within a conversation | Ordered per conversation (causal within it) | Replies must follow messages | Per-conversation sequence numbers (article 34) |
Like and view counts | Eventual | Off by a few for seconds harms no one | Async counters, caches |
Feed contents | Eventual | A few seconds' delay is acceptable | Precomputed feeds (article 35) |
Search results | Eventual | Index lags writes slightly | Event-fed search engine |
Leader election, distributed locks | Linearizable | Two leaders cause corruption | Consensus systems (article 22) |
Worked example: Pixly across two regions
#Suppose Pixly expands to serve users in India and Europe, with a deployment in each region.
- User accounts and usernames: must be unique globally. Writes go to one home region (a single primary); signups from Europe pay the cross-region latency on that one rare operation. During a partition, signups in the cut-off region fail with a friendly error (CP for this operation).
- Photos and captions: each photo is owned by its uploader's home region; replicated asynchronously to the other region for fast reads there. Readers abroad may see a new photo a second late (eventual), and uploaders always read their own from their home region (read your writes).
- Likes: counted in each region and merged as counters (merge-friendly; a CRDT-style counter). Totals converge after a partition (AP for this operation).
- Feeds: built per region from replicated events; eventual.
Asked "is Pixly CP or AP?", the right answer is: "Different operations make different choices: usernames and anything involving money are CP; likes, feeds and photo replication are AP with session guarantees for users' own data."
Failure modes
#Failure | What users see | Mitigation |
|---|---|---|
Stale replica read after a write | "My change disappeared" | Read-your-writes routing |
Reads bouncing between replicas | Data appears and disappears | Monotonic reads (sticky replica) |
LWW with skewed clocks | A newer edit silently lost | Versions and explicit conflict handling |
Misconfigured quorum (W + R not > N) | Intermittent stale reads | Review settings per operation |
Partition with AP writes on both sides | Conflicting data after healing | Merge strategy, or CP for that operation |
Partition with CP behaviour | Errors for users on the minority side | Clear error handling and retries; limit CP to operations that need it |
Trade-offs
#Choice | You gain | You pay |
|---|---|---|
Linearizable | Simple reasoning, no anomalies | Latency; unavailability for some clients during partitions |
Eventual | Low latency, high availability | Stale reads, conflicts to resolve |
Session guarantees | Users never see their own changes vanish | Routing complexity |
Larger W | Durability and overlap | Slower writes; less write availability |
Larger R | Fresher reads | Slower reads; less read availability |
Common mistakes
#- Reciting "pick two" and labelling the whole system CP or AP.
- Assuming CAP forces a sacrifice when there is no partition.
- Forgetting the latency cost of strong consistency (PACELC).
- Believing W + R > N alone gives linearizability.
- Using last-write-wins for data where losing a write matters.
- Strong consistency everywhere "to be safe", paying latency for counters and feeds.
In an interview
#- Define terms before using them: "by strong consistency I mean linearizable for this operation".
- Choose per feature, with a reason tied to the cost of a wrong answer.
- If you use quorums, give N, W and R and what they tolerate.
- If asked about CAP, state it precisely: during a partition, choose between consistency and availability for each operation; otherwise the trade-off is latency.
Exercises
#Exercise 1
Choose the model
#Choose the weakest consistency model that is acceptable, and say why:
- Displaying the number of people currently watching a live stream.
- Ensuring two people cannot register the same email address.
- Showing a user the playlist they just edited.
- A group chat where replies must appear after the messages they answer.
- A global configuration flag that turns off a buggy feature.
Exercise 2: Quorum choices
#A key-value store has N = 5 replicas. For each goal, choose W and R and state how many replica failures writes and reads can tolerate:
- Reads always overlap the latest write; tolerate 2 failures for both reads and writes.
- Very fast, highly available writes; reads should still overlap.
- Lowest possible latency for both; staleness is acceptable.
Exercise 3: Critique the statement
#A candidate says: "We chose MongoDB because it is CP, so our system is strongly consistent and we don't need to think about stale reads." Explain what is wrong or incomplete.
Exercise 4: The partition
#An inventory service runs in two data centres, each with a replica, and accepts orders in both. The link between them fails for 10 minutes during a sale. Describe what happens under (a) a CP design and (b) an AP design, and propose a design that sells as much as possible without overselling.
Show solutionHide solution
- Eventual. An approximate, slightly delayed count is fine.
- Linearizable for the uniqueness check (in practice, a unique constraint on one primary). Two accounts with one email is a real failure.
- Read your writes. The editor must see their change; others can see it a moment later.
- Causal (at least per conversation ordering). Replies must follow their parents; unrelated messages in other chats need no ordering.
- Eventual, with fast propagation, is usually acceptable (a few seconds for every server to pick it up), but make sure it does converge quickly and is monitored. If the bug is causing serious harm, prefer a mechanism that pushes the change to all servers promptly and verify that it took effect.
Exercise 2
Show solutionHide solution
Overlap requires W + R > 5, so W + R >= 6.
- W = 3, R = 3: overlap (6 > 5); writes and reads each tolerate 5 - 3 = 2 failures.
- W = 2, R = 4: writes need only 2 acknowledgements (tolerate 3 failures) and are fast; reads need 4 (tolerate 1 failure) to overlap. Alternatively W = 1, R = 5, which makes reads fragile (no failures tolerated).
- W = 1, R = 1: fastest and most available (tolerate 4 failures each), with no overlap guarantee: eventual consistency.
Exercise 3
Show solutionHide solution
- "CP" is not a property of a product. Behaviour depends on configuration and on each operation: which read preference is used (primary or secondaries), which write concern, which read concern, and what happens during failover.
- Reads from secondaries can be stale if the application is configured to use them, and even primary reads during a failover can see rollbacks of unreplicated writes, depending on settings.
- Stale reads are not the only concern: concurrent updates still need conditional writes or transactions (article 14), and data shared across services is not covered by one database's guarantees at all.
- Thinking is still required: the candidate should state, per operation, what guarantee is needed and which settings provide it.
Exercise 4
Show solutionHide solution
(a) CP: only the side holding the authoritative copy (or a majority) accepts orders; the other side refuses or queues them. No overselling, but users on the cut-off side get errors for 10 minutes during a sale.
(b) AP: both sides keep selling from their own view of the stock. Total sales can exceed stock; after the link heals you must cancel some orders and apologise.
Better: split the stock in advance. Give each data centre an allocation (for example, 60% of units to the busier one, 40% to the other), each enforced locally with atomic decrements. During a partition each side sells its own allocation without coordination and can never oversell in total. When connected, the sides rebalance unsold allocation periodically. Some units may remain unsold on one side while the other sells out, which is a small, bounded cost compared with overselling or refusing everyone. This "escrow" or allocation idea is a common way to turn a global constraint into local ones.
Where to go next
#- Next: Idempotency, Retries and Message Delivery Guarantees, which makes retries safe in a world of partial failure and eventual consistency.
- Later: consensus for linearizable coordination (article 22) and multi-region design (article 24).
Sources & further reading
- Technology
- Software Engineering
- #CAP theorem
- #consistency
- #distributed systems
- #roadmap
- #scalability
- #system design
- #system design interview
Connected lessons
Linked from 1 guide
Other pages in the library that point here.
Keep reading
More in Technology →Guide · Technology
Start Here: Your Roadmap from Zero to Job-Ready DSA
Guide · Technology
Heaps and Priority Queues
Guide · Career
A LinkedIn Profile That Gets Recruiter Messages

