Home Resume
Home Blog AWS Architecture Series #18 — DynamoDB On-Demand vs Provisioned: The Utilisation Number That Decides It…
AWS AWS Architecture Series

AWS Architecture Series #18 — DynamoDB On-Demand vs Provisioned: The Utilisation Number That Decides It

On-demand and provisioned DynamoDB are billed in different units, so the choice is not a philosophy. Convert both to cost per million requests and a break-even utilisation falls out — about 29%, and the same on both axes since November 2024.

Verified against current vendor documentation on 12 August 2026. Pricing, limits and API behaviour were checked against the official docs on that date. Cloud services change fast — if you are reading this much later, treat the specifics as a starting point and re-check the linked sources.

Business Challenge

A team ran about forty DynamoDB tables, every one of them on-demand. The reasoning was reasonable and entirely unexamined: on-demand is the serverless option, serverless is the modern default, and nobody wanted to forecast capacity for forty tables.

Most of those tables served a business application with the traffic shape you would expect — busy in office hours, quiet overnight, essentially identical week to week. That is about as forecastable as load gets. They were paying per-request rates for a workload whose requests could have been predicted a month in advance.

The interesting part is that “on-demand is more expensive at steady load” is not a useful statement on its own. Steady at what level? The two modes are billed in different units — one per request, one per reserved unit per hour — so until you put them on the same scale there is nothing to compare.

1The two prices are not comparable until you convert them

On-demand is $0.625 per million writes. Provisioned is $0.00065 per WCU-hour. Those numbers cannot be compared as written.

One write capacity unit sustains one 1 KB write per second, so held for an hour it serves 3,600 writes. Divide: $0.00065 / 3,600 is about $0.18 per million writes at full utilisation. On-demand costs roughly 3.5× that.

Fix

Convert both to cost per million requests before arguing about which is cheaper. Everything else follows from that one division.

2That ratio is really a utilisation threshold

Provisioned capacity only achieves $0.18 per million if every unit is used every second, which never happens. At half utilisation it is $0.36; at a quarter, $0.72 — more than on-demand.

So the real question is what utilisation makes them equal, and that is simply $0.18 / $0.625: about 29%. Sustain average write utilisation above roughly 29% and provisioned is cheaper. Below it, on-demand is, and no amount of tuning changes that.

Fix

Pull ConsumedWriteCapacityUnits against provisioned capacity for a fortnight. The average is the answer.

3Reads and writes cross over at the same point — now

Running the same arithmetic on reads gives, surprisingly, the same answer. $0.00013 / 3,600 is about $0.04 per million strongly consistent reads, against $0.125 per million on-demand — a ratio of 3.5× and a break-even near 29%. Identical to writes, to the decimal place.

That is not a coincidence, and it is recent. In November 2024 AWS halved on-demand throughput pricing while leaving provisioned rates alone, which moved both break-even points together. Anything written before that date — including a good deal of advice still circulating — puts reads at roughly half the utilisation writes need. That was true against the old $0.25 read price. It is not true now.

Fix

One threshold, not two: about 29% average utilisation on either axis. If a source quotes different break-evens for reads and writes, check the date on its prices.

4The console deletes your auto scaling settings

This one is documented and still surprising. Switching a table from provisioned to on-demand behaves differently depending on how you do it: in the console all of your auto scaling settings will be deleted, while through the CLI or SDK all of your auto scaling settings will be preserved and can be reapplied when you switch back.

Identical operation, different outcome, decided entirely by which tool someone reached for. Try on-demand for a week via the console, switch back, and the carefully tuned scaling policy is simply gone — with the table working perfectly well the whole time on flat capacity.

Fix

Make mode changes through the CLI or IaC, never the console. Anything reversible should stay reversible.

Architecture

Diagram: on-demand and provisioned DynamoDB pricing converted to a common cost-per-million-requests basis, showing provisioned becoming cheaper above about 29% sustained utilisation on either axis, plus the four-switches-per-24-hours limit and the console behaviour that deletes auto scaling settings.

The decision, in the order it should be made

Start on-demand for anything new. You cannot forecast a workload that has never run, and a wrong provisioned figure either throttles users or wastes money. On-demand buys accurate measurements of real traffic, which is exactly what the next step needs.

