System design interview guide
DynamoDB System Design Interview: Designing a Distributed Key-Value Store That Serves Millions of Requests per Second at Single-Digit-Millisecond Latency
DynamoDB is built to return a point read or write in single-digit milliseconds no matter how large the table gets, and large tables can sustain millions of requests per second by spreading data and traffic across thousands of partitions on thousands of storage nodes. The trick is not any one clever algorithm. It is that the whole system is organized so that adding hardware adds throughput almost linearly, and so that no single request ever has to touch more than a handful of nodes. The interesting design questions are all about what you give up to get that: rich queries, cross-key transactions, and, by default, read-your-write freshness. Any specific throughput or latency number here is an industry-typical range or an illustration, not a measured AWS-internal figure.
DynamoDB is a managed distributed key-value and document store descended from the 2007 Amazon Dynamo paper. You address every item by a primary key, and the system hashes that key to decide which partition, and therefore which set of storage nodes, owns the item. Data is partitioned by consistent hashing and replicated to a small number of nodes (typically three) across separate availability zones, so a single node or even a whole zone can fail without losing data or availability. The original Dynamo was fully leaderless and used vector clocks with application-side conflict resolution, but production DynamoDB moved to a per-partition leader with quorum-style replication and a write-ahead log, which is simpler for developers to reason about. Reads come in two flavors: eventually consistent (cheap, may be slightly stale) and strongly consistent (routed to the leader replica). The hard design themes are all trade-offs: how you pick a partition key so load spreads evenly instead of creating a hot partition, how the system reshares and moves data online as tables grow, how secondary indexes are kept up to date asynchronously, and how global tables give you multi-region writes at the cost of last-writer-wins conflict resolution. DynamoDB leans toward availability and predictable latency over rich query power and strong global consistency.
Where it shows up
Asked at Amazon first and foremost, since Dynamo is their own paper and DynamoDB is their flagship NoSQL service, but the underlying design shows up everywhere: Google, Meta, Uber, Netflix, and any company that runs Cassandra, ScyllaDB, or Riak, all of which are direct descendants of the Dynamo paper. It appears both as a pure infrastructure question (design a distributed key-value store) and as a building block inside larger designs like shopping carts, session stores, feature stores, and metadata services.
Why this question is asked
Interviewers reach for this problem because it cannot be answered by naming a product. You have to build up from first principles: how do you spread data across machines so it stays balanced (consistent hashing), how do you keep it available when machines die (replication and quorums), what happens when two replicas disagree (conflict resolution), and how do you keep single-key operations fast while the table grows without bound (partitioning and online resharding). It also rewards intellectual honesty, because the correct answers force you to admit real limits: the default read is eventually consistent, a bad partition key creates a hot partition that no amount of provisioned capacity fixes cleanly, and cross-partition transactions are expensive and constrained. It is one of the few questions where the CAP theorem stops being a slogan and becomes a concrete set of decisions you have to defend.
Requirements
Always clarify these in the first 5 minutes of the interview. Do not start drawing boxes until both lists are agreed.
Functional requirements
- Store and retrieve an item by its primary key (get and put) with single-digit-millisecond latency at any table size
- Support a composite primary key of a partition key plus a sort key, enabling ranged queries within a single partition key (for example, all orders for a customer between two dates)
- Support conditional writes (put, update, or delete only if a condition holds), which gives optimistic concurrency and idempotency without a separate lock service
- Support atomic counters and item-level atomic updates on individual attributes
- Provide secondary indexes: global secondary indexes (GSI) for querying on non-key attributes, and local secondary indexes (LSI) for alternate sort keys within a partition
- Support automatic item expiry through a per-item TTL attribute that the system reaps in the background
- Emit an ordered change stream of item-level mutations so downstream systems (indexes, replicas, consumers) can react
Non-functional requirements
- Single-digit-millisecond latency for point reads and writes that stays flat as the table grows from megabytes to petabytes
- High availability, tolerating single-node and single-availability-zone failures with no loss of durability or write availability
- Horizontal scalability: throughput and storage grow by adding partitions and nodes, ideally linearly, with no manual resharding
- Durability of acknowledged writes through replication across multiple availability zones plus a durable write-ahead log
- Tunable read consistency per request: cheap eventually consistent reads by default, strongly consistent reads on demand
- Predictable, isolated performance: one customer or one partition load spike should not degrade others (multi-tenant admission control)
- Optional multi-region operation (global tables) for low-latency local reads and writes and regional disaster tolerance
Back-of-envelope scale estimates
Show your math. Pulling numbers from thin air signals you have not thought about the load.
Point-read/write latency
single-digit ms (typical)
An eventually consistent read served from an in-memory or local-SSD replica, or a write acknowledged after a quorum of local-zone replicas, is dominated by intra-datacenter network hops and a B-tree or LSM lookup. This is a design target of the service, not a per-request guarantee, so treat it as typical.
Item size limit
~400 KB per item
A key-value store caps item size so a single item cannot dominate a partition or a network buffer. DynamoDB's public documented limit is 400 KB including attribute names and values. Large blobs are expected to live in object storage with only a pointer in the item.
Per-partition throughput ceiling
~3000 reads/sec and ~1000 writes/sec per partition
Each physical partition is one unit of concurrency backed by a bounded slice of a node CPU, memory, and disk. Published DynamoDB guidance describes a per-partition ceiling on the order of 3000 read units and 1000 write units per second. A table exceeds this only by having many partitions, which is why key distribution matters.
Replication factor
3 replicas across 3 availability zones
Three copies in three failure domains is the standard durability-versus-cost point: it survives losing any one copy or one whole zone while keeping a majority quorum of two available. Derived from the general quorum model, matching DynamoDB's documented multi-AZ replication.
Partitions per large table
thousands (estimate)
If one partition holds on the order of 10 GB and caps at a few thousand ops/sec, then a petabyte-scale, million-op/sec table must be spread across many thousands of partitions. Derived by dividing total size and total throughput by per-partition limits.
Global table replication lag
typically sub-second (estimate)
Cross-region replication in global tables is asynchronous, so a write in one region propagates to others after a network and processing delay. Sub-second is the commonly cited typical figure, but it is a range that widens with distance and load, so it is an estimate.
High-level architecture
A client issues an operation against a table, addressing an item by its primary key, and speaks to the service through a stateless request layer. The first job of that layer is routing: it takes the partition key, hashes it, and looks up which partition owns that hash range in the partition metadata. That lookup tells it which storage nodes hold the replicas for the item. The request router is not the source of truth for data; it is a thin, horizontally scalable tier whose only job is to authenticate the caller, check that the request stays within its allocated throughput (admission control), find the right partition, and forward the operation. Because routing is a pure function of the key plus a metadata map, you can run as many request routers as you need and any of them can serve any request. Data is partitioned by consistent hashing. The keyspace is a ring, each key hashes to a point on the ring, and each partition owns a contiguous arc of that ring. When a partition gets too big or too hot, it splits, and the metadata map is updated so future requests route to the new owners. Each partition is replicated, typically three ways, across separate availability zones so that the failure of a disk, a machine, or an entire zone never takes the data offline. Production DynamoDB designates one replica per partition as the leader. Writes go to the leader, which appends to a write-ahead log and replicates to the other members; a write is acknowledged once a quorum has durably accepted it. Strongly consistent reads are served by the leader, which knows it has the latest committed value, while eventually consistent reads can be served by any replica and may lag slightly. On each storage node, an item lives in a local storage engine, commonly a log-structured merge tree (LSM) or a B-tree, that turns random-looking key access into efficient sequential disk writes and indexed reads. Writes first hit a durable log and an in-memory structure, then get flushed and compacted in the background. This is what lets the node absorb a high write rate while still answering point reads quickly. Secondary indexes are maintained as their own partitioned structures that are updated asynchronously from the base table change stream, which is why a global secondary index is eventually consistent with the item you just wrote. Underneath all of this is a control plane that the data path does not sit on directly. It tracks node membership and health, decides when a partition should split or move, drives the actual data movement while the partition stays online, and updates the metadata map that the request routers consult. Membership and failure information propagate through a gossip-style mechanism in the original Dynamo design and through a more centralized, quorum-backed metadata service in production DynamoDB, but the principle is the same: the fast path stays simple and local, and the slow, global coordination is pushed off to a separate system that is not in the critical path of a get or a put.
In a real interview, sketch this on the whiteboard before diving into any single box.
Core components
Walk through each service. The interviewer wants to hear what each one owns, not just the names.
Request router / coordinator
A stateless front-end tier that receives every operation, authenticates it, enforces the caller throughput allocation, hashes the partition key to find the owning partition, and forwards the request to the right storage nodes. For a write it targets the partition leader; for an eventually consistent read it can target any replica. Because it holds no durable state, it scales out freely and any router can handle any key.
Partition metadata / consistent-hashing map
The authoritative mapping from hash ranges on the ring to the partitions and storage nodes that own them. Routers cache this map and consult it on every request. When partitions split or move, the map is updated and the change propagates so routers stop sending traffic to stale owners. This is the component that turns a key into these three specific nodes.
Partition and its replicas
A partition is the unit of data ownership, scaling, and replication. It owns a slice of the ring and is copied to a small replica group (typically three) placed in different availability zones. The partition is what splits when data or traffic grows, and the replica group is what keeps it available and durable when hardware fails.
Storage node with local engine (LSM or B-tree)
The machine that physically stores item data on SSD. It runs a local storage engine, commonly a log-structured merge tree, that buffers writes in memory, appends them to a log, and flushes sorted runs to disk that are later compacted. This gives high write throughput and fast indexed point and range reads within a partition.
Replication and quorum layer
The mechanism that keeps replicas consistent. Production DynamoDB uses a per-partition leader that sequences writes, appends them to a write-ahead log, and replicates to peers, acknowledging once a durable quorum accepts. The original Dynamo was leaderless and used sloppy quorums with N, W, and R tunables. Either way, the write and read paths only need a majority of the replica group to make progress, so one slow or dead replica does not block the operation.
Secondary index builder
A subsystem that maintains global and local secondary indexes as separate partitioned tables. It consumes the base table ordered change stream and applies each mutation to the relevant index partition. Because this happens asynchronously for a GSI, the index is eventually consistent and has its own throughput and its own partition key.
Admission control and throttling
The multi-tenant guardrail. Every table (and effectively every partition) has an allowed request rate, either provisioned or on-demand. When traffic exceeds what a partition can serve, requests are throttled with a retriable error, and a token-bucket style mechanism lets short bursts through while smoothing sustained overload. This is what keeps one hot key or noisy tenant from starving everyone sharing the fleet.
Membership and failure detection
The service that knows which nodes are alive and which own what. In the Dynamo paper this is gossip-based, with nodes exchanging membership and partition information peer to peer. In production DynamoDB it is backed by a more centralized, consensus-backed control service. Its output feeds the metadata map and triggers replacement of failed replicas.
Auto-scaling and repartitioning controller
The control-plane logic that watches partition size and traffic and decides to split a partition (when it grows past a size or throughput threshold) or to move a partition to a less loaded node. It performs this online: it copies the data to new owners, catches up from the log, then atomically flips ownership in the metadata map so clients never see downtime.
Data model
Pick the right store per table. Justify each choice with the access pattern, not by reflex.
base item tablepartition_key (hash key)sort_key (range key, optional)attributes (schemaless map)The primary store. The partition key decides which partition and replica set an item lives on; the optional sort key orders items that share a partition key so you can range-scan within it. Everything other than the key attributes is schemaless, so different items in the same table can have different fields.
global secondary index (GSI)gsi_partition_keygsi_sort_keyprojected_attributesA separate partitioned copy of selected attributes, keyed on a different attribute than the base table, so you can query by something other than the primary key. It is partitioned and replicated independently and updated asynchronously from the change stream, so it is eventually consistent with the base item and has its own throughput budget.
local secondary index (LSI)partition_key (same as base)lsi_sort_keyprojected_attributesShares the base table partition key but offers an alternate sort key, so it lives on the same partition as the item and can be kept strongly consistent. Because it is co-located, it is constrained by that partition size limits and must be defined at table creation.
partition metadata / ring maphash_rangepartition_idreplica_node_idsleader_node_idversionThe routing source of truth. Maps each arc of the hash ring to a partition and the nodes holding its replicas, including which one is the current leader. A monotonic version lets routers detect and discard stale cached maps after a split or failover.
write-ahead log / replication logpartition_idsequence_numberoperationitem_payloadThe per-partition ordered log of mutations. The leader appends here before acknowledging, replicas and secondary indexes consume it in order, and a recovering or newly added replica replays it to catch up. It is both the durability mechanism and the source of the customer-facing change stream.
Deep dives
These are the conversations the interviewer is steering you toward. Practice each one until you can talk through it without notes.
Consistent hashing and virtual nodes
The core problem in a key-value store is deciding which machine owns which key, in a way that stays balanced and does not reshuffle everything when you add or remove a machine. Naive hashing (key mod N) fails the moment N changes, because almost every key remaps. Consistent hashing solves this by placing both keys and nodes on a ring: a key is owned by the first node clockwise from its hash. Adding or removing a node only reassigns the keys in the arc next to it, so roughly 1/N of the data moves instead of nearly all of it. The catch in the basic scheme is that a few nodes can end up owning large arcs by chance, creating imbalance, and a failed node dumps its whole load onto its single successor. The fix, introduced in the Dynamo paper, is virtual nodes: each physical machine is represented by many points on the ring. This smooths the distribution, spreads a failed machine load across many peers instead of one, and lets a more powerful machine carry more virtual nodes and therefore more data. DynamoDB partitioning is the managed evolution of this idea, where partitions are the owned arcs and the service moves them around for you.
Partitioning, hot partitions, and adaptive capacity
Every item is assigned to a partition by hashing its partition key, and each partition has a hard ceiling on throughput because it is backed by a bounded slice of one node resources. This makes partition key choice the single most important design decision. If your key has high cardinality and even access (a user id, a random uuid), traffic spreads across many partitions and you get the full aggregate throughput of the table. If your key is low cardinality or skewed (a status field, today date, a single celebrity account), a disproportionate share of requests lands on one partition, and that partition throttles even though the table as a whole is far under its limit. That is a hot partition. The classic mitigations are write sharding (append a suffix or prefix to spread a hot key across several synthetic keys) and choosing a naturally high-cardinality key. On the service side, DynamoDB added adaptive capacity, which lets a hot partition temporarily borrow unused throughput from the table other partitions and can isolate a persistently hot item by splitting the partition around it. Adaptive capacity softens the problem but does not eliminate it: a single key that is hotter than one partition can serve is still a physical limit, because one item cannot be split across machines.
Replication and quorums (N, W, R) with eventual versus strong reads
Durability and availability come from keeping N copies of each partition, typically three across three availability zones. The Dynamo paper frames consistency as a quorum: a write must be acknowledged by W replicas and a read must consult R replicas, and if W + R > N you are guaranteed that any read overlaps with the latest write and therefore sees it. Tuning these lets you trade latency for consistency: W=1 is fast but risky, W=N is durable but slow, and a common balance is N=3, W=2, R=2. Dynamo also used sloppy quorums and hinted handoff, meaning if a target replica is temporarily unreachable, a write is accepted by a healthy stand-in node that holds it as a hint and forwards it later, which keeps writes available during partitions at the cost of possible temporary inconsistency. Production DynamoDB simplifies the developer view with a leader per partition: an eventually consistent read (the default, and cheaper) can be served by any replica and might be slightly stale, while a strongly consistent read is routed to the leader, which holds the latest committed write. The interview point is that the default read is eventually consistent on purpose, because forcing every read through the leader would cost latency and availability that most workloads do not need.
Conflict resolution, last-writer-wins versus vector clocks
In a leaderless system where two clients can write the same key at nearly the same time to different replicas, the replicas can end up with divergent versions, and something has to reconcile them. The original Dynamo attached a vector clock to each version, a set of (node, counter) pairs that records the causal history of the update. When two versions are causally ordered, the newer one wins automatically; when they are concurrent (neither descends from the other), Dynamo cannot decide and returns both versions to the application, which must merge them. The canonical example is the Amazon shopping cart, where merging two concurrent carts by union is safe and better than dropping either. Vector clocks preserve correctness but push complexity onto the developer and can grow large. The simpler alternative is last-writer-wins (LWW): attach a timestamp and keep the one with the higher value, silently discarding the other. LWW is easy and stateless but can lose writes when clocks disagree or two updates race. Production DynamoDB avoids exposing this to developers on the base table by funneling writes through a per-partition leader that orders them, so single-region writes do not produce sibling versions. Where it does surface is global tables across regions, which resolve cross-region conflicts with last-writer-wins based on a timestamp, and that is exactly why multi-region writes carry a real last-writer-silently-wins caveat.
The storage engine, log-structured merge trees
Underneath a partition is a local storage engine, and the workload it faces (high write rate, point and short-range reads, data far larger than RAM) is what LSM trees were built for. Instead of updating data in place on disk, which turns writes into slow random I/O, an LSM buffers incoming writes in an in-memory table and appends them to a durable log for crash recovery. When the in-memory table fills, it is flushed to disk as an immutable, sorted file. Reads check the in-memory table first, then the on-disk files, using per-file indexes and Bloom filters to skip files that cannot contain the key. Over time the small files are merged and rewritten into larger sorted files in a background process called compaction, which is where deleted and overwritten records are finally discarded. The trade is that writes become cheap and sequential while reads may have to consult several files and compaction consumes background I/O. B-trees are the alternative, favoring read-optimized in-place updates at the cost of more expensive random writes. A key-value store that must ingest writes at scale generally leans LSM, which is what Cassandra and other Dynamo descendants do.
Secondary indexes, GSI async propagation and LSI
A pure key-value store can only find an item by its primary key, which is too limiting, so secondary indexes let you query by other attributes. There are two kinds and they behave very differently. A local secondary index shares the base table partition key but provides an alternate sort key, so it lives on the same partition as the items it indexes. Because it is co-located with the data, it can be updated in the same write and kept strongly consistent, but it inherits that partition size limits and must be declared when the table is created. A global secondary index uses a completely different partition key, so its entries can live on entirely different partitions and nodes than the base items. That means it cannot be updated synchronously without a distributed transaction on every write, which would kill write latency. Instead the base table change stream is consumed asynchronously and applied to the GSI, so the index is eventually consistent: right after you write an item, a query against a GSI might not see it yet, usually for a very short window. A GSI also has its own throughput, and if the GSI is under-provisioned, writes to the base table can be throttled because the index cannot keep up. Understanding this asynchrony is a frequent interview discriminator.
The write path and durability
Following a single put makes the durability story concrete. The request router hashes the partition key, finds the leader replica, and forwards the write. The leader assigns it a sequence number and appends it to the partition write-ahead log, then replicates the log entry to the other replicas in the group. Once a quorum (for example two of three) has durably persisted the entry, the leader acknowledges the write to the client. At that point the write survives the loss of any single replica, including the leader, because a majority already holds it and a newly elected leader will have it. The in-memory state and the LSM flush happen after the log append, so the log is the real durability boundary, not the flushed data file. Conditional writes add a check on top: the leader evaluates the condition (attribute does not exist, version equals expected) against the current committed value before appending, which gives you optimistic concurrency and idempotent retries without any external lock. The reason this is fast despite crossing machines is that a quorum only needs a majority, so the slowest replica in the group never blocks the acknowledgment.
Throttling, partition throughput limits, and adaptive capacity
Because DynamoDB is a shared, multi-tenant fleet, it cannot let any table or any partition consume unbounded resources, so throughput is metered. Under provisioned capacity you declare how many read and write units per second you want; under on-demand it scales to your traffic and bills per request. Either way the meter is enforced per partition, and each partition has a physical ceiling (illustratively a few thousand reads and about a thousand writes per second). Exceed the partition share and requests are throttled with a retriable error, and the SDK backs off and retries. The subtlety that trips people up is that provisioned capacity is divided across partitions, so a table provisioned for 10000 writes per second spread over ten partitions gives about 1000 per partition, and a hot key hitting one partition throttles at 1000 even though nine-tenths of the table capacity sits idle. Adaptive capacity and burst credits mitigate this by letting a hot partition borrow idle capacity from siblings and absorb short spikes, and by isolating persistently hot items into their own partitions. The design lesson is that provisioned throughput is a per-partition budget, not a magic global pool, and even distribution of the partition key is what lets you actually use the capacity you pay for.
Multi-region global tables and their consistency implications
A single-region table survives node and zone failures but not the loss of a whole region, and it cannot give a user on another continent a local, low-latency write. Global tables solve both by replicating a table across multiple regions with active-active, multi-primary writes: every region accepts local reads and writes, and each region asynchronously ships its changes to the others, typically within a second. The benefit is local latency everywhere and regional disaster tolerance. The cost is consistency. Because writes are accepted independently in each region and replicated asynchronously, two regions can update the same item concurrently, and the system resolves the conflict with last-writer-wins based on a timestamp: the write with the later timestamp survives and the other is silently discarded. There is no cross-region strong consistency and no read-your-write guarantee across regions, so an application built on global tables must tolerate a brief window where regions disagree and must accept that a losing concurrent write vanishes. For workloads where that is unacceptable (financial ledgers, inventory that cannot oversell), you either keep writes pinned to one region or add application-level reconciliation.
Trade-offs to discuss
Every senior interviewer expects you to surface at least 3 of these. Pick the decisions, state the alternatives, and justify your choice.
Leaderless quorum (original Dynamo) versus single-leader per partition (production DynamoDB)
A fully leaderless design with sloppy quorums maximizes write availability during partitions, since any healthy replica can accept a write, but it produces concurrent sibling versions that the application must reconcile. A per-partition leader sequences writes so single-region conflicts never arise and strong reads are trivial, at the cost of a failover step when a leader dies. DynamoDB chose the leader model because the developer simplicity was worth more than the last increment of write availability.
Eventually consistent reads as the default versus strongly consistent
Eventual reads can be served by any replica, so they are cheaper, lower latency, and stay available even when the leader is briefly unreachable, but they can return slightly stale data. Strong reads must go to the leader, costing latency, availability, and roughly double the read capacity. Making eventual the default matches the reality that most reads (a profile, a product, a feed) tolerate a few milliseconds of staleness, and lets teams pay for strong consistency only where correctness demands it.
Last-writer-wins versus vector clocks for conflict resolution
Vector clocks preserve every concurrent write and never silently lose data, but they force the application to merge siblings and add per-item metadata that can grow. Last-writer-wins is trivial to implement and keeps the API simple, but it can silently drop a concurrent write and depends on clock quality. DynamoDB keeps LWW out of the single-region path via the leader and only accepts its downside where it is unavoidable, in cross-region global tables.
Single-table / denormalized design versus normalized multi-table design
DynamoDB has no joins and charges per partition access, so idiomatic design packs related entities under shared partition keys in one table, letting a single query fetch an item and its children in one round trip. This is fast and cheap but bakes your access patterns into the key schema, so a new query pattern can require a new index or a migration. A normalized, relational-style layout is more flexible to query but multiplies round trips and cost, which is exactly what the store is built to avoid.
Provisioned capacity versus on-demand capacity
Provisioned capacity is cheaper per request for steady, predictable load and lets you cap spend, but it throttles when traffic exceeds what you reserved and wastes money when idle. On-demand scales instantly to any traffic and bills only for what you use, ideal for spiky or unknown workloads, at a higher per-request price. The choice is a bet on how well you can predict and smooth your traffic.
Bounded item size and no cross-partition transactions versus a richer data model
Capping items at a few hundred kilobytes and constraining transactions to keep them from spanning the whole fleet is what preserves predictable single-digit-millisecond latency and linear scale. The price is that large objects must be offloaded to object storage with only a pointer stored, and workloads needing multi-item atomicity across many partitions must use the limited transaction API or redesign around it. Predictability was chosen over generality.
How DynamoDB (a distributed key-value store) actually does it
The design above tracks two authoritative public sources that bookend the system history. The 2007 SOSP paper Dynamo: Amazon's Highly Available Key-value Store by DeCandia and colleagues introduced the ideas that everything else builds on: consistent hashing with virtual nodes, N/W/R quorums, sloppy quorums with hinted handoff for availability during partitions, vector clocks with application-side reconciliation, gossip-based membership, and an explicit choice of availability over strong consistency for the shopping-cart use case. That paper directly inspired Cassandra, Riak, and Voldemort. Fifteen years later, the 2022 USENIX ATC paper Amazon DynamoDB: A Scalable, Predictably Performant, and Fully Managed NoSQL Database Service documents how the production service diverged from the paper: it emphasizes predictable performance and admission control, describes moving away from pure leaderless replication toward leader-based partitions with a write-ahead log, and explains adaptive capacity and how the service isolates hot partitions and noisy tenants. An honest interview answer distinguishes the two: the paper is the conceptual foundation, but production DynamoDB made deliberate changes (a per-partition leader, managed repartitioning, admission control) precisely because the fully leaderless model pushed too much complexity onto developers. Any claim that DynamoDB is strongly consistent by default, or that a good partition key does not matter, contradicts these sources.
Lessons to study before this interview
If any of these topics are fuzzy, the interviewer will catch it. Each lesson is 15 to 60 minutes with diagrams, code, and a quiz.
Design a Key-Value Store
capstone / capstone
Quorum
advanced / distributed systems core
Vector Clocks
advanced / distributed systems core
CAP Theorem
advanced / distributed systems core
Hash Partitioning
foundation / database fundamentals
Database Sharding
foundation / database fundamentals
SQL vs NoSQL
foundation / core fundamentals
Related system design interview questions
Practice these next. They lean on the same core building blocks as DynamoDB (a distributed key-value store).