CAP Theorem and PACELC
easyThe CAP theorem says a distributed data store can guarantee at most two of Consistency, Availability, and Partition tolerance. Because partitions are unavoidable in the real world, the practical choice is between Consistency and Availability during a partition.
Key Concepts
Approach
- Pin down the consistency model in plain language: linearizable, serializable, snapshot, causal, read-your-writes, eventual.
- Identify the partition pattern. Same rack? Same AZ? Cross-region? Long-lived netsplit?
- Decide per-data-class, not per-system. Orders and inventory want CP; counters and recommendations want AP.
- Pick a store that supports the chosen mode. CP options: Spanner, CockroachDB, etcd, HBase. AP: Cassandra, DynamoDB, Riak. Tunable: Cassandra, DynamoDB, Couchbase.
- Decide quorum settings. For Dynamo-style: R + W > N gives strong reads. R=W=1 = eventual; R=W=N = full agreement, low availability.
- Handle the AP case explicitly: conflict resolution (LWW, vector clocks, CRDTs), read repair, anti-entropy.
- Now layer in PACELC. Async replication for cheap reads; sync only where staleness is unacceptable.
Components
- Replication protocol — sync, semi-sync, async, quorum-based.
- Replica placement — same AZ, cross-AZ, cross-region, with proximity rules.
- Conflict resolution — Last-Write-Wins timestamps, vector clocks, CRDTs (G-counters, OR-sets), domain merge functions.
- Failure detection — heartbeats, gossip (SWIM), phi-accrual.
- Leader election or coordinator — Raft, Paxos, single-master with promotion.
- Client-side routing knowledge — which replica owns this key, which is leader, fall-back order.
- Anti-entropy — Merkle tree compare, read repair, periodic full sync.
Trade-offs
CP: simpler app code, fewer surprises, but a partition or leader loss means the minority side returns errors. Acceptable if your SLO is correctness over uptime.
AP: never tells the user 'no', but conflict resolution and read repair complexity bleed into the application. Stale data is a UX problem unless you compensate (read-your-writes, session stickiness).
Latency vs consistency in the no-partition case (PACELC): sync replication = correct + slow tail; async = fast + potentially stale. Most products land on async cross-region replication with strong consistency only on the primary region.
Hybrid is the real answer: ledger CP, derived views AP, search index eventually consistent on a separate path.
Real-world systems
- Spanner: CP system using TrueTime to bound clock uncertainty; achieves external consistency globally at the cost of write latency tied to the TT interval.
- CockroachDB: Raft per range; CP with tunable transactional isolation.
- DynamoDB: AP by default with eventual reads; opt into strongly-consistent reads at 2x cost and higher latency.
- Cassandra: tunable per-query consistency; QUORUM reads + QUORUM writes give linearizability under R+W>N.
- etcd / ZooKeeper: CP coordination services; never use for high-throughput data, only for config and leases.
Common interview pitfalls
- Treating CAP as a static label for the whole system. Real systems mix per-table.
- Forgetting that 'P' is not optional — partitions will happen.
- Claiming a system is 'CA' — that just means no partitions are tolerated, which is unrealistic for distributed systems.
- Confusing eventual consistency with weak consistency. Eventual = converges if writes stop; weak = no guarantees.
- Ignoring PACELC and missing the day-to-day latency trade-off, which dominates user-perceived performance.