CloudBurn Rules

DynamoDB Rules

CloudBurn cost optimization rules for Amazon DynamoDB.

These rules identify DynamoDB tables with stale data, provisioned tables missing auto-scaling, completely unused provisioned tables, and tables where autoscaling is configured with identical min and max values — all common sources of unnecessary DynamoDB spend.

Rule IDScan TypeName
CLDBRN-AWS-DYNAMODB-1DiscoveryDynamoDB Table Stale Data
CLDBRN-AWS-DYNAMODB-2Discovery and IaCDynamoDB Table Without Autoscaling
CLDBRN-AWS-DYNAMODB-3DiscoveryDynamoDB Table Unused
CLDBRN-AWS-DYNAMODB-4IaCDynamoDB Autoscaling Range Fixed

CLDBRN-AWS-DYNAMODB-1

DynamoDB Table Stale Data

Scan type: Discovery

What it checks

Flags DynamoDB tables whose data has not changed for more than 90 days, based on the table's latest stream label timestamp. Tables that store data nobody reads or writes are candidates for archival or deletion.

Tables without DynamoDB Streams enabled are skipped because there's no reliable timestamp to measure staleness.

Why it matters

DynamoDB charges for provisioned or on-demand read/write capacity and for stored data. A table sitting idle with no writes for 90+ days is still paying for storage (and capacity, if provisioned). If the data is no longer needed, deleting or archiving the table to S3 eliminates ongoing charges.

What triggers a finding

The table has DynamoDB Streams enabled, and the latestStreamLabel timestamp is more than 90 days in the past.

How to remediate

  1. Check whether any application still reads from the table. CloudWatch's ConsumedReadCapacityUnits metric can confirm if reads are happening
  2. If the table is no longer needed, export it to S3 for archival and delete it:
aws dynamodb export-table-to-point-in-time \
  --table-arn arn:aws:dynamodb:us-east-1:123456789012:table/my-table \
  --s3-bucket my-archive-bucket \
  --s3-prefix dynamodb-exports/

aws dynamodb delete-table --table-name my-table
  1. If the data is still needed but access is infrequent, switch the table to on-demand capacity mode to eliminate provisioned throughput charges during idle periods

CLDBRN-AWS-DYNAMODB-2

DynamoDB Table Without Autoscaling

Scan type: Discovery and IaC

What it checks

Flags provisioned-capacity DynamoDB tables that do not have Application Auto Scaling configured for table-level read and write capacity. Without auto-scaling, provisioned tables pay for a fixed throughput regardless of actual traffic.

Tables using on-demand (pay-per-request) billing are not flagged because they scale automatically.

Why it matters

A provisioned DynamoDB table without auto-scaling pays for its fixed capacity around the clock. If traffic drops to zero at night but the table is provisioned for peak daytime load, you're paying for unused capacity every off-peak hour. Auto-scaling adjusts provisioned capacity based on actual utilization, keeping costs proportional to demand.

What triggers a finding

All of the following must be true:

  • The table's billing mode is not PAY_PER_REQUEST (i.e., it uses provisioned capacity)
  • The table does not have a table-level read scalable target registered with Application Auto Scaling
  • The table does not have a table-level write scalable target registered with Application Auto Scaling

GSI-level auto-scaling targets are not considered for this rule, only table-level targets.

How to remediate

Register the table with Application Auto Scaling and create scaling policies:

# Register read capacity target
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id "table/my-table" \
  --scalable-dimension "dynamodb:table:ReadCapacityUnits" \
  --min-capacity 5 \
  --max-capacity 1000

# Register write capacity target
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id "table/my-table" \
  --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
  --min-capacity 5 \
  --max-capacity 1000

Alternatively, consider switching to on-demand billing if your traffic is unpredictable. On-demand costs more per request but eliminates the risk of over-provisioning entirely.

IaC resources checked

ProviderResource
Terraformaws_dynamodb_table + aws_appautoscaling_target
CloudFormationAWS::DynamoDB::Table + AWS::ApplicationAutoScaling::ScalableTarget

CLDBRN-AWS-DYNAMODB-3

DynamoDB Table Unused

Scan type: Discovery

What it checks

Flags provisioned-capacity DynamoDB tables with no consumed read or write capacity over the last 30 days.

Why it matters

Provisioned tables incur hourly charges for read and write capacity units whether or not the table receives any traffic. A table with zero consumed capacity for 30 days is wasting money on unused capacity.

What triggers a finding

billingMode is PROVISIONED AND totalConsumedReadCapacityUnitsLast30Days is 0 AND totalConsumedWriteCapacityUnitsLast30Days is 0.

How to remediate

Switch the table to on-demand billing (PAY_PER_REQUEST) if occasional access is expected, or delete the table if it's no longer needed. For tables with sporadic usage patterns, on-demand pricing eliminates charges during idle periods.


CLDBRN-AWS-DYNAMODB-4

DynamoDB Autoscaling Range Fixed

Scan type: IaC

What it checks

Flags provisioned-capacity DynamoDB tables whose autoscaling min and max capacity are set to the same value, making autoscaling ineffective.

Why it matters

When autoscaling min equals max, the table cannot scale up during traffic spikes or scale down during quiet periods. This defeats the purpose of autoscaling and locks you into paying for peak capacity around the clock.

What triggers a finding

billingMode is PROVISIONED AND either read min capacity equals read max capacity or write min capacity equals write max capacity.

How to remediate

Set a meaningful gap between min and max capacity. A common pattern is to set min at the sustained baseline and max at 2-5x the baseline, allowing autoscaling to handle spikes without over-provisioning during off-peak hours.

IaC resources checked

ProviderResource
Terraformaws_dynamodb_table + aws_appautoscaling_target
CloudFormationAWS::DynamoDB::Table + AWS::ApplicationAutoScaling::ScalableTarget

See Also