DynamoDB table uses on-demand capacity or has auto scaling enabled for read and write capacity units
DynamoDB tables use automatic capacity scaling via on-demand mode or PROVISIONED mode with auto scaling enabled for both read and write capacity units.
Provisioned tables are evaluated for scaling on both dimensions.
Risk
Insufficient capacity scaling causes throttling that degrades availability and increases latency.
Sustained throttling can trigger retry storms, timeouts, and backlogs, risking missed writes or out-of-order processing that impacts data integrity and drives operational costs.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks dynamodb_table_autoscaling_enabledRecommendation
Adopt elastic capacity: prefer on-demand for unpredictable traffic, or use PROVISIONED with auto scaling on both reads and writes.
Define safe utilization targets and bounds, monitor consumption, and plan for bursts to maintain availability and resilience over manual fixed throughput.
Remediation
CLI
aws dynamodb update-table --table-name <table-name> --billing-mode PAY_PER_REQUESTTerraform
# DynamoDB table with on-demand capacity
resource "aws_dynamodb_table" "<example_resource_name>" {
name = "<example_resource_name>"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
billing_mode = "PAY_PER_REQUEST" # Critical: enables on-demand capacity to pass the control
}NativeIaC
# CloudFormation: Set table to on-demand capacity
Resources:
<example_resource_name>:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST # Critical: enables on-demand capacity to pass the controlOther
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.autoscaling.applicationautoscaling_client import (
applicationautoscaling_client,
)
from prowler.providers.aws.services.dynamodb.dynamodb_client import dynamodb_client
class dynamodb_table_autoscaling_enabled(Check):
def execute(self):
findings = []
scalable_targets = applicationautoscaling_client.scalable_targets
dynamodb_scalable_targets = [
target
for target in scalable_targets
if target.service_namespace == "dynamodb"
and target.resource_id.startswith("table/")
]
autoscaling_mapping = {}
for target in dynamodb_scalable_targets:
table_name = target.resource_id.split("/")[1]
if table_name not in autoscaling_mapping:
autoscaling_mapping[table_name] = {}
autoscaling_mapping[table_name][target.scalable_dimension] = target
for table in dynamodb_client.tables.values():
report = Check_Report_AWS(metadata=self.metadata(), resource=table)
report.status = "PASS"
report.status_extended = (
f"DynamoDB table {table.name} automatically scales capacity on demand."
)
if table.billing_mode == "PROVISIONED":
read_autoscaling = False
write_autoscaling = False
if table.name in autoscaling_mapping:
if (
"dynamodb:table:ReadCapacityUnits"
in autoscaling_mapping[table.name]
):
read_autoscaling = True
if (
"dynamodb:table:WriteCapacityUnits"
in autoscaling_mapping[table.name]
):
write_autoscaling = True
if read_autoscaling and write_autoscaling:
report.status = "PASS"
report.status_extended = f"DynamoDB table {table.name} is in provisioned mode with auto scaling enabled for both read and write capacity units."
else:
missing_autoscaling = []
if not read_autoscaling:
missing_autoscaling.append("read")
if not write_autoscaling:
missing_autoscaling.append("write")
if missing_autoscaling:
report.status = "FAIL"
report.status_extended = f"DynamoDB table {table.name} is in provisioned mode without auto scaling enabled for {', '.join(missing_autoscaling)}."
findings.append(report)
return findings