shreyansh

CAP PACELC and Consistency Models

30-Second Glance

  • "Pick 2 of 3" is the misleading slogan: CAP only binds during a network partition; the rest of the time you're trading latency against consistency (that's PACELC).
  • Consistency is a spectrum — linearizable > sequential > causal > eventual — and each step down buys latency/availability; name where your system sits and what anomaly you accept.
  • CP systems (etcd/ZooKeeper, HBase, MongoDB primary) refuse or stall writes on partition; AP systems (Cassandra, DynamoDB, CouchDB) accept writes everywhere and reconcile later.
  • Placement rule: per-key/single-leader paths can be linearizable cheaply; cross-region and leaderless paths pay milliseconds-to-seconds for it — so put strong consistency only where money/coordination lives.
  • Linearizability's formal deep dive lives in Linearizability — this note is the map, that note is the territory.

CAP, Precisely Stated

Gilbert–Lynch CAP: when a network partition occurs, a distributed read/write store chooses between consistency (every read sees the latest committed write — linearizability in the proof) and availability (every non-crashed node answers, even if stale). Partition tolerance isn't optional — networks partition — so the real choice is CP vs AP during partitions.

The "pick 2" triangle misleads three ways, and interviewers reward candidates who say so:

  1. Partitions are rare; latency is forever. Most of a system's life has no partition, and CAP says nothing about that period. A "CP" and "AP" system can behave identically with no partition.
  2. Availability and consistency are not binary. Timeouts, 99.9% vs 99.99%, stale-by-100ms vs stale-by-minutes — the choice is a dial (how long do you wait before giving up and serving stale?) not a switch.
  3. One system makes different choices per operation. Cassandra with QUORUM reads/writes is CP-ish per operation; with ONE it's AP — same cluster, dial turned per query (see Quorums for the R+W>N machinery).

The usable interview framing: "CAP governs behavior during partitions; my SLA numbers (timeout, retry, staleness bound) govern everything else."

PACELC: The Completion

PACELC (Abadi): if Partition, trade Availability vs Consistency; Else, trade Latency vs Consistency. The "else" clause is where systems actually live:

  • ELC (else-latency-consistency): DynamoDB/Cassandra quorum reads pay cross-replica RTT for freshness; ONE reads return in single-digit ms but may be stale. Leader-based systems (see Single Leader Replication) route writes through the leader — one extra hop of latency buying a single serialization point.
  • EEC: Spanner/TrueTime and Calvin-style deterministic systems spend latency budget (commit-wait ~2× clock uncertainty, ~5–10 ms) to keep consistency even in the common case.
  • Classify systems both halves: Spanner = PC/EC (consistent under partition by stalling, consistent otherwise by waiting); Dynamo/Cassandra = PA/EL (available under partition, low-latency otherwise, consistency dialed per op); etcd/ZooKeeper = PC/EC for coordination-sized data only.

Draw it as the triangle-plus-else and place two systems on it — instant senior signal.

loading diagram…

The Consistency Spectrum

Strongest to weakest, each with its guarantee and its price. Formal definitions and the Alice-and-Bob recency examples are the deep dive in Linearizability; here is the ordering interviewers expect you to rattle off:

Model Guarantee Price / mechanism Typical home
Linearizability Every operation appears atomic at a point between invocation and response; reads never go back in time Quorum or leader round trip per op (~RTT to 2×RTT); unavailable on partition minority side etcd, ZooKeeper, Spanner, single-leader primary reads
Sequential consistency All clients see one common operation order (but it may lag real time) Still needs total-order broadcast; marginally cheaper, rarely offered alone Historical multiprocessors; mostly a teaching step
Causal consistency Causally related ops seen in order; concurrent ops may differ across replicas Dependency tracking (see Version Vector, Lamport Clocks); metadata overhead COPS, Eiger, causal stores, chat/comment threads
Read-your-write / monotonic reads (session guarantees) Within one client session: see your own writes, never read older after newer Sticky routing or client-side version tokens; cheap Leaderless with sticky sessions, CDN session affinity
Eventual consistency Replicas converge if writes stop — no bound on when Anti-entropy (Merkle trees, gossip), last-write-wins or CRDT merge; cheapest + most available DynamoDB default reads, Cassandra ONE, S3, DNS

