R
Reqflow
Rebuild

Requirements & API: Dynamo-Style KV Store

The first move in any interview: define requirements and sketch the API before drawing a single box.

Functional requirements

  • GET and PUT a key-value pair with sub-millisecond latency.
  • Remain available for reads and writes even when nodes are unreachable.
  • Detect and surface conflicting versions of the same key written during a partition.
  • Recover consistency automatically when partitioned nodes reconnect (anti-entropy).

Non-functional requirements

  • Always available: no single node failure should make the store unavailable.
  • Tunable consistency: clients choose N, R, W for their latency/consistency trade-off.
  • Eventual consistency: divergent replicas converge within seconds of a partition healing.
  • Horizontal scalability: add nodes to the ring to increase capacity with minimal rebalancing.

API contract

put(key, value, context?) → ok
Context carries the vector clock from a prior get. Required for conditional writes to detect conflicts.
get(key) → { value, context } | { siblings: [value], context }
Returns siblings when conflicting versions exist and the application must resolve them.
delete(key, context) → ok
Tombstone-based: delete inserts a tombstone that propagates and eventually expires.

About Dynamo-Style KV Store

Amazon's 2007 Dynamo paper is one of the most influential engineering documents ever published. It described a key-value store built entirely around availability: a system that would keep accepting reads and writes even when nodes crashed, partitions occurred, or entire data centers went dark. The techniques it introduced (consistent hashing, vector clocks, sloppy quorums, and hinted handoff) are now the foundation of DynamoDB, Cassandra, Riak, and every AP distributed database.

The core design choice is leaderless replication. Unlike Kafka or Raft, there's no designated leader for a key. Any node in the ring can accept a write for any key, and the write propagates to N replica nodes. To read, a client asks R nodes for their version and takes the most recent. As long as W + R > N, at least one node that participated in the last write will be in the read quorum. That's quorum-based consistency.

The interesting part is what happens during a partition. A node that can't reach its designated replicas accepts the write anyway, storing it locally as a 'hinted handoff' and forwarding it when the replica recovers. This is sloppy quorum: availability is preserved at the cost of consistency. Multiple nodes may accept concurrent writes to the same key, creating conflicting versions. Vector clocks track causal history so that siblings (conflicting versions) can be detected and resolved, either automatically (last-write-wins) or by the application.

Understanding Dynamo is understanding the design space of AP distributed databases: how to stay available, how to detect conflicts, and how to recover from them.