Skip to content
Dynamo: Amazon's Highly Available Key-value Store 7 min
Back to Papers

Giuseppe DeCandia, Werner Vogels, Peter Vosshall, Swaminathan Sivasubramanian, Alex Pilchin, Avinash Lakshman, Gunavardhan Kakulapati, Madan Jampani, Deniz Hastorun · SOSP 2007

Dynamo: Amazon's Highly Available Key-value Store

Amazon's shopping cart can never say no. This paper shows how Dynamo trades strict consistency for always-on availability using consistent hashing, sloppy quorums, and vector clocks, the same ideas behind Cassandra and Riak today.

Read the original paper

Systems & Distributed · intermediate · 7 min read

Dynamo: Amazon's Highly Available Key-value Store

In 2004, an Amazon shopping cart went down during a routine failure and refused to accept new writes even though most of the system was healthy. That single incident, and dozens like it, pushed a team inside Amazon to ask a question most databases at the time were not designed to answer honestly: what should happen when a machine you depend on simply disappears?

Their answer, published in 2007 as "Dynamo: Amazon's Highly Available Key-value Store," is not a general-purpose database. It is a narrow, opinionated storage system built for one job: never refuse a write, no matter how many nodes have failed. To get there, the authors were willing to give up something every database course teaches you to protect: strong consistency. This breakdown walks through exactly how they did it, and why the tricks they invented (consistent hashing, vector clocks, quorum reads and writes, hinted handoff) are still the vocabulary every distributed systems interview leans on today.


The problem: "always writable"

Amazon's internal services, most famously the shopping cart, have one hard requirement: a customer must always be able to add an item to their cart. Rejecting a write because a database node is briefly unreachable is a direct hit to revenue. This is a different priority than a bank ledger, where refusing a transaction is safer than accepting a wrong one.

That priority maps directly onto the CAP theorem: during a network partition, you must choose between Consistency and Availability. Dynamo chooses Availability, every time. It is what systems designers now call an AP system. The rest of the paper is essentially an engineering answer to the question: "if we refuse to ever say no, how do we keep the data from turning into garbage?"

Dynamo trades strong consistency for always-on availability. It never rejects a write due to node failure, and instead pushes the work of resolving conflicting versions to read time.

Spreading data around the ring: consistent hashing

The first problem in any distributed key-value store is simple to state and easy to get wrong: given a key, which machine holds it? A naive answer is hash(key) % number_of_nodes, but that formula falls apart the moment a node joins or leaves, since almost every key now maps to a different machine and you have to reshuffle nearly all your data.

Dynamo instead arranges nodes on a logical ring using consistent hashing. Both keys and nodes are hashed into the same numeric space (imagine a clock face going from 0 to a very large number, then wrapping back to 0). A key belongs to the first node you hit walking clockwise from its position on the ring, called the coordinator. Adding or removing one node only reshuffles the keys between it and its neighbor, not the whole ring.

A key hashes to a position on the ring, walks clockwise to its coordinator (C), and replicates to the next N-1 distinct physical nodes (D, E).

One wrinkle: physical machines are not identical, some have more disk and CPU than others, and a plain ring would give each machine one arbitrarily-sized slice, so a slow machine could get an unlucky, oversized chunk of the keyspace. Dynamo's fix is virtual nodes: each physical machine claims many points on the ring, not just one, proportional to its capacity. This smooths out load, and lets a new machine absorb a fair share of data from many existing peers at once instead of stealing a single huge chunk from one neighbor.

Virtual nodes are the detail everyone forgets and interviewers love to ask about. Without them, consistent hashing alone still leaves you with a lumpy, unfair distribution of keys across heterogeneous hardware.

Replication: N, R, and W

Every key is replicated to N nodes: the coordinator plus the next N-1 distinct physical nodes clockwise on the ring (this list of nodes is called the preference list). A common production setting in the paper is N = 3.

Rather than requiring all N replicas to respond, Dynamo lets each operation specify how many replicas must participate:

  • W: the number of replicas that must acknowledge a write before it is considered successful.

  • R: the number of replicas that must respond to a read before the result is returned to the client.

With N=3 and W=2, a write succeeds as soon as any two replicas acknowledge it. A slow or unreachable third replica does not block the client.

The classic quorum condition R+W>NR + W > N guarantees that every read overlaps with the most recent write on at least one replica, giving you a "usually fresh" read without needing all replicas online. Set W and R lower than that and you favor latency and availability over freshness. Dynamo lets each application tune this trade-off per use case: the shopping cart favors availability, some other internal services favor consistency.