Two nuances that score points. First, linearizability vs serializability: linearizability is a single-object recency guarantee; serializability is multi-object transaction isolation (the "I" in ACID). Spanner gives both (externally consistent transactions); a linearizable register store with no transactions gives only the first. Second, CRDTs (see CRDTs) let AP systems converge without last-write-wins data loss — counters, sets, and collaborative-text types merge commutatively.

CP vs AP: System Mapping

System CAP stance Mechanism Staleness / behavior on partition
etcd / ZooKeeper (via Coordination Services) CP (PC/EC) Raft/ZAB quorum — see Raft Leader Election, Raft Writes Minority side stops serving writes; linearizable reads via quorum
HBase / MongoDB (primary) CP Single-leader; failover needs majority Partitioned minority unavailable until new leader elected (~10s)
Spanner / CockroachDB CP (PC/EC) Paxos/Raft per shard + TrueTime/clock-bounded waits Stalls rather than serves stale; cross-region writes ~50–100 ms
Cassandra / DynamoDB / Riak AP, tunable (PA/EL) Leaderless, hinted handoff, read repair; R+W vs N dial Accepts writes on all sides; conflicts resolved by LWW/CRDT/vector clocks
CouchDB / Dynamo default reads AP Multi-master + async replication Reads may lag seconds; conflicts surfaced to app
Kafka (ISR) / SQS FIFO CP-flavored durability ISR quorum ack (min.insync.replicas) Refuse produce rather than risk loss when ISR shrinks

How to choose in an HLD interview — three sentences: coordination metadata (locks, leader election, config, unique IDs) goes to a CP store because split-brain there corrupts everything; user-facingOLTP with a partitionable keyspace goes leaderless/quorum-tunable so one AZ failure doesn't halt writes; and cross-region, the speed of light (~70–100 ms RTT US–Asia) forces the question "is linearizability across oceans worth 200 ms on every write?" — almost always no, hence single-region-linearizable plus async cross-region replication as the default global topology.

Trade-offs

Approach Pros Cons Use when
Linearizable (CP, quorum/leader) No stale reads, safe coordination, simple app reasoning RTT+ per op, minority-side unavailability, cross-region latency Locks, leader election, uniqueness, money ledger per region
Causal + session guarantees Cheap, matches human intuition for feeds/threads Concurrent-write anomalies remain; needs version metadata Social, chat, collaborative apps
Eventual (AP, W+R≤N) Single-digit-ms reads, writes survive partitions, simplest scaling Stale reads, conflicts, app must reconcile Catalogs, carts (mergeable), DNS/CDN-style data, analytics
Tunable quorum per operation One cluster serves both (QUORUM for money, ONE for previews) Operators must actually tune it; mixed-mode reasoning burden Cassandra/Dynamo/Riak shops with heterogeneous access patterns
Single-region-strong + async-global Strong where users are, fast everywhere Cross-region conflicts/lag on failover; RPO > 0 across regions Default global topology — strong local, eventual global

Interview One-Liners

  • Q: CAP — pick two? A: Only during a partition, and partitions are the rare case; the daily trade is PACELC's else-branch — latency vs consistency — tuned per operation, not per system.
  • Q: When would you choose CP over AP? A: When split-brain corrupts invariants: locks, leader election, uniqueness constraints, ledger writes — and I'd isolate that CP state in etcd/ZooKeeper rather than making the whole product CP.
  • Q: Linearizable vs serializable? A: Linearizability is single-object recency (reads never go stale); serializability is multi-object transaction isolation — you can have either without the other.
  • Q: How does Cassandra tune CAP per query? A: R+W vs N quorums: QUORUM/ALL leans CP with cross-replica latency; ONE leans AP with possible staleness — same cluster, dial per operation.
  • Q: Strong consistency across three continents? A: Physics says no without ~200 ms writes, so: linearizable within the home region, async replication + CRDT/LWW merge globally, and failover accepts bounded staleness.
  • Q: What's the cheapest consistency that still feels correct in a feed? A: Causal + read-your-write session guarantees — replies after posts, own posts visible instantly — without paying quorum RTT on every read.
  • Q: Where do vector/Lamport clocks fit? A: They track causality so replicas can order concurrent writes and detect conflicts — the machinery under causal stores and Dynamo-style reconciliation.