This error occurs when your application's request rate exceeds the read or write capacity units (RCU/WCU) provisioned for your DynamoDB table. DynamoDB will reject excess requests with throttling, causing failures in your application.
The "ProvisionedThroughputExceededException" error means your DynamoDB table or global secondary index (GSI) has received more requests than the provisioned capacity can handle. DynamoDB enforces strict rate limits based on your configured Read Capacity Units (RCU) and Write Capacity Units (WCU). When you exceed these limits, DynamoDB rejects requests to prevent overload and maintain performance for all users. This is different from exceeding soft limits—it's a hard rejection that requires immediate attention. The error occurs at the partition level: each partition in your table can handle up to 1000 WCU or 3000 RCU per second. If a "hot partition" receives too many requests, it can be throttled even if your table has sufficient overall capacity.
DynamoDB requests that hit throttling should be retried with progressive delays. AWS SDKs handle this automatically, but verify your client configuration:
For AWS SDK v3 (JavaScript/Node.js):
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
const client = new DynamoDBClient({
region: "us-east-1",
// Exponential backoff is enabled by default
maxAttempts: 3, // Retry up to 3 times
});For Python (boto3):
import boto3
from botocore.config import Config
config = Config(
retries = {
'max_attempts': 3,
'mode': 'adaptive' # Uses exponential backoff
}
)
dynamodb = boto3.client('dynamodb', config=config)For Java:
AmazonDynamoDB client = AmazonDynamoDBClientBuilder
.standard()
.withRegion(Regions.US_EAST_1)
.build();
// Automatic retries are built-inIf you're consistently hitting limits, increase your provisioned capacity via the AWS Console or CLI:
Using AWS CLI:
aws dynamodb update-table \
--table-name YourTableName \
--billing-mode PROVISIONED \
--provisioned-throughput ReadCapacityUnits=200,WriteCapacityUnits=200Using AWS Console:
1. Open DynamoDB → Tables → Select your table
2. Go to "Capacity" tab
3. Change "Provisioned capacity" values
4. Click "Save changes"
Note: Capacity increases take a few seconds to apply. Decreases can only happen every 4 hours.
On-demand mode scales automatically based on traffic, eliminating throttling at the cost of variable pricing:
Using AWS CLI:
aws dynamodb update-billing-mode \
--table-name YourTableName \
--billing-mode PAY_PER_REQUESTUsing AWS Console:
1. Open DynamoDB → Tables → Select your table
2. Go to "Billing settings"
3. Select "On-demand" mode
4. Confirm the change
Best for: Unpredictable workloads, spike handling, or during testing. Costs more per request but no capacity planning needed.
Auto Scaling automatically adjusts capacity based on CloudWatch metrics:
Using AWS CLI:
# Enable auto scaling for read capacity
aws application-autoscaling register-scalable-target \
--service-namespace dynamodb \
--resource-id table/YourTableName \
--scalable-dimension dynamodb:table:ReadCapacityUnits \
--min-capacity 5 \
--max-capacity 200
# Create scaling policy
aws application-autoscaling put-scaling-policy \
--service-namespace dynamodb \
--scalable-dimension dynamodb:table:ReadCapacityUnits \
--resource-id table/YourTableName \
--policy-name MyTableReadScaling \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration TargetValue=70,PredefinedMetricSpecification={PredefinedMetricType=DynamoDBReadCapacityUtilization}Using AWS Console:
1. Open DynamoDB → Tables → Select your table
2. Go to "Capacity" tab
3. Enable "Autoscaling"
4. Set minimum and maximum capacity
5. Set target utilization (70% is typical)
Use CloudWatch Contributor Insights to find which partition keys are causing throttling:
1. Open CloudWatch → Logs → Contributor Insights
2. Create a rule for your DynamoDB table
3. View "LeadingKeys" to see most-accessed partition keys
For example, if user_id=123 receives 80% of traffic while others get 20%, that's a hot partition.
Solutions:
- Add randomness to partition keys (sharding): user_id#123#shard_1, user_id#123#shard_2
- Distribute traffic across multiple items: Use sort keys or secondary keys
- Cache frequently accessed items in ElastiCache or DAX
Example with sharding:
// Instead of: partition key = "user_123"
// Use: partition key = "user_123#shard_" + Math.floor(Math.random() * 10)
const userId = "user_123";
const shardId = Math.floor(Math.random() * 10);
const partitionKey = `${userId}#shard_${shardId}`;Inefficient queries can cause throttling. Optimize your access patterns:
Bad: Full table scan (expensive)
const params = {
TableName: "Users",
FilterExpression: "age > :age",
ExpressionAttributeValues: { ":age": { N: "25" } },
};
// Scans all items, very inefficientGood: Query with GSI if available
const params = {
TableName: "Users",
IndexName: "AgeIndex", // Global Secondary Index
KeyConditionExpression: "age > :age",
ExpressionAttributeValues: { ":age": { N: "25" } },
};
// Only reads relevant itemsBest practices:
- Use Query instead of Scan when possible
- Create indexes for commonly filtered attributes
- Use projection expressions to fetch only needed columns
- Batch operations to combine multiple requests
Global Secondary Indexes (GSIs) have their own provisioned capacity, separate from the base table:
Verify GSI capacity:
aws dynamodb describe-table --table-name YourTableName | grep -A 10 GlobalSecondaryIndexesUpdate GSI capacity:
aws dynamodb update-table \
--table-name YourTableName \
--global-secondary-index-updates \
"[{\"Update\": {\"IndexName\": \"YourGSI\", \"ProvisionedThroughputUpdate\": {\"ReadCapacityUnits\": 100}}}]"GSI throttling appears as the same error but affects queries on that index only.
Burst Capacity: DynamoDB provides burst capacity for temporary spikes. You can accumulate unused capacity as "burst capacity" which allows brief overages without throttling. However, burst capacity is limited and exhausts quickly under sustained load.
Partition Management: DynamoDB automatically splits partitions when they exceed capacity, but this takes time. During the split, throttling can still occur. If you know you'll need high capacity, request a quota increase in advance.
Cost Considerations:
- Provisioned: Cheaper for predictable, steady workloads. Pay per RCU/WCU per hour.
- On-demand: More expensive per request but scales automatically. Good for variable traffic.
- Auto Scaling: Middle ground, but doesn't respond instantly to sudden spikes.
Monitoring: Set up CloudWatch alarms for:
- ConsumedReadCapacityUnits > 80% of provisioned
- ConsumedWriteCapacityUnits > 80% of provisioned
- UserErrors (throttling exceptions) > 0
Regional Quotas: Default per-region quotas are 40,000 RCU and 40,000 WCU. Request increases via AWS Support if needed.
ValidationException: The provided key element does not match the schema
How to fix "ValidationException: The provided key element does not match the schema" in DynamoDB
UnrecognizedClientException: The security token included in the request is invalid
How to fix "UnrecognizedClientException: The security token included in the request is invalid" in DynamoDB
TransactionCanceledException: Transaction cancelled
How to fix "TransactionCanceledException: Transaction cancelled" in DynamoDB
RequestLimitExceeded: Throughput exceeds the current throughput limit for your account
How to fix "RequestLimitExceeded: Throughput exceeds the current throughput limit for your account" in DynamoDB
InternalServerError: Internal Server Error
How to fix "InternalServerError" in DynamoDB