Home › Decoder › ReadRequestUnits and WriteRequestUnits - when DynamoDB on-demand costs 3.5x provisioned
ReadRequestUnits and WriteRequestUnits - when DynamoDB on-demand costs 3.5x provisioned
WriteRequestUnits and ReadRequestUnits are the DynamoDB on-demand charges: $0.625 per million write request units and $0.125 per million read request units in US East (N. Virginia).
In your bill the usage type reads: WriteRequestUnits, USE1-WriteRequestUnits, ReadRequestUnits, USE1-ReadRequestUnits
What it costs
| Charge | Price | Unit |
|---|---|---|
| On-demand read request units (ReadRequestUnits) | $0.125 | per million units |
| On-demand write request units (WriteRequestUnits) | $0.625 | per million units |
| Provisioned read capacity beyond the free tier (ReadCapacityUnit-Hrs) | $0.00013 | per RCU-hour |
| Provisioned write capacity beyond the free tier (WriteCapacityUnit-Hrs) | $0.00065 | per WCU-hour |
US East (N. Virginia); other regions differ. Checked 2026-11-11. Sources: Amazon DynamoDB pricing, AWS price list file, Amazon DynamoDB offer, us-east-1.
Example with made-up numbers
A table on on-demand with a steady 200 writes per second all month: 200 x 3,600 x 730 = 525,600,000 write request units
On-demand: 525.6 x $0.625 = $328.50. Provisioned at 300 write capacity units (200 / 0.7 target use, rounded up): 300 x 730 x $0.00065 = $142.35
Switching saves $328.50 - $142.35 = $186.15 per month on that table
Typical causes
On-demand left on after launch
A table created on-demand during development for convenience, kept after the traffic became steady.
Steady background load
Queues, session stores and counters that write at a constant rate all day.
Global secondary indexes
Every write to an indexed attribute also writes the index, multiplying write units.
Large items and scans
Write units are per 1 KB and reads per 4 KB; big items and table scans consume many.
Find it in your bill
Have a CUR file queryable in Athena? Paste this and run it:
SELECT date_trunc('month', line_item_usage_start_date) AS month,
line_item_product_code,
line_item_usage_type,
line_item_resource_id,
SUM(line_item_usage_amount) AS usage_amount,
SUM(line_item_unblended_cost) AS cost
FROM your_cur_table
WHERE line_item_product_code = 'AmazonDynamoDB'
AND (line_item_usage_type LIKE '%ReadRequestUnits'
OR line_item_usage_type LIKE '%WriteRequestUnits')
GROUP BY 1, 2, 3, 4
ORDER BY month DESC, cost DESC
LIMIT 50;Columns used: line_item_usage_start_date, line_item_product_code, line_item_usage_type, line_item_resource_id, line_item_usage_amount, line_item_unblended_cost.
No CUR file? Use Cost Explorer
- Open Billing and Cost Management, then Cost Explorer, and set the date range to the last 3 months with Monthly granularity.
- Set Group by to Usage type.
- In the Filters panel choose Usage type and tick the entries ending in *ReadRequestUnits or *WriteRequestUnits (the region prefix, such as USE1-, differs by region).
- Read the monthly cost per usage type. A line that grows faster than your traffic is the one to chase with the fix below.
- To see which resource drives it, query the CUR above; resource IDs appear only if your CUR was set up with resource IDs included, otherwise the resource column is empty.
Column names checked against: docs.aws.amazon.com/cur/latest/userguide/Lineitem-columns.html, docs.aws.amazon.com/cur/latest/userguide/cur-ate-run.html.
The fix, step by step
Verify first
Check these before you change anything: the steps below are suggestions, and only you can see your own configuration.
- Provisioned tables throttle requests above their capacity; set Auto scaling minimum and maximum capacity so a spike does not cause errors.
- You can switch a table between on-demand and provisioned only once every 24 hours; do not switch in the middle of a launch or load test.
- Check indexes: each global secondary index has its own capacity and its own consumption.
- Tables with large items or heavy scans use many units; reducing item size or replacing scans with queries can save more than a mode change.
- Check for reserved capacity commitments before changing; they are billed for provisioned capacity regardless of use.
In the console
- DynamoDB console > Tables; open a table > Additional settings and read Read/write capacity mode.
- Table > Monitor; read ConsumedWriteCapacityUnits and ConsumedReadCapacityUnits for the last 30 days with Sum at 1 hour.
- If the busiest hour is not more than about 3 times the quietest, the table is steady enough for provisioned capacity.
- Edit capacity settings > Provisioned, set capacity just above the peak per second, and turn on Auto scaling with a 70% target.
- Repeat per table, starting with the one that has the biggest share of the line in your file.
With the CLI
aws dynamodb list-tables
aws dynamodb describe-table --table-name EXAMPLE --query 'Table.[BillingModeSummary,ProvisionedThroughput]'
aws cloudwatch get-metric-statistics --namespace AWS/DynamoDB --metric-name ConsumedWriteCapacityUnits --dimensions Name=TableName,Value=EXAMPLE --statistics Sum --period 3600 --start-time 2026-10-01T00:00:00Z --end-time 2026-11-01T00:00:00Z
aws dynamodb update-table --table-name EXAMPLE --billing-mode PROVISIONED --provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=300
aws application-autoscaling register-scalable-target --service-namespace dynamodb --resource-id table/EXAMPLE --scalable-dimension dynamodb:table:WriteCapacityUnits --min-capacity 100 --max-capacity 1000
Rollback
Switch the table back to on-demand with update-table --billing-mode PAY_PER_REQUEST; the 24-hour limit applies, so if requests are throttled in the meantime raise provisioned capacity or the Auto scaling maximum first.
Find your DynamoDB lines in your own bill
Drop in your Cost Explorer or CUR CSV. Billtrim reads it in your browser, finds the on-demand read and write lines and shows how many request units you pay for.
Paste your export: how to export a Cost Explorer CSV or CUR file in two minutes.
Questions people ask
When does on-demand beat provisioned?
When average use is under about 29% of the capacity you would provision, because a fully used provisioned unit costs 28.9% of the on-demand price.
Can I switch a table back and forth?
You can change the capacity mode once every 24 hours.
Is there a free tier?
Provisioned capacity has a free allowance of 25 read and 25 write capacity units a month in the price list; on-demand requests do not.
Related
- Requests-Tier1 and Requests-Tier2 - $0.005 per 1,000 PUTs and $0.0004 per 1,000 GETs
- CW:MetricMonitorUsage and CW:AlarmMonitorUsage - custom metrics and alarms
- USE1-USW2-AWS-Out-Bytes - data sent between regions, and how to cut it
Part of the guide: Reduce your AWS bill as a startup: a checklist for teams with no FinOps person