Home / AWS

AWSTroubleshootingAdvanced

Sev1: DynamoDB throttling — ProvisionedThroughputExceeded, hot partitions and fast relief

Stop DynamoDB throttling that is failing user requests. Tell table-level from partition-level throttling, find hot keys with Contributor Insights, apply quick relief (on-demand, capacity, GSI fixes) and redesign the key so it doesn't come back.

Deepak Bhardwaj2 min read

Applies toAmazon DynamoDB (provisioned and on-demand), DynamoDB global secondary indexes, AWS CLI v2

Symptoms

  • ProvisionedThroughputExceededException or ThrottlingException in app logs; SDK retries make latency spike.
  • ReadThrottleEvents / WriteThrottleEvents metrics 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 ThrottledRequests and on GSI throttle metrics, not just consumed capacity.
  • Load test with realistic key distribution, not random keys.
  • Keep Contributor Insights on for critical tables.