Choosing Between DynamoDB On-Demand and Provisioned Capacity: A Practical Decision Framework
A practical framework for picking DynamoDB On‑Demand vs Provisioned capacity, with cost crossover math, scaling behavior, operational signals, a worked e‑commerce example, and a step‑by‑step switch checklist.
06 Jan 2026, 23:50 UTC

The problem: capacity mode surprises
You launch a new service on DynamoDB, pick On‑Demand because it “just works,” and three months later the bill is twice what you expected. Or you provision 500 RCU/WCU, enable auto‑scaling, and still see throttling during a flash sale. Both scenarios stem from the same root cause: the capacity mode was chosen without a concrete workload model.
Thesis
Match the capacity mode to the traffic pattern and cost commitment you can reliably forecast. On‑Demand shines for unpredictable or brand‑new workloads; Provisioned with auto‑scaling wins when you can sustain ~30 %+ utilization and are willing to manage scaling policies or commit to Savings Plans.
How the two modes behave
- On‑Demand – You pay per request (Read Request Units / Write Request Units). No capacity planning, instant scale up to 2× the previous peak (default soft limit 40 k RRU / 40 k WRU per table per region). Beyond that, partitions split and you may see 5‑30 minutes of throttling.
- Provisioned – You reserve RCU/WCU per hour. Auto‑scaling (target‑tracking) adjusts capacity in 1‑5 minutes per event; default cooldowns are 5 min scale‑out, 15 min scale‑in. Each partition still caps at 3 k RRU / 1 k WRU and 10 GB.
Cost modeling and the crossover point
At roughly 30‑40 % average utilization of provisioned capacity, Provisioned becomes cheaper than On‑Demand for sustained traffic. Example (us‑east‑1, 2026 pricing):
| Mode | Configuration | Hourly cost | Monthly (730 h) |
|---|---|---|---|
| Provisioned | 100 RCU + 100 WCU | $0.65 | $475 |
| On‑Demand @100 % util. | 100 RRU/s + 100 WRU/s | $1.44 | $1,051 |
| On‑Demand @30 % util. | 30 RRU/s + 30 WRU/s | $0.43 | $314 |
If you can commit to 1‑3 year Savings Plans, Provisioned drops up to 77 % further, moving the crossover well below 20 % utilization.
Operational signals for switching
- Move to Provisioned – Stable daily/weekly pattern, sustained utilization >35 % for 2+ weeks, predictable seasonal peaks.
- Stay On‑Demand – New product launch, event‑driven bursts, multi‑tenant “noisy neighbor” risk, average utilization <15 %.
Monitor ConsumedReadCapacityUnits, ConsumedWriteCapacityUnits, ThrottledRequests, and the account‑level AccountMaxTableLevelReads/Write quotas. For On‑Demand, also track RequestCount and ReturnedItemCount. CloudWatch Contributor Insights reveals hot partition keys regardless of mode.
Worked example: e‑commerce cart service
Baseline: 5 k RRU/s, 5 k WRU/s. Black Friday peak: 50 k RRU/s for 2 hours.
- On‑Demand annual cost ≈ $1,200 (baseline) + $180 (peak) = $1,380.
- Provisioned 5 k RCU/WCU + auto‑scale to 50 k → $0.65/h × 8,760 h ≈ $5,700 baseline + scaling overhead.
- Hybrid not natively supported – you would need separate tables or accept the On‑Demand premium for the peak window.
Decision: because the peak is short and predictable, the team keeps On‑Demand for the whole table and adds a short‑lived read‑replica (global table) for the sale window, avoiding the high provisioned baseline cost.
Limitations and gotchas
- On‑Demand cannot use Savings Plans; Provisioned can.
- Auto‑scaling cooldowns can cause throttling during rapid ramps; custom policies with lower cooldowns mitigate but don’t eliminate it.
- TTL deletions consume WCU in both modes – large purges can throttle writes. Batch‑delete with rate limiting or schedule during low‑traffic windows.
- PartiQL
SELECTwithout a key condition scans the entire table, consuming RCU proportional to table size. Always use key conditions or a GSI;EXPLAINshows the estimated capacity cost.
Actionable checklist
- Collect 2‑4 weeks of
ConsumedReadCapacityUnitsandConsumedWriteCapacityUnitsat 1‑minute granularity. - Calculate average utilization = (average consumed / provisioned) × 100 %. If you’re on On‑Demand, treat the 2× previous peak as your “provisioned” ceiling.
- If utilization >35 % and pattern is stable → plan a switch to Provisioned.
- Switch via a single
UpdateTablecall (once per 24 h). Example (run in a terminal with AWS CLI v2, profile that hasdynamodb:UpdateTableandapplication-autoscaling:*permissions):aws dynamodb update-table \ --table-name CartTable \ --billing-mode PROVISIONED \ --provisioned-throughput ReadCapacityUnits=5000,WriteCapacityUnits=5000After the call, recreate auto‑scaling policies (target‑tracking on
ConsumedReadCapacityUnits/ConsumedWriteCapacityUnitswith 70 % target). - Validate: watch
ThrottledRequestsfor 30 minutes; it should drop to zero. Confirm cost change in the next billing report. - If you later need On‑Demand again, run:
aws dynamodb update-table \ --table-name CartTable \ --billing-mode PAY_PER_REQUESTNote: this resets any auto‑scaling configuration.
Closing thought
Capacity mode is not a “set‑and‑forget” knob. Treat it as a lever you revisit whenever traffic patterns shift or a Savings Plan becomes viable. The cheapest architecture is the one that matches your actual usage curve—not the one that sounds simplest on the pricing page.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.