Skip to main content

Over-provisioned DynamoDB: paying for capacity you never use

· 3 min read
Founder, Dragon Fractal · ex-AWS engineer

Short version: With provisioned DynamoDB capacity you pay for the read/write units you reserve, used or not. Tables are routinely over-provisioned "to be safe" and then run at 5-10% utilization for years. Here is how to find them and pick the right fix: right-size, turn on auto-scaling, or move to on-demand.

Why over-provisioning happens

Someone sets a table to 1,000 RCU / 1,000 WCU during a launch or load test, traffic never materializes, and the provisioned numbers are never revisited. You keep paying for 1,000 units while consuming 50. Because DynamoDB does not bill a big scary line item, it hides.

Step 1 - Compare provisioned vs consumed

Check a table's provisioned capacity:

aws dynamodb describe-table --table-name my-table \
--query 'Table.ProvisionedThroughput.{Read:ReadCapacityUnits,Write:WriteCapacityUnits}'

Then pull actual consumption over the last week from CloudWatch:

aws cloudwatch get-metric-statistics \
--namespace AWS/DynamoDB --metric-name ConsumedReadCapacityUnits \
--dimensions Name=TableName,Value=my-table \
--start-time "$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)" \
--end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--period 86400 --statistics Average Maximum \
--query 'Datapoints[].{Avg:Average,Max:Maximum}'

Average consumption far below provisioned (say, under 20%) means you are overpaying.

Step 2 - Pick the right fix

  • Steady, predictable traffic that is just set too high -> lower the provisioned numbers to match reality:
    aws dynamodb update-table --table-name my-table \
    --provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=100
  • Variable-but-known daily pattern -> enable auto-scaling so capacity tracks demand instead of sitting at a fixed ceiling.
  • Spiky or unpredictable, low-average traffic -> switch to on-demand, which bills per request with no reserved capacity:
    aws dynamodb update-table --table-name my-table --billing-mode PAY_PER_REQUEST

The caveat: on-demand is not always cheaper

On-demand costs roughly 5-7x more per request than provisioned. It wins for spiky, low-average, or unpredictable workloads (you pay nothing when idle), but for steady high throughput provisioned + auto-scaling is far cheaper. Right-size based on the consumption pattern, not a blanket switch. You can change billing mode once per 24 hours, so decide deliberately.

Do it automatically

Cloud Cost Analyzer's dynamodb-over-provisioned rule flags tables running below 20% utilization and estimates the right-sizing savings - alongside 89 other cost rules:

curl -sSL https://releases.dragonfractal.com/install.sh | sh
cca scan --provider aws

The agent runs in your environment with read-only access, so your AWS credentials never leave it. See the AWS setup and required IAM permissions

CLI Reference

  • aws dynamodb describe-table
  • aws dynamodb update-table
  • aws dynamodb describe-auto-scaling-settings