Provisioned Throughput & On-Demand Inference
Capacity models for predictable-latency vs bursty workloads.
Busca en todas las páginas de la documentación
Capacity models for predictable-latency vs bursty workloads.
Bedrock offers two ways to pay for and reserve inference capacity. On-demand bills per token on shared infrastructure with no commitment - the default nearly everyone should start with. Provisioned Throughput reserves dedicated capacity ("model units") for a model, giving steady, predictable performance at high volume, billed by the hour. The inference call is the same either way; what changes is the modelId you pass and how you are billed.
Cost warning: Provisioned Throughput is a real financial commitment. Reserved model units bill by the hour (often with a required term) whether or not you send any requests. Do not create it to experiment - use on-demand for development and delete provisioned units you are not using.
Quick-reference recipe card - copy-paste ready.
# --- Python (boto3) ---
import boto3
# On-demand: just call the model id. No reservation, pay per token.
brt = boto3.client("bedrock-runtime", region_name="us-east-1")
resp = brt.converse(
modelId="amazon.nova-lite-v1:0",
messages=[{"role": "user", "content": [{"text": "Hi"}]}],
)
print(resp["output"]["message"]["content"][0]["text"])// --- TypeScript (AWS SDK v3) ---
import { BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime";
// On-demand: just call the model id. No reservation, pay per token.
const brt = new BedrockRuntimeClient({ region: "us-east-1" });
const resp = await brt.send(new ConverseCommand({
modelId: "amazon.nova-lite-v1:0",
messages: [{ role: "user", content: [{ text: "Hi" }] }],
}));
console.log(resp.output?.message?.content?.[0]?.text);When to reach for each:
Provisioning is a control-plane action on the bedrock client (not bedrock-runtime). You create a provisioned model, wait until it is InService, then invoke it by passing its ARN as the modelId.
# --- Python (boto3) ---
import boto3
bedrock = boto3.client("bedrock", region_name="us-east-1") # control plane
brt = boto3.client("bedrock-runtime", region_name="us-east-1") # data plane
# 1. Reserve capacity (BILLS BY THE HOUR from creation). modelUnits = throughput units.
created = bedrock.create_provisioned_model_throughput(
provisionedModelName="orders-assistant-pt",
modelId="amazon.nova-lite-v1:0", # base model id to reserve capacity for
modelUnits=1,
)
arn = created["provisionedModelArn"]
# 2. Wait until it is ready (poll status until "InService").
status = bedrock.get_provisioned_model_throughput(provisionedModelId=arn)["status"]
print("status:", status)
# 3. Invoke it: pass the ARN as modelId. The inference call is otherwise identical.
resp = brt.converse(
modelId=arn,
messages=[{"role": "user", "content": [{"text": "Ping"}]}],
)
print(resp["output"]["message"]["content"][0]["text"])
# 4. Clean up when done so it stops billing.
bedrock.delete_provisioned_model_throughput(provisionedModelId=arn)// --- TypeScript (AWS SDK v3) ---
import {
BedrockClient, CreateProvisionedModelThroughputCommand,
GetProvisionedModelThroughputCommand, DeleteProvisionedModelThroughputCommand,
} from "@aws-sdk/client-bedrock";
import { BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime";
const bedrock = new BedrockClient({ region: "us-east-1" }); // control plane
const brt = new BedrockRuntimeClient({ region: "us-east-1" }); // data plane
// 1. Reserve capacity (BILLS BY THE HOUR from creation).
const created = await bedrock.send(new CreateProvisionedModelThroughputCommand({
provisionedModelName: "orders-assistant-pt",
modelId: "amazon.nova-lite-v1:0", // base model id to reserve capacity for
modelUnits: 1,
}));
const arn = created.provisionedModelArn!;
// 2. Wait until it is ready (poll status until "InService").
const desc = await bedrock.send(new GetProvisionedModelThroughputCommand({ provisionedModelId: arn }));
console.log("status:", desc.status);
// 3. Invoke it: pass the ARN as modelId. The inference call is otherwise identical.
const resp = await brt.send(new ConverseCommand({
modelId: arn,
messages: [{ role: "user", content: [{ text: "Ping" }] }],
}));
console.log(resp.output?.message?.content?.[0]?.text);
// 4. Clean up when done so it stops billing.
await bedrock.send(new DeleteProvisionedModelThroughputCommand({ provisionedModelId: arn }));What this demonstrates:
bedrock control-plane operation; running prompts stays on bedrock-runtime.modelUnits is the amount of reserved throughput; more units cost more and serve more.InService, you invoke by passing the provisionedModelArn as modelId - the inference code is unchanged.On-demand is the default serving mode. You call a base model id, share pooled capacity with other tenants, and pay per input and output token. There is no reservation and nothing to tear down, which is why it suits development and variable traffic. The trade-offs are that throughput is subject to account-level request quotas and can be throttled under contention, and per-token latency is not guaranteed. Modern on-demand access to some models also runs through cross-region inference profiles (ids like us.anthropic.claude-...) rather than a bare model id.
Provisioned Throughput reserves dedicated capacity for a specific model, measured in model units, each providing a defined level of tokens-per-minute. Because the capacity is yours, latency is steadier and throughput is guaranteed up to what you bought - valuable for high, sustained production load. It is billed hourly, frequently with a commitment term (for example, monthly or longer), and no-commitment hourly options are more expensive per hour. Serving a customized (fine-tuned) model generally requires Provisioned Throughput as well.
The decision is about volume, steadiness, and latency guarantees, not features - the API surface is identical.
| Dimension | On-Demand | Provisioned Throughput |
|---|---|---|
| Billing | Per token | Per hour per model unit (often term-committed) |
| Commitment | None | Hourly, usually with a term |
| Capacity | Shared, quota-limited | Dedicated, reserved |
| Latency | Best-effort | Predictable |
| Best for | Dev, spiky, low/mid volume | Steady high-volume production |
| Idle cost | Zero | Still billing |
A common path: build and launch on-demand, watch real traffic and throttling, and switch to provisioned only once sustained volume makes the reserved capacity cheaper and the latency guarantee worthwhile.
bedrock control-plane op, not bedrock-runtime. Fix: use the bedrock client to create, the runtime client to invoke.InService - a freshly created provisioned model is not immediately ready. Fix: poll GetProvisionedModelThroughput until status is InService.DeleteProvisionedModelThroughput and audit with ListProvisionedModelThroughputs.ListInferenceProfiles and use the profile id where required.| Approach | Use When | Don't Use When |
|---|---|---|
| On-demand (default) | Dev, spiky, low/moderate volume | You need guaranteed capacity and steady latency |
| Provisioned Throughput | Sustained high-volume production | Traffic is bursty or you are still experimenting |
| Retries + backoff on on-demand | Occasional throttling under load | Throttling is constant (then provision) |
| Smaller/cheaper model | Cost is the constraint | The task genuinely needs a larger model |
On-demand. It has no commitment, bills per token, and suits development and variable traffic. Move to Provisioned Throughput only when sustained volume and latency needs justify it.
Call CreateProvisionedModelThroughput on the bedrock control-plane client with a provisionedModelName, base modelId, and modelUnits. It returns a provisionedModelArn.
Pass the returned provisionedModelArn as the modelId in your normal converse/invoke_model call. The inference code is otherwise identical to on-demand.
Yes. It bills by the hour (often with a term commitment) from creation, whether or not you send requests. Delete unused provisioned models to stop the charge.
On-demand shares capacity and is subject to account request quotas. Add retries with exponential backoff, request a quota increase, or move to Provisioned Throughput for guaranteed capacity.
The unit of reserved throughput for Provisioned Throughput, each providing a defined tokens-per-minute capacity. Buy more units for more throughput; each adds to the hourly cost.
Generally yes. Serving a customized/fine-tuned model typically requires Provisioned Throughput rather than on-demand. Check the current requirements for your model.
No. Only the modelId (a base id/inference profile vs a provisioned ARN) and the billing model differ. Converse and InvokeModel calls are otherwise the same.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+). Bedrock model IDs and inference profiles are region/version-specific - verify against the current Bedrock catalog at build time.
Revisado por Chris St. John·Última actualización: 24 jul 2026