3. Partitions and the storage layer
DynamoDB · 3. Partitions and the storage layerYou cannot see partitions. There is no API that lists them, no console page that shows them, and AWS deliberately does not let you manage them. But every throttling incident, every hot-key story and every rule in chapter 8 is a consequence of how they work, so the model is worth building carefully.
The key becomes a machine
Section titled “The key becomes a machine” PutItem(PK = "CUSTOMER#42", …) │ ▼ hash("CUSTOMER#42") ──► a point in the key space │ ▼ the partition owning that point │ ▼ three storage nodes in three AVAILABILITY ZONESThe partition key is hashed, not stored in order. Two consequences run through everything:
✓ keys spread evenly by construction. there is no "last partition" hotspot of the kind an ordered store suffers from (compare CockroachDB ch 3).
✗ you cannot scan partition keys in order. "all customers between A and M" is not a query. the ordering you get is WITHIN a partition, by SORT KEY, and nowhere else.Cassandra made exactly the same choice, for exactly the same reasons, and its ring diagram is a good mental picture for what is happening here behind the API.
Inside a partition
Section titled “Inside a partition” PARTITION (≤ 10 GB) ┌────────────────────────────────────────────┐ │ items sorted by PARTITION KEY hash, then │ │ by SORT KEY within each collection │ │ │ │ B-tree over the sort keys │ │ → equality, range and begins_with are all │ │ ordinary tree operations │ └────────────────────────────────────────────┘So a Query is: hash to the partition (one hop), then a tree descent and a sequential read of a sorted range. Both halves have costs that depend on the result size, never on the table size. That is the whole latency promise from chapter 1, implemented.
Replication and durability
Section titled “Replication and durability” ONE PARTITION = THREE REPLICAS, THREE AZs
┌───────────┐ ┌───────────┐ ┌───────────┐ │ AZ-a │ │ AZ-b │ │ AZ-c │ │ LEADER │──►│ replica │ │ replica │ └───────────┘ └───────────┘ └───────────┘
• a write is acknowledged once the leader and at least one replica have it durably • leader election uses Paxos; failover is seconds and invisible to you • strongly consistent reads go to the LEADER • eventually consistent reads may go to any replica — and are half the price (ch 4, 6)You never see this machinery, and it explains two things you do see: why strongly consistent reads cost twice as much (they must reach the leader), and why eventually consistent reads occasionally return a value a few hundred milliseconds stale.
The throughput ceiling per partition
Section titled “The throughput ceiling per partition”This is the number to memorise, because it is the source of most surprises:
PER PARTITION, MAXIMUM 3,000 read capacity units per second 1,000 write capacity units per second 10 GB of dataA table can do millions of requests per second — across many partitions. One partition key cannot exceed those numbers, however large your table’s provisioned capacity is.
TABLE provisioned 100,000 WCU ALL writes to PK = "GLOBAL#COUNTER"
→ still capped near 1,000 WCU → ThroughputExceededException, while 99% of your provisioned capacity sits unusedThat is the hot partition, and it is the single most common DynamoDB failure (chapter 14). It is a modelling problem, not a capacity problem, and no amount of provisioning fixes it.
Splits
Section titled “Splits”Partitions split automatically, in two circumstances:
SIZE SPLIT the partition passed 10 GB. it splits in half by key hash.
THROUGHPUT SPLIT the partition's traffic exceeds what it can serve. DynamoDB splits it so the load spreads over more machines. A CRITICAL SUBTLETY
A split divides the KEY SPACE. If all the traffic is on ONE partition key, splitting does not help — that key lands entirely on one side of the split, every time, forever.
Splits rescue "many keys, uneven traffic". They cannot rescue "one key, all the traffic".Adaptive capacity
Section titled “Adaptive capacity”Modern DynamoDB does not divide provisioned throughput rigidly by partition count. Adaptive capacity shifts unused throughput toward busier partitions, automatically and continuously.
WITHOUT (old behaviour) 100,000 WCU over 50 partitions = 2,000 each, strictly
WITH ADAPTIVE CAPACITY a busy partition can borrow from idle ones, up to the HARD per-partition ceiling of 1,000 WCU / 3,000 RCUThis removed a whole class of historical complaints, and it is why older blog posts about “capacity dilution” read as obsolete. What it does not do is raise the per-partition ceiling — physics, and the design, still cap a single key.
Designing keys for partitions
Section titled “Designing keys for partitions”The rule that falls out of all of the above:
A GOOD PARTITION KEY HAS
① HIGH CARDINALITY many distinct values ✓ userId, deviceId, tenantId#entityId ✗ status, country, "ORDERS", today's date
② EVEN ACCESS no single value taking a disproportionate share ✗ one celebrity user, one enormous tenant, one hot product on launch day
③ MATCHES THE QUERY you can only Query by an exact partition key, so it must be a value the caller actually hasWhen a naturally hot key is unavoidable, the standard remedy is write sharding:
PK = "PRODUCT#123" → 1 partition, capped
PK = "PRODUCT#123#" + (0..9) → up to 10 partitions reads fan out over 10 keys and mergeChapter 13 works through the trade — ten times the write headroom, ten times the read requests — and chapter 8 covers designing so you need it less often.
Item collections and partitions are not the same thing
Section titled “Item collections and partitions are not the same thing”A subtlety worth getting right, because the words are used loosely.
ITEM COLLECTION all items sharing ONE partition key value. PARTITION a physical storage unit holding MANY item collections whose hashes fall in its range. PARTITION #7 ┌──────────────────────────────────────────────┐ │ CUSTOMER#42 → PROFILE, ORDER#…, ADDRESS#… │ ← one │ CUSTOMER#88 → PROFILE, ORDER#… │ item │ PRODUCT#S1 → META, REVIEW#… │ collection └──────────────────────────────────────────────┘ each CONSEQUENCES • one huge item collection cannot be split across partitions — it is bounded by the partition's 10 GB • a busy NEIGHBOUR can consume capacity you were hoping to use, until adaptive capacity and splits react • with an LSI, an item collection is HARD-CAPPED at 10 GB and writes start failing (ch 7)How big is too big for one partition key?
Section titled “How big is too big for one partition key?” FINE a customer with 10,000 orders a device with a year of daily summaries WATCH a tenant with 5 million items — check the total bytes against 10 GB REDESIGN "ALL_ORDERS" as a partition key a date-only key on a busy day one tenant holding 90% of your dataThe practical rule: a partition key value should identify something whose data is bounded by the nature of the thing, not by the size of your business. A customer’s orders are bounded by that customer’s behaviour. “All orders” is bounded by nothing.
What this means in practice
Section titled “What this means in practice” YOU CANNOT SO INSTEAD see or manage partitions design keys well pin data to a partition use the key prefix scan keys in order model an index (ch 7) exceed 1,000 WCU on one key shard the key fix a hot key with capacity fix the model# what the service will tell you about distributionaws cloudwatch get-metric-statistics \ --namespace AWS/DynamoDB --metric-name ThrottledRequests \ --dimensions Name=TableName,Value=AppData \ --start-time … --end-time … --period 60 --statistics SumCloudWatch Contributor Insights goes further and names the most-accessed keys directly, which is the fastest route from “we are being throttled” to “this key is the problem” (chapter 13).
What to take from this chapter
Section titled “What to take from this chapter”- The partition key is hashed to choose a partition, so distribution is even by construction — and ordering across partition keys does not exist.
- Within a partition, items are sorted by sort key in a B-tree, so
Querycosts scale with the result size, never the table size. - Every partition is replicated to three availability zones, with a leader that serves strongly consistent reads; eventually consistent reads may hit any replica and cost half as much.
- The hard ceiling is 3,000 RCU and 1,000 WCU and 10 GB per partition. A table scales far beyond that; one partition key does not.
- Partitions split by size and by throughput, but a split divides the key space — it cannot help when all traffic is on one key.
- Adaptive capacity lends unused throughput to busy partitions automatically, and does not raise the per-partition ceiling.
- A good partition key has high cardinality, even access, and matches how callers query. When a hot key is unavoidable, shard it with a suffix and fan out reads.
- Splits take time; pre-ramp before known spikes, or use on-demand billing for faster adaptation.
- Use Contributor Insights to identify the hot key rather than guessing.
Next: reads and writes — the API surface, consistency choices, conditional writes, and what each operation actually costs.