Distributed key-value store
Design a distributed key-value store. Get and put by key, data larger than one machine, survives machines failing, and configurable durability. You are building the database, not choosing one.
Where’s the slack?
Reads: milliseconds. Writes: milliseconds. Repair and rebalancing: hours.The slack here is not in the request path at all: a caller is waiting on every get and every put. All the slack lives in the background work, and the design succeeds by moving as much as possible into it.
Gets and puts have no slack. This store is a dependency of other systems, so its p99 is inside their p99, and being slow makes it useless. That rules out anything requiring wide coordination on the request path.
Everything else has a lot of slack. Repairing a replica that has fallen behind, moving partitions when a machine joins, compacting on-disk files, taking backups, rebuilding a failed node: all of it can take hours, run at low priority, and be interrupted and resumed. The hard rule is that none of it may block a get.
The one place you get to sell slack is durability. "Confirmed when one node has it" is fast and can lose data. "Confirmed when a majority has it" is slower on every write, forever. That is not a failure-time decision. It is a latency cost paid on every write, the "else" half of PACELC, so the design lets the caller choose per operation.
So: Background work is aggressively deprioritised and never on the read path. Durability is a per-request knob rather than a system-wide property, so a session cache and a user record can use the same store with different promises.
Work it through
Five stages, gated. You write your answer for each stage before its model answer unlocks. That is the core of the method.
Reference material for this problem. The diagrams below are here to check your own against once you have drawn it, not to read first.
The lifecycle
The numbers
So the hard part is membership and recovery. Each node is barely working; agreeing who owns what while machines come and go, and staying safe for 18 hours at reduced replication, is the design.
The architecture
The decision this turns on
- —Trivial to implement, and every read returns one value.
- —Depends on clocks agreeing, and they never agree exactly.
- —The write that happened second can carry the earlier stamp and be discarded.
- —The loss is silent: no error, no log line, nothing to alert on.
- —Fine for disposable values like a session blob or a presence flag.
- —Tells you whether one version is newer, or whether they are concurrent.
- —Concurrent versions are handed to the application, which is the only layer that knows how to merge them.
- —No silent loss: a conflict becomes a decision somebody makes.
- —Vectors grow with the number of writers and need pruning.
- —Clients get a harder API: a read can return more than one value.
Follow-ups you should expect
Many interviews are decided in the follow-ups, not the first diagram.
Same shape, other products
You are not using a database. You are being asked to design one.
The vocabulary flips from "which store do I pick" to replication, quorums, partition assignment and durability. This is the group where every Tier 2 concept is the answer rather than the context.
Others with this shape: Distributed key-value store · Distributed cache · Object storage · Message broker
How it is really built
Write your own answer first. Then read how teams who run this at scale describe it. Their constraints were real, and the write-ups often say what their choices cost.
- Amazon Dynamo paper ↗Consistent hashing, vector clocks and quorums in the paper that popularised them.
- Please stop calling databases CP or AP ↗Read after the paper, as a corrective to the classification.