CS PAPERS DEEP-READ · PAPER 56
Fox & Brewer · UC Berkeley · HotOS-VII 1999
In 1999, two Berkeley researchers, Fox and Brewer (Brewer would state the famous CAP theorem a year later), asked a question that still bites today. When a big website runs on thousands of machines and a few of them die, we habitually think it's either "up" or "down" — black and white. But real large services are never like that. Their claim: don't treat "available" as a switch — treat it as a dial you can turn.
During a big sale you're trying to check out. The page is slow, or search returns only some of the results, or one small feature won't respond — yet the whole site doesn't crash, and you still buy your thing. That's not luck; it's "graceful degradation," by design. This paper is one of the first to turn "how to break down a little, gracefully" into a method.
People used to have only two black-and-white words: a system is "consistent" or not, "available" or not. This paper splits "available" into two things you can actually score:
A search that returns a few fewer results is "full yield, slightly discounted harvest." Split this way, "break down a little" suddenly offers two cheap ways to break.
The key insight: the amount of "data × requests" a machine can push per second has a physical ceiling. Lose a few machines and that total drops by a chunk. How you absorb the lost chunk is your choice — either put less data into each answer (lower harvest), or answer fewer requests but answer them fully (lower yield). Same failure, two very different experiences, decided by you in advance. One more move: break the system into non-interfering pieces, and pen the "must be exactly right" data into the smallest possible corner, so most of it can be "good enough for now, reconcile later" — and a failure only hits one small piece.
A year later Brewer distilled the trade-off here into CAP: consistency, availability, partition tolerance — you can't have all three. Nearly every large service's "degrade," "rate-limit to protect the core," "eventual consistency," and "success-rate SLO" traces its thinking to this. One honest cost: "half an answer is fine" only works for soft use cases like search and recommendation; when you check a bank balance, an incomplete or stale answer is simply wrong — better to answer nothing.
Don't treat "available" as a switch. Split it into two dials — "how many got answered" (yield) and "how complete each answer is" (harvest) — so when failure comes, you choose how to break gracefully instead of toppling over whole.
Want the DQ principle, the replication-vs-partitioning diagram, and how CAP came out of this? → switch to the deep read
In 1999 Fox and Brewer argued that a large service's "availability" shouldn't be a black-and-white switch but should split into two measurable, tradeable quantities — yield (the fraction of requests completed) and harvest (the fraction of data reflected in a single answer). This turns "what to do under failure" from "hold up or fall over" into an explicit choice: for the same failure, you can lower harvest (answer, but incompletely) or lower yield (answer fewer, but fully), degrading gracefully and staying as available as possible through faults and partitions. This short paper is also the first written statement of the "strong consistency and high availability can't coexist" trade-off — distilled a year later into the CAP theorem.
The authors are Armando Fox and Eric Brewer, both at UC Berkeley; the piece is a position paper at the 1999 HotOS-VII workshop — short, aimed at proposing a framework rather than running experiments. Brewer had earlier co-founded the search company Inktomi and lived the engineering of large cluster services, and the paper's examples are mostly framed around a search cluster. It inherits the authors' earlier cluster-services work (the 1997 Cluster-Based Scalable Network Services that introduced the BASE idea) and launches Brewer's CAP conjecture at PODC 2000 and the 2002 Gilbert–Lynch formal proof — this is the foundation stone right before CAP.
By the late 1990s internet services were exploding in scale, stacking hundreds to thousands of machines, and failure went from "exception" to "constant" — some fraction is always broken. The old ways of measuring reliability were ill-fitting in two places:
The deeper wall: the authors point out that strong consistency (all replicas always in agreement) and high availability cannot both hold when the network may partition. Once a partition splits the cluster into two halves that can't talk, you either let both halves keep serving (give up consistency, each writing on its own) or stop one half to preserve consistency (give up availability). This isn't sloppy engineering — it's a hard trade-off. Since you can't have both, and failure is constant, the authors argue: rather than chasing "never fail," design for "how to degrade gracefully when you do."
Yield = requests completed ÷ requests received. Its difference from uptime is that it's weighted by requests: a crash at peak has more requests in the denominator, so yield drops harder — exactly reflecting "peak failure is costlier." Intuition: yield answers "how many did you actually answer."
Harvest = data reflected in the answer ÷ complete data. It admits that "an answer can be partial": a search that skipped 5% of the corpus but still returns results from the other 95% has harvest = 95%. Intuition: harvest answers "how complete was your answer."
The big payoff of splitting them: failure no longer has only "answer" and "don't answer" as outcomes — a whole buffer of "answer, but less completely" opens up in between, which you can spend to keep "still answering."
The authors offer an empirical rule: near saturation, the product of data-per-request D and requests-per-second Q is roughly constant — capped by the system's physical capacity (memory bandwidth, disk, network). Written D × Q ≈ constant, in plain terms: "enough data and enough requests are the same cake — one grows only as the other shrinks."
This rule translates failure into one plain sentence: a failure that takes x% of capacity is a failure that cuts DQ by x%. Whether you take that cut out of D or out of Q is your choice.
The point: DQ forces you to admit "degradation is unavoidable"; the real design freedom left is "which way to degrade" — and that can be aligned with the business (do you want completeness, or an answer for everyone?).
For the same "one node dies" failure, how the data is laid out decides whether you lose yield or harvest:
The authors add a counterintuitive observation: near saturation, replication doesn't conjure extra capacity — because DQ is capped by a physical ceiling, replication and partitioning have the same total DQ. What replication actually buys isn't "more capacity" but "preserving harvest under failure." So replication vs partitioning isn't "which is faster" — it's "which quantity you'd rather keep."
The last move is architectural: split the application into mutually orthogonal, independently-failing subsystems, each with its own harvest/yield policy; and pen the "must be strongly consistent, must be persistent" hard state into the smallest piece possible, making the rest soft state (rebuildable, tolerant of stale values, eventually consistent). Then one failure hits only a small piece, and most of the system keeps serving with high availability. The authors stress that mechanisms should be orthogonal and composable — state and failures both stay local, so nothing pulls the whole system down.
This is a HotOS position paper: there are no benchmark tables — its "result" is a way of thinking that endures, plus corroboration from real systems, not experimental numbers. The highlights:
(The paper is mainly argument and design principle; no specific percentages or benchmark numbers are invented here.)
① In one line: split "availability" into yield (how many answered) and harvest (how complete), two measurable, tradeable quantities, turning failure from "hold up / fall over" into "how to degrade gracefully."
② The pain: at scale failure is constant; binary availability misses the "mostly fine, a few broken" middle, uptime underweights peak failure, and strong consistency and high availability can't coexist under partition.
③ yield = completed / received (weighted by requests, so failure costs more at peak); harvest = data covered / full data (admits partial answers).
④ DQ principle: at saturation D×Q≈constant (capacity conserved); a failure cuts a chunk of DQ, and you choose to take it from D (lower harvest) or Q (lower yield).
⑤ Replication keeps harvest, loses capacity (yield); partitioning keeps yield, loses harvest; at saturation both have equal total DQ — the difference is which quantity you keep.
⑥ Architectural move: decompose into orthogonal, independently-failing subsystems, and pen strong-consistency hard state into the smallest range, the rest soft state.
⑦ Impact: the direct ancestor of the CAP theorem; gave "graceful degradation / eventual consistency / success-rate SLO" a theoretical name.
⑧ Limits: harvest/yield never became common vocabulary; DQ is only a saturation approximation; CAP was later called too coarse (PACELC completes it); hard use cases can't lower harvest.