Consistency and the CAP Theorem
CAP and PACELC frame the fundamental tradeoffs between consistency, availability, and latency in distributed systems. Knowing the consistency spectrum lets you match guarantees to product requirements instead of over- or under-engineering.
What CAP actually says
The CAP theorem states that when a network partition occurs, a distributed system must choose between consistency (every read sees the most recent write) and availability (every request to a non-failed node gets a response). Partition tolerance is not optional: networks partition in practice, so the real choice is what happens during the partition. A CP system rejects or blocks some requests to stay correct; an AP system keeps answering with possibly stale data.
Common misreadings are worth correcting in an interview. CAP does not mean 'pick two of three at all times'; in the absence of partitions a system can be both consistent and available. Its C means linearizability, a much stronger guarantee than ACID's C (which just means constraints hold). And most real outages are not clean partitions but gray failures, slow links, and partial connectivity, so CAP is a lens rather than a design manual.
Classifying real systems: ZooKeeper and etcd are CP (a minority partition refuses writes because Raft or Zab needs a quorum). Cassandra and Dynamo-style stores default to AP (any replica set that can be reached keeps serving). A single-region relational primary with sync replication behaves CP-ish; DNS is the classic AP example, serving cached answers that may be stale.
PACELC: the latency dimension
PACELC extends CAP with the observation that the interesting tradeoff exists even without partitions: if a Partition occurs, choose Availability or Consistency; Else, choose Latency or Consistency. Strong consistency requires coordination, usually a round trip to a quorum or leader, and coordination costs latency on every single request, not just during failures.
The classification is compact and impressive to wield: DynamoDB and Cassandra are PA/EL, favoring availability under partitions and latency otherwise. Google Spanner is PC/EC, always choosing consistency; it makes global strong consistency practical with TrueTime, GPS and atomic clocks that bound clock uncertainty (typically under 7 milliseconds), letting it order transactions globally, at the price of commit-wait latency. MongoDB with majority write concern behaves PC/EC-ish; with weaker write concerns it slides toward EL.
The concrete intuition: a cross-region quorum write spanning US and Europe pays at least one transatlantic round trip, roughly 80 to 150 milliseconds, on every write. An eventually consistent write to the local region completes in single-digit milliseconds. That two-orders-of-magnitude gap on the hot path, not partition behavior, is usually why teams accept eventual consistency.
The consistency spectrum
Linearizability is the strongest practical guarantee: the system behaves as if there is a single copy of the data, and once any client sees a write, every subsequent read (in real time) sees it. It is what you need for uniqueness constraints, leader election, and locks, and it is what consensus systems (Raft, Paxos) provide. It is expensive because every operation coordinates.
Sequential and causal consistency relax real-time ordering. Causal consistency, the strongest guarantee achievable while staying available under partition, promises only that causally related events appear in order everywhere: a reply never appears before the comment it answers, though unrelated writes may interleave differently on different replicas. Systems track causality with version vectors or explicit dependency metadata.
Eventual consistency merely promises replicas converge if writes stop, with no bound on when. In practice it is packaged with client-centric session guarantees that fix the worst anomalies: read-your-writes (you see your own updates), monotonic reads (time never goes backward across your reads), monotonic writes, and writes-follow-reads. Azure Cosmos DB productizes this spectrum directly, offering five levels from strong through bounded staleness (lag at most K versions or T seconds) and session (its default) down to eventual, each level cheaper and faster than the one above.
Choosing consistency per feature
Strong consistency is a requirement, not a virtue, and it is a per-operation decision. Inventory decrement at checkout, account balances, username uniqueness, and permission revocation want linearizability: overselling the last item or letting a revoked user act is a real cost. Like counts, view counters, follower numbers, and activity feeds tolerate seconds of staleness invisibly, and nobody can even verify whether a view counter is exact.
A strong interview pattern is hybrid design within one product. An e-commerce checkout might read the catalog eventually consistently (cached, fast), but perform the final stock check and payment inside a strongly consistent transaction. A social app might write posts to a feed eventually consistently but enforce read-your-writes so authors always see their own post immediately.
When asked 'what consistency does your design provide', answer per data type and per operation, name the anomaly you are preventing or accepting, and state the price. 'Feed reads are eventually consistent, which risks a follower seeing a post a few seconds late; checkout is linearizable via a single-partition conditional write, which costs a quorum round trip' is a senior-level answer.
Key points
- ▸CAP: during a partition you choose consistency or availability; partition tolerance is mandatory because networks fail.
- ▸CAP's C is linearizability, not ACID's C; and the theorem constrains behavior only during partitions.
- ▸PACELC adds the everyday tradeoff: even without partitions, consistency costs latency (coordination round trips).
- ▸Spectrum from strong to weak: linearizable, sequential, causal, session guarantees (read-your-writes, monotonic reads), eventual.
- ▸Causal consistency is the strongest level compatible with availability under partition.
- ▸Choose consistency per operation: linearizable for money, uniqueness, and permissions; eventual for counters and feeds.
Tradeoffs
CP / strong consistency (Spanner, etcd, quorum writes)
Pros
- + No stale reads or lost updates; safe for invariants like uniqueness and balances
- + Simplest application code; no conflict resolution
Cons
- − Every operation pays coordination latency (cross-region quorums cost 80ms+)
- − Minority partitions refuse service, reducing availability
AP / eventual consistency (Cassandra, DynamoDB defaults)
Pros
- + Low latency from local reads and writes
- + Stays writable through partitions and node failures
Cons
- − Applications must tolerate stale reads and resolve conflicts
- − Anomalies (vanishing updates, out-of-order views) surface as user-facing bugs without session guarantees
In the interview
- ★Never claim your whole system is 'CP' or 'AP'; assign consistency per operation and justify each with the anomaly at stake.
- ★Drop PACELC when the interviewer raises CAP; noting that consistency costs latency even without partitions is a strong signal.
- ★Read-your-writes is the most commonly required session guarantee; explain concretely how your design provides it.
- ★Have examples memorized: etcd/ZooKeeper CP, Cassandra AP, Spanner PC/EC with TrueTime, Cosmos DB's five levels.