The first Bedrock bill that surprised one of my teams was not the model. It was a retry loop. A batch job hit a throttle, backed off, retried the whole prompt, and every retry re-sent 6,000 tokens of context. The token rate on the page was correct. The monthly number was four times what anyone estimated, because nobody costed the traffic, only the model.
That is the whole problem with Bedrock pricing. The per-token numbers are easy to read and easy to misread. The mode you pick, on-demand versus batch versus a reserved model unit, moves the bill more than the model choice does once you are past the prototype. So this part is about the five ways Bedrock charges you, when each one is the right call, and the arithmetic that tells you which side of the line you are on.
The five ways Bedrock charges you
Bedrock does not have one price. It has five billing modes, and the same model can be served under several of them. Before the table, three plain definitions. A token is roughly three quarters of a word; you pay separately for input tokens (your prompt) and output tokens (the model reply), and output almost always costs more. A model unit, or MU, is a fixed block of throughput you can reserve for a model. On-demand means you pay only for tokens you actually send, with no reservation.
On-demand, and why nearly everyone starts here
On-demand is the default. You send a request, Bedrock charges for the input and output tokens, and you owe nothing when traffic is zero. That last property is why it wins for prototypes and for any workload where you cannot predict the load. You never pay for idle capacity.
The rates vary by model across a wide range, from a few cents per million tokens up to tens of dollars per million on the largest frontier models. The Amazon Nova family sits at the cheap end and is priced to pull workloads onto Bedrock. Here are the on-demand token rates for Nova, which I use constantly for classification and extraction where a frontier model is overkill.
Read the output column, not the input column. Output tokens on Nova Pro cost four times the input. On chatty workloads with long replies, output dominates the bill, and every extra sentence you let the model ramble is money. The single cheapest optimization I know is a tight max output token limit and a system prompt that tells the model to be brief.
Batch inference and the flat 50 percent
Batch inference is the easiest win in the whole pricing story. For supported models from Anthropic, Meta, Mistral, and Amazon, you get a flat 50 percent off the on-demand token rate. The trade is latency and shape. You do not call the model live. You write a JSONL file of prompts to Amazon S3, kick off a batch job, and Bedrock returns the results to an S3 bucket, typically within 24 hours.
That fits more work than teams assume. Overnight document classification, embedding backfills, nightly summarization of the day tickets, evaluation runs over a test set, any bulk transform where a human is not waiting on the reply. If nobody is watching a spinner, batch should be your first thought. Half price for moving a job from synchronous to asynchronous is a trade I take almost every time.
Provisioned Throughput is a capacity tool, not a discount
This is where people lose money chasing a discount that is not there. Provisioned Throughput, or PT, lets you reserve capacity for a model in model units. Each MU guarantees a level of throughput, and you are billed by the hour for as long as the reservation exists, used or idle, the same way an EC2 Reserved Instance bills whether the box is busy or not. You can buy with no commitment, a 1-month commitment, or a 6-month commitment, and longer commitments carry lower hourly rates.
PT exists for three reasons: guaranteed capacity so you are never throttled at peak, predictable latency, and access to custom fine-tuned models which can only be served through PT. Raw cost savings on a cheap base model is usually not one of them. An MU billed around the clock is a large fixed number, and for an inexpensive model like Nova you need enormous, steady volume before the flat hourly rate beats paying per token. The honest rule: reach for PT when you need the capacity guarantee or you are serving a custom model, and let the cost math confirm it rather than lead.
Worked example
Take Nova Pro on-demand at 0.80 input and 3.20 output per 1M tokens. Assume an average request of 2,000 input tokens and 500 output tokens. Cost per request is (2000/1,000,000 times 0.80) plus (500/1,000,000 times 3.20), which is 0.0016 plus 0.0016, so 0.0032 dollars per request.
On-demand monthly cost is 0.0032 times your request count. Batch is half that. Now put a single Provisioned Throughput model unit next to it at an illustrative no-commit rate of 24 dollars per hour [VERIFY, model dependent, confirm with your account team]. That MU costs 24 times 730 hours, so about 17,520 dollars per month flat.
Break-even against on-demand is 17,520 divided by 0.0032, which is roughly 5.47 million requests every month, running steadily, before the reserved unit is even level with paying per token. Below that, on-demand or batch wins outright. This is why I do not reach for PT on cheap models to save money. I reach for it when I need the capacity floor.
Prompt caching, the discount hiding in plain sight
Prompt caching is the mode most teams forget. If your requests share a large, stable prefix, a long system prompt, a fixed instruction block, a document you ask many questions about, Bedrock can cache that prefix. The first call writes the cache and costs a little more than a normal input token. Every later call that reuses it reads from cache at roughly a tenth of the on-demand input rate, about a 90 percent saving on those repeated tokens.
This lands hardest on RAG and agent stacks, where a 4,000 token system prompt and toolset ride along on every single call. Cache it once and you stop paying full freight for the same preamble thousands of times. The catch is that caching is supported on a subset of models and there is a short time-to-live on the cache, so it helps steady traffic more than a request that arrives once an hour. Check that your model supports it before you design around it.
Fine-tuning adds three separate charges
Model customization, which is fine-tuning or continued pre-training, is not one price either. You pay for training, measured in tokens processed across your epochs. You pay monthly storage to keep the custom model. And then you pay to serve it, which for a custom model means Provisioned Throughput, because on-demand does not serve custom weights. That last point catches people. The fine-tune looked cheap, then serving it required a reserved MU billed around the clock, and the running cost dwarfed the training cost.
My rule before anyone fine-tunes: prove that prompt engineering, retrieval, and a larger base model cannot get you there first. We built the case for that ordering in the vendor-neutral GenAI series, and it holds doubly on Bedrock because the serving tail is a fixed monthly cost, not a per-call one.
Estimate the bill before you ship
Do not eyeball this. Put your real traffic numbers into a few lines of code and compare modes. Here is the estimator I hand to teams. It costs a workload three ways and refuses to guess a Provisioned Throughput rate, because that number depends on your model and commitment and should come from your account team.
# bedrock_cost.py estimate monthly Bedrock spend by pricing mode
IN_PER_M = 0.80 # Nova Pro on-demand input, USD per 1M tokens
OUT_PER_M = 3.20 # Nova Pro on-demand output, USD per 1M tokens
def monthly_cost(requests, in_tok, out_tok, mode='on_demand', pt_hourly=None):
per_req = (in_tok / 1_000_000) * IN_PER_M + (out_tok / 1_000_000) * OUT_PER_M
if mode == 'on_demand':
return requests * per_req
if mode == 'batch':
return requests * per_req * 0.5 # flat 50 percent off supported models
if mode == 'provisioned':
if pt_hourly is None:
raise ValueError('provisioned needs pt_hourly, confirm with your AWS account team')
return pt_hourly * 730 # 730 hours per month, per model unit
raise ValueError('unknown mode: ' + mode)
for m in ('on_demand', 'batch'):
print(m, round(monthly_cost(5_000_000, 2000, 500, m), 2))
print('provisioned', round(monthly_cost(0, 0, 0, 'provisioned', pt_hourly=24.0), 2))
Expected output at 5 million requests a month:
on_demand 16000.0
batch 8000.0
provisioned 17520.0Failure mode worth keeping: call the provisioned branch without a pt_hourly and it raises a ValueError on purpose, so nobody quietly ships a build that assumed a reserved rate they never confirmed. At 5 million requests, on-demand at 16,000 dollars still beats a single MU at 17,520, and batch at 8,000 wins outright if the job can wait. Change the token counts to yours and re-run before any pricing review.
What I would actually do
My take
Start every workload on on-demand. Move anything offline to batch on day one for the flat 50 percent. Turn on prompt caching wherever a big shared prefix repeats. Only reach for Provisioned Throughput when you need a capacity guarantee, predictable latency at peak, or you are serving a custom model, and prove the break-even with real numbers before committing to a term. Do not fine-tune to save money; the reserved serving tail usually erases the saving.
The through-line is that the mode follows the traffic shape. Bursty and unpredictable wants on-demand. Offline and bulk wants batch. Repeated context wants caching. Steady, guaranteed, or custom wants Provisioned Throughput. Get the shape right and the model rate becomes a second-order decision. Get it wrong and no model choice will save you, because you will be paying for idle reservations or full-price retries.
Next we leave pricing and get physical. Part 7 covers Trainium and Inferentia against GPUs, the silicon underneath these rates and the reason Nova can be priced the way it is.
References
Increase model invocation capacity with Provisioned Throughput, AWS docs
Amazon Nova pricing, AWS


DrJha