After a few weeks, compute utilisation per table, per axis. Average consumed capacity against what you would have to provision to serve the peak without throttling. Above roughly 29% on either axis, provisioned wins.

Move only the tables that clear it, and keep auto scaling on. Provisioned without auto scaling means provisioning for peak and paying for peak around the clock, which throws away most of the saving that justified the move.

Auto scaling does not reach the theoretical number

The 29% figure assumes you can safely run capacity right at consumption, and you cannot. AWS's own recommended default target utilisation is 70%, deliberately leaving headroom for scaling to react — it responds to sustained change, not to a spike that arrives in seconds.

So provisioned at a 70% target costs about $0.18 / 0.7, near $0.26 per million writes. Still well under on-demand's $0.625, but the honest saving on a steady table is closer to 2.4× than 3.5×. Quote the achievable number, not the theoretical one.

What happens at the moment of the switch

Switching is not instantaneous and not symmetric. AWS states a table can move from provisioned to on-demand up to four times in a 24-hour rolling window, while the reverse can be done at any time. Any design that flips modes to chase load is therefore not viable.

Throughput during and after the change is also worth knowing. The switch takes several minutes, during which the table serves throughput consistent with its previous provisioned settings. A table moving to on-demand for the first time is scaled to sustain at least 4,000 write units and 12,000 read units per second, or its previous peak if that was higher — and coming back the other way, it delivers throughput consistent with the peak it reached while on-demand.

Why This Architecture Holds Up

It replaces a preference with an arithmetic question

“On-demand versus provisioned” is usually argued as a philosophy — serverless purity against operational control — and that argument has no ending because neither side is describing the workload. Converting both to cost per million requests turns it into a measurement, and measurements can be settled.

It also makes the answer legitimately different per table, which a philosophy cannot. Forty tables do not share one traffic shape, and there is no reason they should share one billing mode.

The threshold is stable even when the prices are not

AWS has changed these rates before and will again. What survives a price change is the method: divide the hourly rate by 3,600, compare to the per-request rate, and the ratio gives the break-even. Re-running that division after a price change takes a minute, whereas a memorised number becomes quietly wrong.

Reserved capacity is a third option, and it is not free of risk

For provisioned tables, reserved capacity offers up to 54% for a one-year term and up to 77% for three years. That is a substantial further saving on the steady tables — but it is a commitment on a resource whose right size you have only recently worked out.

Sequence it accordingly: measure, move to provisioned, run long enough to trust the number, and only then reserve. Committing three years to a figure derived from two weeks of data is how a cost optimisation becomes a cost floor.

Key Architecture Decisions

SituationChooseBecause
New table, unknown traffic On-demand Nothing to forecast from. It buys real measurements at a price that scales to zero.
Steady load above ~29% write utilisation Provisioned with auto scaling Past the break-even, on-demand is roughly 3.5× the per-request cost.
Read-heavy table, modest writes Provisioned reads, judge writes separately Both cross over near 29%, but the axes are provisioned independently, so one can clear it while the other does not.
Sharp, unpredictable spikes On-demand Auto scaling reacts to sustained change, not to a spike arriving in seconds.
Changing a table's mode CLI or IaC, never the console The console deletes auto scaling settings; the CLI and SDK preserve them.
Provisioned and stable for months Consider reserved capacity Up to 54% for one year, 77% for three — but only once the figure is trustworthy.

The audit that pays for itself

For every on-demand table, pull ConsumedWriteCapacityUnits and ConsumedReadCapacityUnits for a fortnight at one-minute resolution. Take the average and the peak on each axis. Average divided by peak is your achievable utilisation, and any table over roughly 29% on either axis is currently overpaying. Sort by total request volume and the list is already in priority order.

Closing Thought

On-demand is not the expensive option and provisioned is not the grown-up one. They are two billing units for the same capacity, and which is cheaper is decided by a number that most teams have never calculated for their own tables — despite it being one division away from metrics they already collect.

What makes this worth doing properly rather than globally is that the answer genuinely varies per table, and per axis within a table. A blanket policy either way is a decision not to look. The version that holds up is unglamorous: start on-demand because you know nothing, measure because it is cheap to, and move the tables that have earned it.

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent