Dev.to · 13 min read

Track Amazon Bedrock Costs per Team: 3 Methods Compared

Track Amazon Bedrock Costs per Team: 3 Methods Compared

Your Bedrock bill shows models, Regions, and tokens, with no team names. Here is how to split it by team with IAM principals, application inference profiles, or Projects, and how to put a budget on each team. By Evgeny Anikiev, AWS-certified DevOps engineer with 10+ years running build automation, CI/CD, and Kubernetes in production. Checked against the Amazon Bedrock documentation and AWS announcements on October 26, 2026. TL;DR: Amazon Bedrock cost allocation now works three ways, and each one charges inference cost to a team. IAM principal cost allocation charges each request to the IAM user or role that made it. If each team calls Bedrock with its own role, it needs no code change. Application inference profiles carry tags for InvokeModel and Converse calls on the bedrock-runtime endpoint. Projects carry tags for Responses and Chat Completions calls on the bedrock-mantle endpoint. Start with IAM principals, add profiles or Projects where several teams share one role, and put an AWS Budget on each team's tag. Cost Anomaly Detection does not cover AWS Marketplace charges, so do not rely on it alone. What this post covers: Why the default Bedrock bill can't answer "which team spent this". The three methods side by side, with the endpoints each one covers. Setup commands for each method. A per-team budget with the AWS CLI. The limits: delays, the payer account, and what CUR does not show. Why doesn't my Bedrock bill show which team spent the money? By default, Cost Explorer and the Cost and Usage Report (CUR) group Bedrock spend by model, Region, and token type. A usage type such as USE1-Claude4.6Sonnet-input-tokens tells you what was used and where, but nothing on that line says who sent the request. When three teams share one AWS account and one model, their spend lands on the same lines. You can't fix this by tagging the model. On-demand foundation models are AWS-owned resources, so there is nothing of yours to tag. AWS added three ways around that, and each one covers different APIs. In May 2026, The Register reported on a reader who ran Claude Opus through Bedrock and received a $30,141.33 bill for April. Cost Anomaly Detection was set up and never fired. AWS told the publication that AWS Marketplace charges are not supported by Cost Anomaly Detection, and that AWS Budgets does cover Bedrock spend billed through Marketplace. A budget on that spend is the alert that would have covered it. Which Bedrock cost allocation method should I use? Use IAM principal cost allocation first, because it needs no code change when each team or application already has its own IAM role. Add application inference profiles when several teams share one role and call InvokeModel or Converse. Use Projects for apps on the OpenAI-compatible Responses or Chat Completions APIs. You can run all three in one account. The three methods, side by side: What cost is charged to: IAM principals charge the IAM user or role that made the call. Application inference profiles charge the profile the app called. Projects charge the project ID the app sent. Endpoints and APIs: IAM principals cover bedrock-runtime (since April 9, 2026) and bedrock-mantle (since August 11, 2026). Application inference profiles cover InvokeModel and Converse on bedrock-runtime. Projects cover Responses and Chat Completions on bedrock-mantle. Code change: IAM principals need none if each team has its own role. Profiles need the app to call the profile ARN in place of the model ID. Projects need the app to send a project ID. Where you see it: IAM principal data needs a CUR 2.0 export with caller identity turned on, and principal tags also show in Cost Explorer. Profile and Project tags show in Cost Explorer, classic CUR, and CUR 2.0. Scaling limit: IAM principals and session tags allow up to 50 tags per user or role. Application inference profiles are tied to one model, so you need one profile per model, team, and tag set. Projects allow up to 1,000 per account and are not tied to a model. Method 1: How do I allocate Bedrock costs by IAM role? Tag the IAM roles and users that call Bedrock and activate those tags in the management account. Then turn on caller identity data in a CUR 2.0 export. Bedrock records the caller's ARN on each CUR line and copies the role's tags with an iamPrincipal/ prefix. 1. Tag each role that calls Bedrock. One role per team or per application keeps this simple: aws iam tag-role \ --role-name support-agent-prod \ --tags Key=team,Value=support Key=cost-center,Value=cc-1042 2. Pass session tags for shared roles. When one role serves many teams or tenants, pass tags when the caller assumes the role. A session tag overrides a principal tag with the same key for that session: aws sts assume-role \ --role-arn arn:aws:iam::123456789012:role/bedrock-shared \ --role-session-name tenant-acme \ --tags Key=tenant,Value=acme The role's trust policy must allow sts:TagSession for this to work. Federated users from an identity provider such as Okta or Microsoft Entra ID can carry session tags the same way. 3. Activate the tags. In the Billing and Cost Management console, open Cost allocation tags, select the iamPrincipal/ tags, and choose Activate. Do this from the management (payer) account. Member accounts can't activate them. A tag only appears in the list after that principal has made at least one Bedrock call. 4. Turn on caller identity in CUR 2.0. In Data Exports, create a CUR 2.0 export and select Include caller identity (IAM principal) allocation data. Legacy CUR does not carry these fields, and existing exports don't pick up identity data for past periods. 5. Query it. CUR 2.0 adds a line_item_iam_principal column with the caller's ARN, such as arn:aws:sts::123456789012:assumed-role/support-agent-prod/session-123. In Athena, group by it: SELECT line_item_iam_principal, line_item_product_code, ROUND(SUM(line_item_unblended_cost), 2) AS cost_usd FROM cur2_export WHERE line_item_iam_principal '' AND line_item_usage_start_date >= TIMESTAMP '2026-10-01 00:00:00' GROUP BY 1, 2 ORDER BY cost_usd DESC; Replace cur2_export with your export's table name. In Cost Explorer, principal tags appear under the IAM category of the Tags filter. Method 2: How do I tag Bedrock usage with application inference profiles? An application inference profile is a copy of a model ID that you own and can tag. Create one per team and model, then have each team's app call its profile ARN. The profile's tags go onto the billing record for every request made through it. 1. Create the profile. The source can be a foundation model or a cross-Region (system-defined) inference profile: aws bedrock create-inference-profile \ --inference-profile-name support-agent-gpt-oss-120b \ --model-source copyFrom=arn:aws:bedrock:us-east-1::foundation-model/openai.gpt-oss-120b-1:0 \ --tags key=team,value=support key=cost-center,value=cc-1042 The response returns inferenceProfileArn. 2. Call the profile ARN in place of the model ID: import boto3 bedrock = boto3.client("bedrock-runtime", region_name="us-east-1") response = bedrock.converse( modelId="arn:aws:bedrock:us-east-1:123456789012:inference-profile/abc123example", messages=[{"role": "user", "content": [{"text": "Summarize ticket 4821"}]}], ) 3. Activate the tags (team, cost-center) in Cost allocation tags, the same as in Method 1. Application inference profiles don't work with the Responses or Chat Completions APIs on either endpoint. A request to those APIs that names a profile is rejected with a 400 error. Profiles also add up, since three teams on two models need six profiles. Keep them in Terraform or CloudFormation so the list stays readable. Method 3: How do I track Bedrock costs with Projects? Projects are the tagging method for the bedrock-mantle endpoint, which serves the OpenAI-compatible Responses and Chat Completions APIs. Create a project per team or application, tag it, and have the client send the project ID. A project is not tied to a model, so one project covers every model the team calls. You manage projects through the Projects API under the mantle base URL. POST /organization/projects with a name and tags creates a project. POST /organization/projects/{id} with add_tags or remove_tag_keys changes its tags. There is no operation that replaces the whole tag set at once. The client sends the project ID with each request. With the OpenAI Python SDK: from openai import OpenAI client = OpenAI(project="proj_123") # base_url and API key for bedrock-mantle set as usual With plain HTTP, send the header OpenAI-Project: proj_123. Requests without a project ID go to your account's default project, which can't be tagged. An archived project rejects new requests and keeps its metrics for 30 days. How do I set a Bedrock budget per team? Create one AWS Budget per team with a tag filter. Budgets covers Bedrock spend billed through AWS Marketplace, which Cost Anomaly Detection does not. Use the tag key exactly as it appears in Cost Explorer's tag list. aws budgets create-budget \ --account-id 123456789012 \ --budget '{ "BudgetName": "bedrock-support-monthly", "BudgetLimit": {"Amount": "2000", "Unit": "USD"}, "TimeUnit": "MONTHLY", "BudgetType": "COST", "FilterExpression": { "Tags": {"Key": "team", "Values": ["support"], "MatchOptions": ["EQUALS"]} }, "Metrics": ["UnblendedCost"] }' \ --notifications-with-subscribers '[{ "Notification": { "NotificationType": "FORECASTED", "ComparisonOperator": "GREATER_THAN", "Threshold": 80, "ThresholdType": "PERCENTAGE" }, "Subscribers": [{"SubscriptionType": "EMAIL", "Address": "support-leads@example.com"}] }]' A forecast alert at 80% gives the team warning before the month ends. Add a second notification of type ACTUAL at 100% for the hard line. To see all teams at once, group Cost Explorer by the same tag: aws ce get-cost-and-usage \ --time-period Start=2026-10-01,End=2026-11-01 \ --granularity MONTHLY \ --metrics UnblendedCost \ --group-by Type=TAG,Key=team What can't Bedrock cost allocation tell you? All three methods report cost per team per day or per hour. None of them gives cost per request or per prompt. Plan around these limits before you promise finance a number: Delay: Tags take up to 24 hours to appear in Cost Explorer and CUR after activation. AWS's launch blog says 24 to 48 hours. Not retroactive: Cost allocation tags only apply from activation onward. Spend before that stays untagged. Payer account only: Tag activation happens in the management account. If you're a team in a member account, ask whoever owns billing. No per-request cost: CUR rows are aggregated by usage type and time period, with no request ID. For per-request or per-prompt cost, use model invocation logs and join them to CUR at the model and usage-type level. Session tags are not written to invocation logs. STS limits: If you pass a session tag per tenant, every tenant switch is an AssumeRole call. The default STS quota is 500 AssumeRole calls per second per account. Marketplace alerts: Cost Anomaly Detection does not support AWS Marketplace charges. Check how your model's charges are billed, and use Budgets for alerts. Worked example: three teams in one Bedrock account A company runs three AI workloads in one AWS account: The support agent runs on EKS under the IAM role support-agent-prod and calls Converse. The role gets team=support. That is Method 1, with no code change. The data science team signs in through Okta and runs notebooks against several models. Their identity provider passes team=data-science as a session tag. That is Method 1 again, with no code change. The internal chatbot is built on the OpenAI SDK and calls the Responses API on bedrock-mantle. It gets a project tagged team=platform. That is Method 3, with one line of client config. Application inference profiles enter only if the support agent and a second app later share one role. Each team gets a budget filtered on team. Finance gets one Cost Explorer view grouped by team, with every Bedrock dollar assigned to a team. FAQ Can I tag an Amazon Bedrock foundation model directly? No. On-demand foundation models belong to AWS, so you can't tag them. Tag the IAM principal that calls the model, call it through a tagged application inference profile, or send a tagged project ID on bedrock-mantle. How long until Bedrock cost allocation tags show up in Cost Explorer? Up to 24 hours after you activate the tags. AWS's launch blog says 24 to 48 hours. IAM principal tags only appear after that principal has made at least one Bedrock call. Tags don't apply to spend from before activation. Do I need CUR 2.0 for Bedrock cost allocation by IAM role? Yes, for line-item caller data. The line_item_iam_principal column and principal tag data exist only in CUR 2.0 exports with "Include caller identity (IAM principal) allocation data" selected. Legacy CUR does not have them. Do application inference profiles work with cross-Region inference? Yes. Create the application inference profile from a cross-Region (system-defined) inference profile in place of a single-Region foundation model. Requests then route across Regions, and the profile's tags still apply. Can I get the cost of a single Bedrock request? Not from CUR or Cost Explorer. Both aggregate by usage type over an hour or a day. Use model invocation logs for token counts per request, multiply by the model's price, and reconcile the total against CUR. Does AWS Cost Anomaly Detection catch Bedrock cost spikes? Not when the charges are billed through AWS Marketplace. AWS told The Register in May 2026 that Cost Anomaly Detection does not support Marketplace charges, after a reader's $30,141.33 Claude bill raised no alert. AWS Budgets does cover Bedrock spend billed through Marketplace, so set a budget per team as well. How do I split Bedrock costs per tenant in a SaaS product? Pass the tenant as a session tag when your service assumes the Bedrock role. On bedrock-mantle, you can give each tenant its own project instead. Watch the STS quota of 500 AssumeRole calls per second if you assume a role per request. Related reading Bedrock vs Self-Hosted LLMs on EKS: The Break-Even Math: when your own GPUs cost less than per-token pricing. Migrating AI Agents to AWS: 15 Bedrock and AgentCore Checks: a readiness score for AI teams moving agents to Bedrock and AgentCore, cost tracking included. Cut AWS NAT Gateway Costs: 7 Fixes for Platform Teams: model weights and container images pulled through a NAT gateway pay $0.045 per GB in US East. EKS 1.37 Upgrade Checklist: What Breaks and How to Test It: for the clusters your Bedrock callers run on. Sources Application inference profiles (Amazon Bedrock User Guide) Create an application inference profile Projects (Amazon Bedrock User Guide) Understanding your Amazon Bedrock Cost and Usage Report data Amazon Bedrock now supports cost allocation by IAM user and role (April 9, 2026) Amazon Bedrock expands IAM principal cost allocation to the bedrock-mantle endpoint (August 11, 2026) Introducing granular cost attribution for Amazon Bedrock (AWS Machine Learning Blog, April 17, 2026) Bedrock and a hard place: Claude adventure leaves AWS user staring down $30K invoice (The Register, May 14, 2026) AWS CLI: bedrock create-inference-profile AWS CLI: budgets create-budget Can't tell which team spent last month's Bedrock bill? I set up cost allocation and budgets for AI teams on AWS at DevOps Cloud Consult. Send me your Bedrock line from Cost Explorer and I'll map which method fits each workload. Get one AWS cost fix every two weeks: subscribe on Substack.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More AI & Machine Learning News