Tokenomics at scale: Track and cap Amazon Bedrock spend per IAM principal with CUR 2.0 and AWS Budgets An AWS blog post details a code-free method for attributing and capping Amazon Bedrock generative AI spend per IAM principal using IAM principal attribution, AWS Cost and Usage Reports (CUR) 2.0 or Cost Explorer, and AWS Budgets with budget actions that apply a Deny IAM policy when a threshold is crossed. The approach contrasts with the prior Jamf-built enforcement loop on IAM Identity Center, Amazon Athena over Bedrock model invocation logs, and AWS Lambda, which AWS says gives near-real-time control but requires code the customer owns and operates. The post positions the AWS-native path as delivering per-identity cost reporting and an automatic guardrail for organizations expanding AI access. Artificial Intelligence https://aws.amazon.com/blogs/machine-learning/ Tokenomics at scale: Track and cap Amazon Bedrock spend per IAM principal with CUR 2.0 and AWS Budgets Generative AI spend is hard to attribute. Before an organization expands AI access, CFOs and CTOs usually want three answers: what do we spend per person or per team, can we cap it, and how much work does it take to get there. In our previous post, Tokenomics at Scale: How Jamf Built Real-Time Spend Enforcement for Amazon Bedrock https://aws.amazon.com/blogs/machine-learning/tokenomics-at-scale-how-jamf-built-real-time-spend-enforcement-for-amazon-bedrock/ , we explained a custom enforcement loop built on AWS IAM Identity Center https://aws.amazon.com/iam/identity-center/ , Amazon Athena https://aws.amazon.com/athena/ over Amazon Bedrock https://aws.amazon.com/bedrock/ model invocation logs https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html , and AWS Lambda https://aws.amazon.com/lambda/ . This approach gives near-real-time control, but it requires code you then own and operate. This post shows how to get per-identity Amazon Bedrock cost visibility and enforceable spend limits using only AWS-native features, with no application code to write for the common case. The approach relies on three things: IAM principal attribution https://docs.aws.amazon.com/bedrock/latest/userguide/cost-mgmt-iam-principal-tracking.html , which Amazon Bedrock records automatically; AWS Cost and Usage Reports https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-cur2.html CUR 2.0 or AWS Cost Explorer https://aws.amazon.com/aws-cost-management/aws-cost-explorer/ for reporting; and AWS Budgets https://aws.amazon.com/aws-cost-management/aws-budgets/ with budget actions for enforcement. By the end, you will have per-identity cost reporting and an automatic guardrail that restricts Amazon Bedrock access when a threshold is crossed. Solution overview The solution has three parts: attribute, report, and enforce. Attribute. Amazon Bedrock captures the AWS Identity and Access Management IAM principal identity, the IAM user https://docs.aws.amazon.com/IAM/latest/UserGuide/id users.html or role https://docs.aws.amazon.com/IAM/latest/UserGuide/id roles.html , for every inference request. This happens automatically, with no change to your Amazon Bedrock model inference calls. If several people share one role, you add per-user detail with session tags passed at role assumption time. If each person or application has its own role, principal tags on the role are enough. Report. Activate those tags as cost allocation tags, then read the data either in Cost Explorer for a console-only view, or in a CUR 2.0 data export for detailed line-item analysis and SQL queries. Enforce. Create an AWS Budget scoped to Amazon Bedrock and filtered to one identity or tag value, then attach a budget action https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-controls.html that applies a Deny IAM policy when the threshold is crossed. The following sections show each part in more detail, alongside the implementation steps. Prerequisites To deploy this solution, you need: - An AWS account https://aws.amazon.com/account/ with Amazon Bedrock model access enabled. - Permissions to tag IAM principal https://docs.aws.amazon.com/bedrock/latest/userguide/cost-mgmt-iam-principal-tracking.html cost-mgmt-iam-principal-tracking-principal-types , activate cost allocation tags https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html , create data exports https://docs.aws.amazon.com/cur/latest/userguide/dataexports-create.html , and create budgets and budget actions. - Amazon Bedrock accessed through IAM roles or IAM users. - AWS Command Line Interface https://aws.amazon.com/cli/ AWS CLI configured with appropriate credentials. - A CUR 2.0 data export and an Amazon Simple Storage Service https://aws.amazon.com/s3/ Amazon S3 bucket to receive it. optional, for detailed line-item analysis . - Amazon Athena. optional, for querying the export . AWS Billing Console https://aws.amazon.com/aws-cost-management/aws-billing/ access is managed separately from most IAM permissions. Confirm you have it before starting. Walkthrough Before configuring anything, check what you already have. Amazon Bedrock records caller identity for every inference request automatically. Open Cost Explorer, filter Service to Amazon Bedrock, and group by the available identity or tag dimension. For accounts where each application or person already uses a distinct IAM role, this may be all the visibility you need. To configure additional visibility: - Step 1 gives you identity-level visibility. - Steps 2 through 4 add tag dimensions and detailed reporting. - Step 5 adds enforcement. Step 1: Decide how identity maps to your users How you tag depends on how your IAM principals are organized. One role per person or per application. Attach principal tags directly to each IAM role or user. These are static and apply to every request from that principal. Use the IAM console, or the AWS CLI: A shared role used by several people, or a gateway. Principal tags cannot distinguish users on a shared role, because every session carries the same tags. Use session tags instead, passed when the role is assumed. Session tags are dynamic and can vary per session. If a session tag and a principal tag share a key, the session tag wins for that session. The role’s trust policy must allow sts:TagSession . Session tags can be passed three ways: - sts:AssumeRole with --tags , for a gateway assuming a role per user or tenant. - AssumeRoleWithWebIdentity , with tags in the https://aws.amazon.com/tags claim of the OpenID Connect OIDC ID token this is a claim name, not a URL you browse to . - AssumeRoleWithSAML , by mapping PrincipalTag: attributes in the identity provider’s Security Assertion Markup Language SAML assertion. If your organization already captures a claim like saml:sub for other purposes, that alone does not make it available here. Your identity provider must separately map that attribute to a PrincipalTag: SAML attribute statement, and the role’s trust policy must allow sts:TagSession , before it flows through as a session tag. The two integrations draw from the same SAML assertion but are configured independently. Common tag keys are user, team, Department, CostCenter, and Environment. You can apply up to 50 principal or session tags per IAM user or role. Step 2: Activate cost allocation tags Tags do not appear in billing data until you activate them. 1. Open the AWS Billing and Cost Management Console https://aws.amazon.com/aws-cost-management/billing-and-cost-management-console-home/ . 2. Choose Cost allocation tags . 3. Filter by type IAM principal . 4. Select your tag keys and choose Activate . In an AWS Organization https://docs.aws.amazon.com/organizations/latest/userguide/orgs introduction.html , activate IAM principal cost allocation tags in the management account https://docs.aws.amazon.com/managedservices/latest/userguide/management-account.html payer . Member accounts cannot activate them independently. Two things to expect: - A tag key only appears in this list after the principal has made at least one Amazon Bedrock call, so make a test call first if the list looks empty. - It might take up to 24 hours for a newly applied tag key to appear for activation, then up to another 24 hours after you activate it before it begins populating billing data. Activation does not apply retroactively by default, so activate tags before you need the data. Step 3: Create a CUR 2.0 data export that includes caller identity Skip this step if Cost Explorer is enough for your reporting. 1. In the Billing and Cost Management console, choose Data Exports . 2. Choose Create and create a CUR 2.0 Standard export. 3. Under Additional export content , select Include caller identity IAM principal allocation data . 4. Under Time granularity , select Hourly. 5. Under Report data integration , select Amazon Athena . This sets the file format to Parquet and, importantly, delivers a setup script to your S3 bucket alongside the export data. 6. Choose the destination Amazon S3 bucket. 7. Run the delivered setup script or the Glue crawler/DDL it defines once. This is what actually creates the Glue Data Catalog table you’ll query in Step 4. The preceding console flow does not create it for you automatically. If you already have a CUR 2.0 export created before enabling identity attribution, it will not include identity data retroactively. Create a new export with the caller identity option selected. In the export, principal and session tags appear as columns prefixed iamPrincipal/ , and resource tags as resourceTags/ . For example, a tag key team appears as iamPrincipal/team . AWS publishes a ready-made query set for this exact pattern in aws-samples/sample-cur-iam-principal-bedrock-tracking https://github.com/aws-samples/sample-cur-iam-principal-bedrock-tracking . Step 4: Read the data The following diagram compares the two ways to read the data: a console-only path through Cost Explorer, and a SQL path over the CUR 2.0 export with Amazon Athena. Console path, no custom code. Cost Explorer, filtered to Amazon Bedrock and grouped by your tag key, gives per-team or per-user spend as a chart and table. This covers most recurring reporting needs and requires no query authoring. SQL path, low code. Point Amazon Athena at the CUR 2.0 export to group spend by iamPrincipal/team and usage type: Things to note: - Service code : Amazon Bedrock spend can be recorded under more than one product servicecode value, for example, AmazonBedrock and AmazonBedrockService . - Table name : The table name cur2 view is whatever the setup script from Step 3 named it when it created the Glue table. Check the script or your Glue catalog if it differs. Column names match the CUR 2.0 Parquet schema regardless of table name. - Billing-period column. Confirm how your export exposes the period. Some exports use billing period YYYY-MM . Others partition on a start-date or year/month column. Two notes worth carrying into any query you write. - Count all token types : Amazon Bedrock bills four token types, each at a different rate: input, output, cache read, and cache write. Each is a separate line item with its own usage type and unit price, so summing only input and output undercounts. The gap is largest for workloads that use prompt caching heavily. Refer to the AWS document Understanding Amazon Bedrock pricing in CUR https://docs.aws.amazon.com/bedrock/latest/userguide/cost-mgmt-understanding-cur-data.html cost-mgmt-cur-pricing for the latest information. - Match the rate to the line item, not the model : Amazon Bedrock pricing in CUR is determined by three things: the token type, the service tier, and whether the request was routed through cross-Region inference. In-Region and cross-Region requests are priced differently, and service tier is reflected in the usage type as well. The usage type carries a suffix indicating cross-Region routing and service tier, so if your workloads mix these, match the rate to each line item rather than applying one rate per model. Refer to the CUR usage type examples https://docs.aws.amazon.com/bedrock/latest/userguide/cost-mgmt-understanding-cur-data.html cost-mgmt-cur-usage-type-examples for examples. Step 5: Add enforcement with AWS Budgets and budget actions AWS Budgets performs the attach, so there is no custom code for this workflow. Budget acti