DynamoDB tables on on-demand billing whose traffic is steady enough for provisioned capacity
What does ZopNight detect here?
ZopNight flags DynamoDB tables in `PAY_PER_REQUEST` mode whose combined read and write consumption over 30 days has a coefficient of variation below 0.50. It prices provisioned capacity sized to the observed peak at a 70% auto scaling target, and reports the gap to the on-demand bill when that gap is at least $5 a month.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-101 |
| Category | idle |
| Severity | medium |
| Metric | ConsumedReadCapacityUnits |
| Threshold | coefficient of variation < 0.50 |
| Evaluation window | 30d |
| Source | ZopNight |
| Permissions used | dynamodb:ListTables · dynamodb:DescribeTable · cloudwatch:GetMetricStatistics |
Where it applies
On-demand pays per request; provisioned pays per hour of capacity
On-demand mode charges for each read and write request, with no capacity to plan. Provisioned mode charges for the read and write capacity you set, hourly, whatever you consume. One read capacity unit gives one strongly consistent read per second (two eventually consistent) for items up to 4 KB, per the provisioned capacity guide.
On-demand is the right default for spiky or unknown traffic. Once a table settles into a steady pattern, though, capacity sized to that pattern usually costs less than paying per request.
Measuring how steady a table is
aws dynamodb describe-table --table-name orders \ --query 'Table.BillingModeSummary.BillingMode'
aws cloudwatch get-metric-statistics --namespace AWS/DynamoDB \ --metric-name ConsumedReadCapacityUnits --dimensions Name=TableName,Value=orders \ --start-time 2026-08-26T00:00:00Z --end-time 2026-09-25T00:00:00Z \ --period 3600 --statistics Sum MaximumRepeat for ConsumedWriteCapacityUnits. Hourly sums that stay in a narrow band, relative to their
average, point to a table provisioned capacity would handle cheaply.
How the steadiness test works
- The table’s billing mode is on-demand (
PAY_PER_REQUEST). - Both consumed read and consumed write series exist, each with at least 7 days of hourly peak coverage inside the 30-day window.
- Read and write are added together hour by hour, and the coefficient of variation of that combined series (standard deviation divided by mean) is below 0.50.
- ZopNight has the Region’s rates for on-demand request units and provisioned capacity units.
Tables that are not flagged
Anything already in provisioned mode is out of scope; tuning its capacity is the job of DynamoDB Auto Scaling Disabled. Tables with bursty traffic fail the variation test and should stay on on-demand. New tables with less than a week of data, tables with no measured requests, and cases where the provisioned price comes within $5 a month of the on-demand price are all left alone.
Pricing both modes from measured traffic
on-demand monthly = (avg reads per hour x read request rate + avg writes per hour x write request rate) x 730provisioned units = ceiling(peak units per hour / 3600 / 0.70), minimum 1, per axisprovisioned monthly = (read units x RCU hourly rate + write units x WCU hourly rate) x 730saving = on-demand monthly - provisioned monthlySizing to the peak and dividing by 0.70 leaves the same headroom a 70% auto scaling target keeps.
Switching the table to provisioned capacity
- Confirm the pattern holds across a full business cycle, not just the last month.
- Switch mode with capacity at or above the figures in the finding:
aws dynamodb update-table --table-name orders --billing-mode PROVISIONED --provisioned-throughput ReadCapacityUnits=40,WriteCapacityUnits=15 - Attach auto scaling with a 70% target so capacity follows the traffic.
- Watch throttled requests for the first 48 hours.