Per-App Bedrock Cost Tracking with Inference Profiles
Application inference profiles put cost allocation tags on Bedrock calls, turning one shared bill into per-team lines. The tag design is the hard part.

An application inference profile is a tagged wrapper around a model ARN, and it is the only thing standing between you and a Bedrock bill that says one number for the whole company. You create a profile that points at a model, attach cost allocation tags, and invoke the profile ARN instead of the model ID. The tags ride along to Cost Explorer and the Cost and Usage Report. That is the entire mechanism, and it takes an afternoon.
The afternoon is not the problem. The problem is that a tagging scheme is an organizational commitment, and most teams pick one in ten minutes and live with it for two years. So the API is worth twenty minutes of this post and the tag design is worth the rest.
The problem it solves
Without profiles, Bedrock usage shows up as Bedrock usage. You get spend by model and by region, which tells you that Claude Sonnet cost you a lot last month and nothing about which of your nine applications caused it. The default report cannot answer the only question finance ever asks, which is whose budget this comes out of. I wrote about the broader shape of this in Your LLM Bill Is an Observability Problem. Profiles are the specific control for the attribution half.
How it works
Create a profile pointing at a foundation model or a system-defined cross-region profile, with tags:
aws bedrock create-inference-profile \
--inference-profile-name "support-assistant-prod" \
--model-source copyFrom=arn:aws:bedrock:eu-central-1::foundation-model/anthropic.claude-sonnet-4-5-20250929-v1:0 \
--tags key=team,value=support key=app,value=assistant key=env,value=prodThen invoke the profile ARN wherever you passed a model ID:
response = client.converse(
modelId="arn:aws:bedrock:eu-central-1:123456789012:application-inference-profile/abc123",
messages=messages,
)Three operational details that are easy to miss:
- Profiles are model-specific. A profile wraps one model. Six apps times four models is twenty-four profiles. That multiplication is why your tag design matters more than it looks: you are not naming a resource, you are defining a grid.
- Tags are not retroactive. Activating a cost allocation tag in the Billing console tags spend from that point forward. Nothing you did last month gets labelled. Activate the tag keys before you need the data, not when someone asks for it.
- The grain is daily, per usage type. Profiles give you billed dollars in Cost Explorer and CUR at day granularity. They do not give you per-request cost. If you want per-request economics, that is application-side token logging, a different system with a different owner.
Designing the tag scheme
The trap is tagging what is easy to see instead of what someone can act on. Every tag key should answer a question a real person asks in a real meeting.
Four keys carry most organizations:
team: who pays. Match your existing cost center taxonomy exactly. If finance calls itcc-4471, do not inventplatform-eng; you will spend the next year maintaining a translation table nobody trusts.app: which workload. The unit you would actually turn off.env: prod, staging, dev. This is the one that pays for itself fastest, because the first genuinely surprising number in most Bedrock bills is how much dev costs.feature: optional, for apps where one feature can dominate spend. Use sparingly. Every extra key multiplies your profile count.
Deliberately not on the list: per-user tags. Do not create a profile per user. You will hit resource limits, and the maintenance is unbounded. For identity-level attribution, Bedrock supports IAM principal-based cost allocation, which attributes spend to the calling identity without a profile per person. Use profiles for the team and app grain, and IAM principal attribution when you need to know which human or service role drove the spike. They compose.
Make it structural
A tagging scheme that depends on discipline decays. Two controls make it hold.
First, create profiles in your IaC, next to the app that uses them, and pull tag values from the same variables that tag the rest of that app's resources. A profile created by hand in the console is a profile that will be tagged test forever.
Second, close the direct path. Once profiles exist, an app that calls a raw model ID produces untagged spend, and untagged spend is exactly the line item nobody claims. An IAM policy that denies bedrock:InvokeModel and bedrock:Converse on foundation-model ARNs while allowing them on application-inference-profile ARNs makes the tagged path the only path. This is the same instinct as scoping a role to a task, and I will not repeat the argument from IAM for LLM Apps: Least Privilege When the Caller Is a Model, only note that it applies to your bill as well as your blast radius.
Do that on day one. Retrofitting a deny policy onto six apps already calling model IDs is a migration with a change-freeze attached.
What you get, and what you still will not have
After a month of tagged data you can group Cost Explorer by team and see the split, filter to env=dev and find the batch job someone left running, and query CUR for cost per app per day and put it on a dashboard next to request volume. Anomaly detection gets useful too, because a budget alert on one app is signal where an alert on total Bedrock spend is noise.
What you still will not have: per-request cost, cost per customer in a multi-tenant app, and any idea whether the spend was worth it. The first is token logging. The second needs tenant context the billing system never sees, which is why multi-tenant attribution stays an application problem. The third is not a billing question at all. Profiles tell you where the money went. They have no opinion on whether it should have.
The takeaway
Application inference profiles turn an unattributable Bedrock bill into per-team, per-app lines for the cost of wrapping a model ARN. Activate the tag keys before you need history, keep the scheme to a few keys that match how your org actually budgets, create profiles in IaC, and deny the untagged path with IAM so attribution does not depend on anyone remembering. The API is an afternoon. The tag design outlives the people who chose it.
Read this next
- Your LLM Bill Is an Observability Problem, on why token spend behaves like telemetry rather than a line item.
- Multi-Tenant LLM Apps: Isolating Customers on a Shared Model, on the attribution problem profiles cannot reach.
The general cost-allocation discipline this borrows from, tagging strategy across an AWS estate, is in the field notes at ercan.cloud. The hub is at ercanermis.com.
More from Ercan
Two more sites, same author, different ground.
Cloud, AWS, EKS, Terraform, platform engineering.
Field notes from production systems. EKS, IAM, Terraform at organization scale, observability, cost optimization.
Visit ercan.cloud →The hub. About, consulting, contact.
Personal hub for both writing tracks. Who I am, how the consulting works, how to reach me.
Visit ercanermis.com →