Consistency models and the CAP theorem
SeniorWhat CAP actually constrains, strong vs eventual vs causal consistency, and why most real systems live somewhere in between.
Created 4 September 2026 · Updated 12 September 2026
7 concepts · detail hidden
01The CAP theorem — what it actually forces, and the common misreading
#c-the-cap-theorem-what-it-actually-forces-and-the-common-misreFor a distributed system, during a network partition (P — some nodes cannot communicate with others, which real networks will eventually experience), you must choose between Consistency (every read sees the most recent write, or an error) and Availability (every request receives a non-error response, even if it might not be the most recent data). You cannot have both during the partition. The most common misreading: treating CAP as “pick 2 of 3 permanently” — Partition tolerance is not optional for any real distributed system spanning more than one node/network segment, so the actual choice is CP vs AP, and only during an active partition; when the network is healthy (the common case), a well-designed system can be both consistent and available simultaneously. CAP says nothing about latency or normal-operation trade-offs — that gap is what the PACELC extension addresses.
02What PACELC adds to CAP, and why it matters more day to day
#c-what-pacelc-adds-to-cap-and-why-it-matters-more-day-to-dayPACELC: if there is a Partition, choose between Availability and Consistency (this is plain CAP); Else (no partition, normal operation), choose between Latency and Consistency. This matters more day-to-day because partitions are relatively rare events, while the latency/consistency trade-off during normal operation is active on every single request: a system that always reads from a strongly-consistent source (e.g. always the primary, or a quorum) pays a real, constant latency cost even when nothing is wrong, versus one that allows reading from a nearby replica that might be milliseconds-to-seconds stale for lower, more predictable latency. Most real architecture decisions (read replicas, caching, geo-distributed reads) are actually PACELC trade-offs made during healthy operation, not CAP trade-offs made during a rare partition — which is why PACELC is the more practically useful framing when reasoning about a concrete system.
03Strong vs eventual vs causal consistency — definitions and where each fits
#c-strong-vs-eventual-vs-causal-consistency-definitions-and-whe- Strong consistency — every read reflects the most recent completed write, as if there were only one copy of the data. Right when correctness depends on it directly — a bank balance check before approving a withdrawal, a seat reservation system where double-booking is unacceptable.
- Eventual consistency — replicas will converge to the same value eventually, with no bound on how long “eventually” takes under adverse conditions, but reads in between can return stale or differing values across replicas. Right when brief staleness is harmless and availability/latency matter more — a social media like-count, a product view counter, most caches.
- Causal consistency — a middle ground: writes that are causally related (a reply to a comment, an edit that depends on reading a prior value) are seen by every observer in that same causal order, but causally-unrelated writes can be observed in different orders by different replicas. Right when full strong consistency is too expensive but “eventual, with no ordering guarantee at all” would produce visibly nonsensical results — e.g. a comment thread must never show a reply before the comment it replies to, even if unrelated comments elsewhere can appear in any order across users.
05Quorum reads/writes (`W + R > N`) — tuning consistency vs availability
#c-quorum-readswrites-w-r-n-tuning-consistency-vs-availabilityFor a dataset replicated across
Nnodes, define a write quorumW(writes must be acknowledged by at leastWreplicas to succeed) and a read quorumR(reads must consult at leastRreplicas and return the most recent value among them). IfW + R > N, any read quorum and any write quorum are guaranteed to overlap in at least one replica, so a read is guaranteed to see the most recent successful write — this is how systems like Cassandra or DynamoDB let you dial consistency per operation rather than committing to one system-wide policy:W = N, R = 1gives fast reads at the cost of slow, less-available writes (every replica must ack);W = 1, R = Ngives fast writes at the cost of slow reads;W = R = (N/2 + 1)(majority quorums) balances both while tolerating some node failures. ChoosingW + R <= Ndeliberately trades this guarantee away for lower latency/higher availability, accepting that a read can occasionally miss the most recent write — a legitimate choice for workloads that can tolerate it.06The real cost of "just make everything strongly consistent"
#c-the-real-cost-of-just-make-everything-strongly-consistentThe reasoning-simplicity argument is genuinely real — eventual consistency introduces real application-level complexity (handling stale reads, conflict resolution, causal-ordering bugs) that strong consistency sidesteps entirely. The cost that argues against defaulting to it everywhere: availability and latency, concretely — every write (and often every read, depending on the design) now depends on reaching a quorum or a single leader, so a partition or a slow node directly becomes user-facing unavailability or latency rather than being absorbed; and it does not scale horizontally for free the way eventually-consistent replication does, since coordination overhead grows with replica count and geographic spread. Push back specifically when: the workload is read-heavy and tolerant of brief staleness (most content-serving systems), the system needs to serve users across regions with low latency, or availability during a partial outage genuinely matters more than every reader seeing the absolute latest write (most consumer-facing products, versus a financial ledger). The right answer is rarely “always strong” or “always eventual” — it is picking consistency per data type, since most real systems have both a small strongly-consistent core (payments, inventory counts, auth) and a much larger eventually-consistent periphery (feeds, counts, recommendations) in the same product.
07Read-your-own-writes — a bug from assuming stronger consistency than you have
#c-read-your-own-writes-a-bug-from-assuming-stronger-consistencA common one: a service writes a record to a primary database, then immediately reads it back from a read replica to confirm and use in the same request — under asynchronous (eventually consistent) replication, that read can miss the write entirely if it lands on the replica before replication lag catches up, producing a spurious “not found” or stale value right after a successful write, even though nothing actually failed. This is the read-your-own-writes consistency violation, and it is a frequent real bug specifically because eventual consistency’s staleness window is often small enough in testing/low-load conditions to go unnoticed, then shows up intermittently in production under real replication lag. Fixes: route the immediate post-write read to the primary rather than a replica for that specific request (session-level read-your-writes guarantee), or design the write path to return the written value directly from the write call itself rather than requiring a separate read at all.