Symptoms
ProvisionedThroughputExceededExceptionorThrottlingExceptionin app logs; SDK retries make latency spike.ReadThrottleEvents/WriteThrottleEventsmetrics above zero.- Sometimes consumed capacity is well below provisioned — the sign of a hot partition.
1. Table, index or partition?
aws cloudwatch get-metric-statistics --namespace AWS/DynamoDB --metric-name WriteThrottleEvents \
--dimensions Name=TableName,Value=orders --start-time $(date -u -d '-1 hour' +%FT%TZ) \
--end-time $(date -u +%FT%TZ) --period 60 --statistics Sum --output table
| Pattern | Likely cause |
|---|---|
| Consumed ≈ provisioned, all keys | Table capacity too low |
| Consumed far below provisioned | Hot partition / hot key |
| Table fine, writes throttled | A GSI is throttled — GSI throttling back-pressures base table writes |
| On-demand table throttled after a sudden jump | Traffic exceeded what on-demand can absorb instantly (it scales from previous peak) |
Check GSIs too: the same metrics with the GlobalSecondaryIndexName dimension.
2. Find the hot keys
aws dynamodb update-contributor-insights --table-name orders --contributor-insights-action ENABLE
aws dynamodb describe-contributor-insights --table-name orders
Contributor Insights shows the most accessed and most throttled partition keys in CloudWatch. A single customer ID, a date-only key (2026-10-24) or a status key (PENDING) is the usual suspect.
3. Quick relief
Raise provisioned capacity (or autoscaling max):
aws dynamodb update-table --table-name orders \
--provisioned-throughput ReadCapacityUnits=4000,WriteCapacityUnits=2000
Or switch to on-demand for unpredictable spikes:
aws dynamodb update-table --table-name orders --billing-mode PAY_PER_REQUEST
There are limits on how often you can switch billing modes; check current rules before flipping back and forth.
Throttled GSI:
aws dynamodb update-table --table-name orders --global-secondary-index-updates \
'[{"Update":{"IndexName":"status-index","ProvisionedThroughput":{"ReadCapacityUnits":2000,"WriteCapacityUnits":2000}}}]'
Note
More capacity helps less with a single hot key: each partition has its own throughput ceiling. Adaptive capacity spreads load, but one key can still be throttled. That needs a design fix.
4. Reduce load right now
- Make sure SDK retries use exponential backoff with jitter (the AWS SDK default) and that the app isn't adding its own tight retry loop.
- Put DAX or an application cache in front of hot reads.
- Batch writers: slow them down or smooth them with a queue (SQS) instead of bursting.
5. Fix the key design
- Write sharding: append a suffix (
customerId#0..9) and read with parallel queries. - Avoid low-cardinality GSI keys (
status); use a sparse index or composite keys. - Spread time-series writes across keys rather than one "today" key.
Prevent it next time
- Alarm on
ThrottledRequestsand on GSI throttle metrics, not just consumed capacity. - Load test with realistic key distribution, not random keys.
- Keep Contributor Insights on for critical tables.