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

ChargePriceUnit
On-demand read request units (ReadRequestUnits)$0.125per million units
On-demand write request units (WriteRequestUnits)$0.625per million units
Provisioned read capacity beyond the free tier (ReadCapacityUnit-Hrs)$0.00013per RCU-hour
Provisioned write capacity beyond the free tier (WriteCapacityUnit-Hrs)$0.00065per 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

  1. Open Billing and Cost Management, then Cost Explorer, and set the date range to the last 3 months with Monthly granularity.
  2. Set Group by to Usage type.
  3. 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).
  4. Read the monthly cost per usage type. A line that grows faster than your traffic is the one to chase with the fix below.
  5. 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

  1. DynamoDB console > Tables; open a table > Additional settings and read Read/write capacity mode.
  2. Table > Monitor; read ConsumedWriteCapacityUnits and ConsumedReadCapacityUnits for the last 30 days with Sum at 1 hour.
  3. If the busiest hour is not more than about 3 times the quietest, the table is steady enough for provisioned capacity.
  4. Edit capacity settings > Provisioned, set capacity just above the peak per second, and turn on Auto scaling with a 70% target.
  5. 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.

See a sample result

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

Part of the guide: Reduce your AWS bill as a startup: a checklist for teams with no FinOps person