CS PAPERS DEEP-READ · PAPER 54
DeCandia et al. · Amazon · SOSP 2007
In 2007, Amazon published the design of its internal storage system, Dynamo. It powers things like the shopping cart: during a Black Friday rush, with machines failing in the datacenter and the network occasionally hiccupping, when you add an item to your cart, that write must never fail. The whole paper answers one question: how do you build storage that is "always writeable"?
Traditional databases live by one rule: data must be consistent at all times—everyone always sees the same latest value. To hold that line, when a failure or network split hits, they would rather refuse service than let the data diverge. Dynamo bets the other way: it would rather let data diverge briefly than turn a user away. For a shopping cart, "add-to-cart failed" is far worse than "the cart briefly holds an extra item we'll reconcile later."
With thousands of machines, which one stores a given key (say, a user's cart)? Dynamo imagines all machines seated around a round table, each holding a seat number. It hashes the key to a number, and the first machine you reach walking around the table is responsible for it—plus the next two, for three copies. The beauty: adding or removing one machine only affects its two neighbors; almost all other data stays put. Scaling up or down needs no big migration.
What if the machine you meant to write to is down? Dynamo doesn't wait—it hands the data to the next live neighbor around the table to "sign for it," attached with a note saying "this really belongs to Machine X." When the original recovers, the neighbor delivers the held data plus the note back. So writes almost always land somewhere.
If the same cart got edited on two machines, you now have two versions. Dynamo won't silently pick a winner for you—it keeps both, and hands them over together the next time someone reads, letting the application merge them. The cart's merge rule is simple: take the union—keep everything either side added (an extra item is better than a lost one). The cost is honest: the app must write this "what to do with two versions" logic itself, rather than leaving it all to the database.
To stay "always writeable," Dynamo deliberately gives up "always consistent": a round-table scheme decides where data lives so scaling needs no big migration, a dead machine's writes are signed for by a neighbor, and divergent versions coexist and get merged by the app at read time. This "eventual consistency" playbook ignited a whole generation of NoSQL databases—Cassandra, Riak, DynamoDB, and more.
Want the consistent-hashing ring, vector clocks, and the R+W quorum mechanics? → switch to the deep read
Dynamo is Amazon's highly available key-value store for core services like the shopping cart: it places "always-writeable" above strong consistency, using consistent hashing for data placement, a tunable N/R/W quorum for replicated reads and writes, vector clocks to track version causality and hand conflicts to the application, and sloppy quorum + hinted handoff to ride out transient failures—putting the CAP trade-off squarely in the operator's hands and becoming the founding work of "eventually consistent" NoSQL.
put(key,value) and get(key), with no SQL-style complex queries or cross-table joins.The authors are Amazon's Giuseppe DeCandia, Deniz Hastorun, Werner Vogels (then Amazon's CTO), and others, published at SOSP 2007. It stands on distributed-systems classics like Chord (2001, consistent hashing and DHTs) and Lamport's vector/logical clocks (1978), and assembles those academic building blocks into a system that actually runs in production. It, in turn, gave rise to Cassandra, Riak, Voldemort, and eventually DynamoDB—the ancestral blueprint for the whole "eventually consistent NoSQL" line.
Amazon's e-commerce platform is stitched from hundreds of services, runs at enormous scale, and always has machines and networks failing—"failure is the normal case, not the exception." In that world, many core services (cart, sessions, seller rankings) place one near-brutal demand on storage: never turn me away. "Add to cart," in particular, must not fail even if the datacenter is half-crippled or the network is partitioned—one failed add is a lost order.
But relational databases and most strongly consistent stores take the opposite philosophy: to guarantee "every read returns the one latest value," they will block or even reject writes under failure or partition. By CAP, once the network partitions, you can keep only one of consistency (C) and availability (A). Amazon's business judgment: here, availability far outweighs immediate consistency. A cart briefly showing two versions and reconciled afterward is nearly invisible to the user; a failed add loses them instantly. Dynamo is the product of taking that trade the other way: sacrifice immediate strong consistency to buy "always writeable."
Dynamo is not a single new algorithm but a set of known techniques assembled around the goal of high availability—each piece serving "don't turn users away, self-heal after failures, scale without downtime." Piece by piece.
With thousands of machines, which one does a key land on? The naive approach is "hash mod machine-count," but then adding or removing one machine reassigns almost every key—a full migration. Dynamo uses consistent hashing: it joins the ends of the hash range into a ring; each machine hashes to a position on it. A key belongs to the first machine you reach walking clockwise from its hash point—called that key's coordinator.
For load balancing, Dynamo gives each physical machine multiple positions on the ring (called virtual nodes), spreading data more evenly and letting heterogeneous machines carry load in proportion to their capacity.
The coordinator doesn't hoard the data—it plus the next N−1 machines on the ring each keep a copy, for N replicas (typically N=3). Those N machines form the key's preference list. If any one dies, others on the list keep serving.
With N replicas, how many must a write reach and a read touch to count as success? Dynamo exposes two tunable parameters: a write needs at least W replicas to acknowledge, a read needs at least R replicas to respond. The key design is to keep R + W > N: because "the W that were written" and "the R that were read" must overlap in at least one replica out of N, any read touches at least one replica holding the latest write—overlap in numbers buys "reads won't entirely miss the latest write."
The knob is tunable: (N,R,W)=(3,2,2) is a common balance; lowering W=1 means a write returns after just one ack—extremely fast and nearly impossible to fail (more available); raising R makes reads more likely to catch the latest. Each service can turn it to fit "read-heavy vs write-heavy, and how stale it can tolerate."
But what if the top few machines on the preference list happen to be down and you can't gather W acks? A strict quorum would reject the write—exactly what Dynamo can't accept. It uses a sloppy quorum: the write walks further down the ring to the next live machines to reach W copies, and a machine "standing in for another" records a hint saying "this data really belongs to the down machine." When the original recovers, the stand-in hands off the data plus hint back, then deletes its local copy. This hinted handoff makes writes almost never fail and lets data return to its home automatically after the failure passes.
The price of giving up immediate strong consistency is that one key may hold multiple versions at once (e.g. two writes on either side of a partition). The trouble: reading two versions, how do you tell "one is a newer version of the other (just overwrite)" from "they truly conflict (each edited independently, need merging)"? Dynamo solves this with vector clocks—each version carries a list of (node, counter) marks recording which nodes edited it, in what order, how many times. Compare two versions' vector clocks: if every entry of A is ≥ B and at least one is larger, then A is a descendant of B—just use A (this is syntactic reconciliation); if neither dominates (each has updates the other lacks), they truly conflict.
Dynamo does not resolve true conflicts on its own—it returns the conflicting versions together to the application, which performs semantic reconciliation by business meaning. The cart's rule is remarkably simple: take the union of the two versions, keeping every item either side added. The worst case is a deleted item "resurrecting," but versus losing an order, that's a good trade.
Hinted handoff only cures transient failures; when a machine dies for good, replicas drift apart for the long term. Dynamo uses Merkle trees for anti-entropy: each replica hashes its data into a tree, then the two compare hashes level by level, descending only into subtrees that differ—pinpointing differences and repairing just the divergent part with minimal data transfer. Membership uses a gossip protocol: with no central node, each machine periodically exchanges "who I know is alive and what the ring looks like" with random peers, so failure detection and membership changes spread through the cluster this way—fully decentralized, every node a peer.
Dynamo is an engineering systems paper, not a benchmark paper—its "result" is that it actually ran Amazon's core services in production: cart, session management, seller rankings, parts of S3, and dozens more. The paper centers on 99.9th-percentile latency (not the average), reports measured behavior under strict SLAs (e.g. high-percentile latency within hundreds of milliseconds), and shows how different (N,R,W) settings shift the trade-off point among latency, durability, and consistency: set W to 1 and writes almost never fail; raise R and W and reads are more consistent but slower. It also quantifies how partitioning/placement strategies affect load balance. The most persuasive conclusion is that a system deliberately sacrificing immediate consistency can, at real large scale in production, come close to never refusing a write.
Dynamo turned the abstract "availability vs consistency" trade-off into a concrete, tunable, self-healing engineering pattern for the first time, and put the CAP choice explicitly in the operator's hands. Almost single-handedly it ignited the NoSQL and "eventual consistency" movement: Cassandra (Facebook—directly inheriting Dynamo's consistent hashing + tunable quorum), Riak, and Voldemort are its direct descendants; many of its mechanisms—consistent hashing, preference lists, R+W quorums, vector clocks/version conflicts, hinted handoff, Merkle anti-entropy, gossip membership—are now the common vocabulary of distributed storage. Years later Amazon's managed service DynamoDB borrowed the name (though it is a ground-up rewrite). It's fair to say that any discussion of "highly available distributed databases" today runs through this paper.
① One line: Dynamo is Amazon's highly available key-value store built so the "cart never refuses a write," trading immediate consistency for perpetual availability.
② Trade-off: under CAP it explicitly picks A (availability) over immediate C—a failed add is far worse than briefly divergent data.
③ Placement: consistent hashing arranges machines on a ring; a key finds its first clockwise machine as coordinator, and adding/removing a machine only moves a neighboring arc (virtual nodes for load balance).
④ Replication: the coordinator plus the next N−1 machines hold N copies, forming the preference list.
⑤ Knob: write W copies, read R copies, with R+W>N so read and write sets must overlap—consistency tunable per workload.
⑥ Fault tolerance: sloppy quorum + hinted handoff—if a home machine is down, a neighbor signs for the write with a hint and hands it back on recovery, so writes almost never fail.
⑦ Conflicts: vector clocks record version causality; dominated versions auto-resolve, true conflicts coexist and are merged by the app's semantics (cart union).
⑧ Self-healing: Merkle-tree anti-entropy repairs long-term drift, gossip spreads membership and failures with no center—fully peer-to-peer.
⑨ Impact: ignited NoSQL and eventual consistency, the ancestor of Cassandra / Riak / Voldemort, its mechanisms now standard distributed-storage vocabulary.
⑩ Limits: merge logic offloaded to the app, vector clocks bloat, sloppy quorums allow occasional stale reads/lost writes, tuning and ops have a learning curve; DynamoDB is a ground-up rewrite.