When even a healthy preference list is not enough: sloppy quorum

Strict quorum still has a weakness: if a required replica is temporarily down, the operation should not just fail outright. Dynamo uses what it calls a sloppy quorum: instead of insisting on exactly the N nodes in the preference list, it accepts writes from the first N healthy nodes it can reach while walking the ring, even if that means temporarily using a node outside the "proper" preference list.

That temporary stand-in node stores the replica along with a hint pointing at the node it was meant for. Once the original node recovers, the stand-in forwards ("hands off") the data back to it and deletes its local copy. This is hinted handoff, and it is the mechanism that lets Dynamo absorb a full node outage without ever blocking a write.

The cost of sloppy quorum is real: it is possible for a client to write successfully, then read from a different set of replicas and not see that write yet. Dynamo is deliberately, explicitly eventually consistent, not linearizable.

Living with conflicts: vector clocks

If two different coordinators can both accept a write for the same key during a network partition (because sloppy quorum allows writes to proceed almost anywhere), you inevitably end up with two different versions of the same object. Dynamo does not pick a winner automatically using a timestamp, because clocks across machines are not reliable enough to be a source of truth for something as important as "which shopping cart update actually happened first."

Instead, every object carries a vector clock: a small list of (node, counter) pairs recording which nodes have modified this object and how many times. Comparing two vector clocks tells you one of three things: one version is strictly newer than the other (safe to discard the old one), they are identical, or they are siblings: genuinely divergent versions that both need to be kept.

Two devices independently modify the same cart while partitioned from each other. Neither vector clock dominates the other, so both versions are kept as siblings until read time.

When siblings exist, Dynamo returns all of them to the client on the next read and lets the application reconcile them. For a shopping cart, reconciliation is easy: union the two carts together, you cannot really lose an "add to cart" action by merging it in. This is called semantic reconciliation, and it is only tractable because the application logic understood the merge, not because the database magically knew the right answer.

Keeping replicas honest: Merkle trees and gossip

Two more mechanisms round out the design. First, replicas can silently drift apart over time (a hinted handoff might get lost, a node might miss a write). Dynamo runs an anti-entropy protocol using Merkle trees, hash trees where each leaf hashes a small range of keys and each parent hashes its children. Two replicas can compare just the root hash first, and only recurse into branches that differ, finding divergent keys without transferring or even reading the entire dataset.

Two replicas compare hash trees top-down. A subtree whose hash matches is provably identical and gets skipped entirely; only the branch that actually differs is walked down to the individual key range that needs to be synced.

Second, Dynamo has no master node tracking cluster membership. Instead, nodes use a gossip-based protocol: each node periodically exchanges membership and node-liveness information with a few random peers, and this information spreads through the cluster the way a rumor spreads through a room. This keeps the system fully decentralized and avoids introducing the very kind of single point of failure Dynamo was built to eliminate.

Why this paper still matters

Dynamo itself was never released outside Amazon, but the paper's ideas escaped anyway. Apache Cassandra and Riak are both explicitly "Dynamo-style" databases, and Voldemort at LinkedIn was a near-direct implementation of the paper. Consistent hashing now shows up anywhere you need to shard data or route requests: CDNs, load balancers, distributed caches like memcached.

More than any specific mechanism, Dynamo popularized a mindset: availability and consistency are a dial, not a switch, and the right setting depends entirely on what you are building. That framing is why, more than fifteen years later, "sloppy quorum," "hinted handoff," and "vector clock" are still exactly the phrases a system design interviewer expects to hear when the question is "how would you design a highly available key-value store?"

Key takeaways: consistent hashing plus virtual nodes for balanced partitioning, sloppy quorum plus hinted handoff for uninterrupted writes, vector clocks plus semantic reconciliation for conflict resolution without a central authority, and Merkle trees plus gossip for keeping a leaderless cluster in sync.

Found this breakdown useful?

Share it with someone else wrestling with this paper.

Discussion0

Join the Discussion

Sign in to leave comments, reply to others, or like insights.

Sign In to ScaleDojo

No comments yet. Be the first to start the thread!

More Papers

Enjoyed this? Get more like it.

New paper breakdowns, levels, and one concept worth knowing, straight to your inbox.

No spam, ever. Unsubscribe in one click.

Enjoyed this content?

Your support keeps us creating free resources

We put a lot of hours into researching and writing these guides. If it helped you, consider buying us a coffee. Every bit goes toward keeping ScaleDojo's content free and growing.

$

One-time payment via Stripe. ScaleDojo account required.