Tier 4 · Case Studies

Case Study — Dynamo & DynamoDB

How one shopping-cart requirement produced a technique catalogue, and one idea that did not survive

⏱ 17 min case-studykey-valueavailability

One business requirement, and everything follows

Dynamo (SOSP 2007) is the rare architecture you can derive from a single sentence about money. The paper states that the shopping cart requires that an "Add to Cart" operation can never be forgotten or rejected. A refused write is a customer who does not buy the thing. Beside it sat a target measured at the tail rather than the mean: a representative internal SLA in the paper is a response within 300 ms for 99.9% of requests at a peak load of 500 requests per second.

The rest is forced:

  1. Availability beats consistency, permanently — the AP corner of CAP, with no runtime flag to flip.
  2. A single leader per key blocks writes when that leader is unreachable, so there is no leader. Any replica in the preference list accepts writes.
  3. A strict quorum blocks writes when the key's home nodes are partitioned away, so the quorum gets to be sloppy.
  4. Concurrent writes to different replicas therefore become normal traffic, not an anomaly.
  5. Something must detect them without trusting wall clocks: vector clocks.
  6. Nothing in a key-value store knows how to merge two carts, so the client resolves.

Each step is compelled by the one above it. That chain is the transferable part.

The technique catalogue

Technique Problem it solves What it costs
Consistent hashing on a ring, with virtual nodes Partitioning and incremental scalability: adding a node moves ~K/N keys; vnodes fix clumping and let bigger machines take more positions Ring state on every node; nothing for a single hot key
Sloppy quorum plus hinted handoff Write availability during partitions: accept on the first N reachable healthy nodes, store a hint for the rightful home Voids R + W > N — a read of the home replicas can miss the write
Vector clocks Detecting genuinely concurrent versions instead of silently discarding one Size grows with coordinating nodes; Dynamo truncates at a threshold (the paper says 10 pairs), after which descendant relationships can be inexact
Merkle tree per key range Anti-entropy: find the few differing keys without shipping the dataset Trees must be rebuilt when ranges move on membership change
Gossip membership with seed nodes Decentralised membership and failure detection, no coordinator to lose Eventually consistent view of the ring; seeds exist to prevent logical partitions

Three of these have their own lessons worth re-reading together: the ring and virtual nodes in partitioning, sloppy quorums and Merkle trees in quorums, and why vector clocks rather than timestamps in clocks. The paper reports (N, R, W) = (3, 2, 2) as the common configuration — the same balanced default the quorum lesson lands on.

The famous consequence

When two writes are concurrent, Dynamo cannot order them, so it keeps both. A later read returns siblings: multiple versions, handed to the caller. The store refuses to guess.

For the cart, the application's merge is a union of item sets. That makes add to cart unloseable, which was the whole requirement. It also means a removal recorded on one branch loses to the item's presence on the other. The paper is direct: an add-to-cart operation is never lost, however deleted items can resurface.

Read that as an engineering decision, not a defect. Amazon weighed a resurrected item (customer removes it again, mildly annoyed) against a refused write (abandoned purchase) and chose. The paper also quantifies the rarity: profiling the cart service for 24 hours, 99.94% of requests saw exactly one version, and the remainder saw two, three or four.

What DynamoDB the product actually is

DynamoDB launched in 2012 and has its own paper (USENIX ATC 2022). It is not the 2007 design with a control plane bolted on. It is a different system:

Why the change? Client-side resolution exported a distributed-systems problem to every application team that touched the store. A correct merge must be idempotent, commutative and associative, and when it is wrong it is wrong silently. Very few product teams should be writing one.

The partition key decides your throughput

Capacity in DynamoDB is allocated per partition, not per table. A single partition tops out around 3,000 read capacity units, 1,000 write capacity units, and 10 GB. Provision 100,000 WCU on the table and one partition key still cannot absorb more than its partition's share.

So a low-cardinality or skewed partition key — status = ACTIVE, today's date, a celebrity account — concentrates load on one partition. You get throttling while table utilisation sits in single digits, which reads as a bizarre bug until you know the model. Adaptive capacity shifts spare capacity toward hot partitions and can isolate a frequently accessed item, but it cannot lift the per-partition ceiling.

What generalised, and what did not

The catalogue generalised completely. Cassandra took the ring, virtual nodes, tunable quorums, Merkle-tree repair and gossip more or less wholesale; ScyllaDB reimplemented that model in C++; Riak was close to a literal implementation, siblings included; and pieces recur wherever multi-region systems need membership without a coordinator.

The conflict model did not. Cassandra chose last-write-wins on timestamps rather than expose siblings — cheaper for developers, and lossy exactly as the clocks lesson warns. Riak kept siblings but added CRDT data types in 2.0 so the database could merge counters, sets and maps without an application-supplied function. DynamoDB removed the problem with a leader. Three escapes from one conclusion: pushing conflict resolution onto application developers did not survive contact with application developers.

What to take away

Check yourself

  1. In the 2007 Dynamo paper, why could an item a customer deleted reappear in their shopping cart?

  2. Which statement describes DynamoDB the product rather than the Dynamo paper?

  3. A DynamoDB table provisioned at 40,000 WCU is throttling writes while overall utilisation stays near 5%. Most likely cause?

  4. What does a sloppy quorum with hinted handoff buy, and what does it give up?