1Why is the 'pick two of three' framing of the CAP theorem misleading?
The CAP theorem proves that a distributed data store can provide at most two of three guarantees -- Consistency, Availability, and Partition tolerance -- during a network partition. This deep dive moves beyond the simplified 'pick two' framing to explore how real systems navigate the CAP spectrum and why partition tolerance is non-negotiable in production.
The CAP theorem, first conjectured by Eric Brewer at PODC 2000 and formally proved by Seth Gilbert and Nancy Lynch in 2002, is the most cited -- and most misunderstood -- result in distributed systems. The theorem states that in the presence of a network partition, a distributed data store must sacrifice either consistency (linearizability) or availability (every non-failing node responds). Since partitions are a fact of life in any networked system, the practical question is not 'pick two of three' but rather 'when a partition occurs, do you favor consistency or availability?'
The 'pick two' framing is misleading because it implies you can have CA without P -- but network partitions are not optional; they happen due to switch failures, cable cuts, GC pauses, and cloud provider issues. Every production distributed system must handle partitions. The real design space is a spectrum: most of the time (when there is no partition) you can have both C and A, and you only need to make the hard choice during the (hopefully rare) partition events. This is why Daniel Abadi proposed the PACELC extension: even without partitions, there is a latency-consistency trade-off.
Modern systems have moved beyond a single global CAP choice to per-operation tunability. DynamoDB lets you choose between eventually consistent reads (low latency, AP behavior) and strongly consistent reads (higher latency, CP behavior) on each individual request. Cassandra lets you set consistency levels per query (ONE, QUORUM, ALL). CockroachDB defaults to serializable isolation (CP) but allows stale reads via AS OF SYSTEM TIME for read-heavy analytics workloads. This per-operation flexibility is the practical realization of the CAP theorem.
Understanding CAP deeply means recognizing what it does NOT say: it does not say you must always sacrifice one guarantee; it does not apply to single-node systems; it does not address latency; and it does not distinguish between different consistency models weaker than linearizability. Causal consistency, for example, can be achieved without sacrificing availability -- the CALM theorem proves that monotone programs can be made both available and consistent. These nuances are what separate a senior engineer's understanding from a surface-level recitation.
ATM Network During a Partition
Two ATMs serve the same bank account with a $500 balance. A network partition cuts communication between them. Customer A withdraws $400 at ATM-1. Customer B tries to withdraw $400 at ATM-2. A CP system would reject B's request (ATM-2 cannot confirm the current balance), preserving consistency but sacrificing availability. An AP system would allow B's withdrawal (ATM-2 uses its last-known balance of $500), providing availability but causing an overdraft -- the bank loses $300. Real ATMs use an AP approach with risk limits: small withdrawals are allowed offline (AP), but large withdrawals require online authorization (CP). This per-operation tuning is how real systems navigate CAP.
Amazon DynamoDB
DynamoDB is fundamentally an AP system -- during partitions, it favors availability. However, it offers per-read consistency tuning: eventually consistent reads (default, half the cost, lower latency) vs strongly consistent reads (routed to the leader replica, higher latency). This lets developers choose CP behavior for critical reads (e.g., account balance checks) and AP behavior for latency-sensitive reads (e.g., product catalog) within the same table.
Google Spanner
Spanner is a CP system that minimizes the availability cost through engineering. It uses TrueTime (GPS + atomic clocks) to provide globally consistent timestamps, enabling externally consistent (linearizable) transactions across continents. During partitions, Spanner sacrifices availability: affected partitions become unavailable. Google mitigates this by investing heavily in network redundancy to make partitions extremely rare within their private network.
Apache Cassandra
Cassandra is an AP system by default (writes and reads at consistency level ONE succeed even during partitions), but it supports tunable consistency. Setting both reads and writes to QUORUM provides strong consistency when a majority of replicas are reachable. With ALL, it behaves as CP. Cassandra also supports lightweight transactions (LWT) using Paxos for linearizable operations on individual partitions, enabling CP behavior for specific critical operations.
| Aspect | Description |
|---|---|
| Consistency vs Availability During Partitions | This is the core CAP trade-off. CP systems (Spanner, etcd, ZooKeeper) reject operations when they cannot guarantee consistency, causing downtime for affected partitions. AP systems (DynamoDB default, Cassandra at CL=ONE) continue serving requests but may return stale or conflicting data. The right choice depends on your domain: financial transactions demand CP; shopping carts and social feeds tolerate AP. |
| Consistency vs Latency (PACELC) | Even without partitions, strong consistency requires coordination (leader round-trips, quorum reads) that adds latency. Spanner pays 7-15ms per write for Paxos consensus. DynamoDB eventually consistent reads are 2x cheaper and lower latency than strongly consistent reads. For read-heavy workloads, this latency difference is the dominant design factor, not partition behavior. |
| Global Consistency vs Operational Simplicity | Achieving global consistency (Spanner-style) requires sophisticated infrastructure: TrueTime, dedicated network links, custom hardware. Most organizations cannot replicate this. CockroachDB approximates it with NTP-synchronized clocks and uncertainty intervals, but this adds complexity. An AP design with application-level conflict resolution (last-write-wins, CRDTs) is operationally simpler for many use cases. |
| Per-Operation Tuning vs Cognitive Overhead | Per-operation consistency levels (Cassandra CL, DynamoDB read modes) offer maximum flexibility but increase developer cognitive load. Engineers must reason about consistency for every query. A simpler approach is a global default (e.g., QUORUM everywhere) with explicit exceptions. Over-tuning per query often leads to subtle consistency bugs that surface only under partition conditions. |
Amazon's Dynamo and the Shopping Cart
Scenario
In the early 2000s, Amazon needed a key-value store for the shopping cart service. The shopping cart had to be always-writable: a customer adding an item should never see an error, even during data center failures or network partitions. However, traditional CP databases (like MySQL with synchronous replication) would reject writes when replicas were unreachable, directly impacting revenue.
Solution
Amazon built Dynamo (the internal predecessor to DynamoDB), an AP system using consistent hashing, vector clocks for conflict detection, and sloppy quorums with hinted handoff. During partitions, writes were accepted on any available node and reconciled later. Conflicting shopping cart states were merged using application-level logic (union of items -- it is better to show a deleted item than to lose an added one). The system prioritized availability over consistency.
Outcome
Dynamo achieved 99.995% availability for the shopping cart, directly measured in customer-facing uptime. The AP design meant occasional duplicate items appeared in carts after partition recovery, but this was a minor UX issue compared to the revenue loss of rejected writes. The Dynamo paper (2007) became one of the most influential papers in distributed systems, spawning Cassandra, Riak, and Voldemort. It demonstrated that for commerce workloads, the AP side of CAP is often the correct choice.
See CAP Theorem Deep Dive in action
Explore system design templates that use cap theorem deep dive and run traffic simulations to see how these concepts perform under real load.
Browse Templates1Why is the 'pick two of three' framing of the CAP theorem misleading?
2What does the PACELC theorem add to CAP?