Hot Partition
A hot partition is a DynamoDB partition receiving a disproportionate share of a table’s read or write traffic. Requests to that partition get throttled with ProvisionedThroughputExceededException while the rest of the table sits well under capacity.
The confusing symptom, and the reason this is worth understanding properly: your table has plenty of capacity and is throttling anyway.
Why it happens
DynamoDB spreads a table across many physical partitions, assigning items by hashing the partition key. Capacity is allocated per partition, not per table, and each partition has hard ceilings:
| Limit | Value |
|---|---|
| Read capacity | 3,000 RCU/sec |
| Write capacity | 1,000 WCU/sec |
| Storage | 10 GB |
A table provisioned for 40,000 WCU still throttles if 1,500 writes per second target a single partition key value. Table-level capacity is the sum of what partitions can do, not a pool any partition can draw from freely.
There’s also a per-item ceiling that sharding cannot fix: a single item is limited to roughly 1,000 WCU/sec regardless of how the surrounding partition is keyed. If one specific record is the bottleneck, the answer is caching or write coalescing, not key redesign.
What adaptive capacity does and doesn’t do
AWS added adaptive capacity to soften this, and it’s often misunderstood as making hot partitions a non-issue.
What it does: automatically shifts capacity toward partitions receiving more traffic, and can isolate a persistently hot key onto its own partition. For gradual, sustained imbalance it works well and you may never notice a problem.
What it doesn’t do: react instantly, or exceed the hard per-partition limits. Reallocation takes minutes. A sudden spike, a scheduled batch job, or a flash-sale surge throttles before adaptive capacity responds. And no amount of adaptation lets one partition exceed 3,000 RCU or 1,000 WCU.
Treat adaptive capacity as a cushion for imperfect key design, not as a substitute for it.
Common causes
Low-cardinality partition keys. pk: STATUS#pending or pk: COUNTRY#US concentrates a large fraction of items and traffic on very few values. This is the most common cause by a wide margin.
Time-based partition keys. pk: 2026-08-05 means every write today hits one partition, then moves at midnight. High cardinality over time, catastrophic distribution at any instant.
The celebrity problem. Your key has excellent cardinality, but access is Zipf-distributed. A million users, one of whom is a public figure whose profile gets a thousand reads per second. The schema is fine; the traffic isn’t.
Static GSI partition keys. gsi1pk: TENANT_LIST for admin enumeration puts every tenant on one index partition. Deliberate and acceptable at low read volume, a problem the moment that view gets popular or polled.
Oversized tenant partitions in single-table design. Co-locating all of a tenant’s data under TENANT#<id> is the point of the pattern. It becomes a hot partition when one enterprise customer is a hundred times larger than the median, or when a tenant’s data exceeds 10 GB.
Diagnosing it
CloudWatch Contributor Insights for DynamoDB is the direct answer. Enable it on the table and it reports the most accessed partition keys by request count and throttled request count. This tells you exactly which key value is hot, which no other tool does as cleanly.
CloudWatch metrics. ThrottledRequests and UserErrors climbing while ConsumedWriteCapacityUnits sits well under ProvisionedWriteCapacityUnits is the diagnostic signature. Consumed capacity near provisioned means you need more capacity; consumed capacity far below it while throttling means you have a hot partition.
Application-side. Retries and elevated p99 latency on a specific access pattern, while other patterns are unaffected.
Fixes
Write sharding. Append a shard suffix to spread one logical key across N partitions: STATUS#pending#0 through STATUS#pending#9. Reads fan out across shards and merge client-side. This is the standard fix when the low-cardinality key is genuinely required.
Redesign the partition key. Often the hot key is a filter that shouldn’t have been a partition key at all. STATUS#pending as a base table partition key is usually a mistake; the same requirement is better served by a sparse index, which keeps the working set small and moves the hot key onto an index where write volume is lower.
Cache. DAX or an application cache in front of read-hot partitions removes the traffic entirely. This is the right answer for the celebrity problem, where the key design is correct and the traffic is simply skewed.
Split the entity out. In single-table design, when one entity type dominates a partition, move it to its own partition key. Projects under TENANT#<id> is elegant until a tenant has 100,000 projects; TENANT#<id>#PROJECTS#<shard> or a dedicated PROJECT#<id> partition is the escape hatch.
Common mistakes
Raising provisioned capacity. It does nothing for a hot partition and costs money. The table wasn’t out of capacity.
Sharding pre-emptively. Sharding adds read fan-out cost and code complexity on every read path. Design a sound key, monitor, and shard when Contributor Insights shows you need to. Most tables never do.
Assuming on-demand mode is immune. On-demand removes provisioning decisions, not per-partition physics. The same limits apply, and on-demand tables throttle on hot keys too.
Confusing hot partitions with hot items. If a single item is the bottleneck, sharding the partition key doesn’t help, because the item still lives in one place. Cache it or coalesce the writes.
Related terms
- Partition Key — the design decision that causes or prevents this
- Write Sharding — the standard mitigation
- Sparse Index — often a better answer than sharding a status key
Hot partitions are usually visible in the key structure long before they’re visible in CloudWatch. I’m building singletable.dev to flag low-cardinality keys while you’re still designing the schema.