From Aryan Vatsa | Product & Market Analysis
GPU and Model Cost Allocation: What AWS, Azure and Google Bills Can Attribute
On this page
GPU cost allocation on the three big clouds is no longer a blank. Since April 2026, Amazon Bedrock can attribute model spend to the IAM role that made the call, but only per usage type per day. Google lets you put labels on every Vertex AI request, but caps each label key at 1,000 unique values for the life of the billing account. Azure splits Foundry spend by model deployment. We read the vendor documentation for 7 common allocation tasks across all three clouds. Native billing fully handles 7 of the 21 cells.
Key takeaways
- Every cloud now attributes managed model spend to an application. AWS uses application inference profiles or Projects, Azure splits cost by model deployment, and Google forwards request labels on pay-as-you-go Vertex AI traffic to Cloud Billing.
- Only AWS attributes model spend to the caller in the bill itself. Bedrock writes the IAM principal ARN into a CUR 2.0 column, at a finest grain of one usage type per day, and the tags are not retroactive.
- Committed capacity breaks per-team attribution on all three clouds. Vertex AI silently ignores request labels on Provisioned Throughput, and Azure bills provisioned deployments per PTU per hour regardless of tokens consumed.
- Per-request cost does not exist in any native bill. Token counts per request live in logs or gateway metrics: Bedrock invocation logs, Azure API Management token metrics, and Vertex AI request metadata logs.
Who this is for: the head of a platform or FinOps team who runs AI workloads on more than one cloud and has to produce a single chargeback report.
The short answer: AWS, Azure and Google can all split managed model spend by application, and AWS can also split it by IAM caller. None of them can price a single request in the bill. GPU-hours by Kubernetes namespace are available on EKS and GKE with caveats, and least documented for GPUs on AKS.
This post sits next to our earlier reading of what the State of FinOps 2026 says about AI spend tooling. This one stays inside the three native billing products.
AWS Bedrock cost tracking: profiles, Projects and IAM principals
AWS now offers three separate ways to attribute Bedrock spend, and which one works depends on the endpoint your code calls.
Application inference profiles and Projects split spend by workload
An application inference profile is a resource you create per application or team, tag, and then pass as the model ID. The Bedrock user guide says you can "attach tags to an application inference profile to track costs when you submit on-demand model invocation requests". You pass the profile ARN in InvokeModel, Converse and their streaming variants.
The catch is the endpoint. Bedrock now runs two inference endpoints, bedrock-runtime and the newer bedrock-mantle. AWS's IAM principal cost tracking page carries a comparison table showing that application inference profiles work only on bedrock-runtime. Projects, the construct AWS marks as recommended, work only on bedrock-mantle with the Responses and Chat Completions APIs. If half your services call one endpoint and half the other, you need both constructs.
A team that standardises on inference profiles and then moves a service to bedrock-mantle loses its application attribution silently. Nothing errors.
IAM principal attribution reaches the caller, at daily grain
On 9 April 2026 AWS announced cost allocation by IAM principal for Bedrock, in CUR 2.0 and Cost Explorer. On 11 August 2026 it extended the feature to bedrock-mantle. The AWS Billing guide says AWS records the caller identity for each Bedrock call in a line_item_iam_principal column, and tags on that principal appear with an iamPrincipal/ prefix.
Three limits matter in practice. The finest grain is per usage type per day, with no per-request cost. Tags are not retroactive, so only spend after activation is attributed. And tags are activated from the payer account, not a member account.
The same page recommends Projects for application-level attribution and IAM principals for user-level attribution in the same account. It also notes that session tags suit "LLM gateways that proxy requests on behalf of multiple users or tenants". We think that is the strongest design on any of the three clouds: a gateway that assumes a role with session tags per tenant gets tenant-level cost into the bill. Enabling it multiplies CUR rows by the number of calling identities per model.
Per-request token counts live elsewhere. Bedrock model invocation logging records input and output token counts and the caller's ARN for every request. It is disabled by default and captures only bedrock-runtime calls. So the newer endpoint, the one Projects need, is currently invisible to the only per-request record AWS offers.
Azure OpenAI cost management: deployments, project tags and the gateway
Azure's model is the most resource-shaped of the three. Cost attaches to the Foundry resource and its model deployments, and finer attribution comes from Azure API Management rather than from Cost Management.
Deployment and project splits in Cost Analysis
Microsoft's Foundry cost management page, updated in October 2026, says you can add "deployment tags, user-defined tags" as filters to segment costs by model deployment. It also describes a preview feature: for supported models, project usage is automatically tagged with a project tag. That covers models sold by Azure, including Azure OpenAI, and not models served through Azure Marketplace.
Azure OpenAI appears under the Cognitive Services service name, so the right filter is the Azure OpenAI service tier rather than a service filter. Partner and community model meters land under the resource group rather than the Foundry resource, so a cost view scoped to the resource undercounts.
If your teams share a deployment, you get nothing finer from the bill.
Per-caller token counts come from API Management, not the bill
For per-caller attribution Microsoft points to Azure API Management. Its llm-emit-token-metric policy, formerly named azure-openai-emit-token-metric, sends total, prompt and completion token counts to Application Insights. Default dimensions include API ID, Product ID, User ID and Subscription ID, and you can add up to five custom dimensions. It now covers OpenAI Chat Completions and Responses, Anthropic Messages and Google Vertex AI.
The limits are tight. API Management limits each dimension to 100 unique values and each metric namespace to 1,000 active time series, and data beyond that is silently discarded. A dimension keyed on end-user ID breaks in any product with more than 100 users.
Provisioned deployments add another wrinkle. Microsoft's provisioned throughput page says they are billed hourly per PTU "regardless of the number of tokens consumed", and that reservation discounts apply to the PTU meter rather than to individual deployments. If two teams share a provisioned deployment, the bill cannot split it at all.
Google Cloud Billing and Vertex AI: labels on every request
Google takes the most granular approach of the three. You attach labels to the inference request itself, and those labels flow into Cloud Billing reports and the BigQuery billing export.
Request labels and the 1,000-value ceiling
Google's custom metadata labels page says Gemini calls take labels in the request body on generateContent and streamGenerateContent. Partner models such as Anthropic Claude and Mistral take them in an X-Vertex-AI-Labels header. A call can carry up to 64 labels for Google models and 32 for partner models. Costs typically appear within a day, sometimes later.
The limit that shapes your design is cardinality. Each label key can hold up to 1,000 unique values over the life of the billing account, and the key "might be dropped without notice" beyond that. Google itself warns against timestamps and per-call IDs. So request labels suit team, feature and environment keys, not customers or requests.
Header labels with the x-goog-agent-platform-observability-label prefix reach request metadata logs only, and Google's page states that they "never reach Cloud Billing". Use both on purpose: body labels for low-cardinality billing keys, header labels for run and request IDs that belong in logs.
Provisioned Throughput silently drops your labels
The same page says requests using the Provisioned Throughput consumption option "silently ignore labels sent in the request". Provisioned Throughput is Google's fixed-price, fixed-term capacity product. Header labels are still recorded in logs, but the billing attribution disappears. A team that moves a busy workload from pay-as-you-go to a 1-year commitment to save money also loses its per-feature cost view on that day.
The pattern holds across all three clouds: the cheaper the capacity, the coarser the attribution.
GPU cost allocation by team on EKS, AKS and GKE
Self-hosted models and fine-tuning jobs run on GPU nodes, usually in Kubernetes.
On AWS, split cost allocation data for EKS has covered NVIDIA and AMD GPUs, Trainium and Inferentia since 2 September 2025. It adds three usage records per pod per hour for accelerated instances in the CUR. AWS's September 2025 blog explains that pods are charged the greater of reservation and usage, and unused instance cost is "proportionally distributed to each pod". A separate splitLineItem/UnusedCost column exists, so idle cost can be queried, but it is folded into team totals by default.
On Google, GKE cost allocation writes namespace, workload and pod labels into the detailed BigQuery export, and GPU SKUs are covered. Unrequested capacity lands in a kube:unallocated bucket rather than inside team totals, which is the cleaner choice for finding waste. Two caveats stand out. Google says the feature does not work with A4 or A4X instances or their GPUs, which are its newest Blackwell-generation machine types. And a pod with more than 50 Kubernetes labels loses all of them in billing.
On Azure, the AKS cost analysis add-on, built on OpenCost, breaks cost down by cluster and namespace and reports idle, system and unallocated charges separately. Microsoft's page does not mention GPUs or GPU node pools. It also requires the Standard or Premium cluster tier and an Enterprise Agreement or Microsoft Customer Agreement.
Requests, not utilisation, on every cloud
All three Kubernetes tools allocate on reservations or requests. Google says so directly: allocation data "is based on resource requests, not resources consumed". AWS uses the greater of the two. None of them tells you how busy the accelerator was. A team that requests a full GPU and runs it at 15% utilisation is billed for the full GPU in every one of these reports. Utilisation has to come from monitoring telemetry joined on node and pod. The money at stake is laid out in our GPU break-even utilisation model.
The cloud cost management AI matrix, with a document behind every cell
Each cell links to the vendor page that supports the verdict. "Native" means the cloud's own billing data answers the question. "Partial" means it answers with a documented condition or only through logs or metrics. "Gap" means the documentation we read describes no native answer.
| Allocation task | AWS | Azure | Google Cloud |
|---|---|---|---|
| Managed model spend by application. | Native. Inference profiles on bedrock-runtime, Projects on bedrock-mantle. | Native. Split by deployment, project tag in preview. | Native. Request labels on pay-as-you-go. |
| Managed model spend by caller or user. | Native. IAM principal column, daily grain. | Partial. Token metrics by user, not cost, 100 values per dimension. | Partial. A label can carry a user key, capped at 1,000 values. |
| Committed model capacity by team. | Partial. Tags on the Provisioned Throughput resource, so per purchase. | Partial. Hourly per PTU, reservation applied to the meter. | Gap. Labels silently ignored on Provisioned Throughput. |
| Per-request token record. | Partial. Invocation logs, off by default, bedrock-runtime only. | Partial. API Management metrics in Application Insights. | Partial. Header labels in request logs, never in billing. |
| Kubernetes GPU-hours by namespace or team. | Native. EKS split cost allocation covers GPUs and Trainium. | Partial. AKS add-on by namespace, GPUs not mentioned. | Partial. GKE cost allocation covers GPUs, not A4 or A4X. |
| Idle GPU capacity shown separately. | Partial. UnusedCost column, redistributed into pods. | Native. Idle charges reported separately. | Native. kube:unallocated bucket. |
| History after you switch it on. | Gap. Tags not retroactive. | Partial. Tag inheritance backfills the current month. | Gap. GKE data not backfilled. |
Source: vendor documentation linked in each cell, retrieved 6 and 7 November 2026. Verdicts are Zan Digital's reading of the documentation, not product tests.
Counting the cells gives the original figure in this post. Of 21 cells, 7 are native, 11 partial and 3 gaps. AWS scores 3 native cells, Azure and Google 2 each. The differences are in which questions each cloud answers, not in how many.
A sample tagging scheme that survives all three clouds
The design rule: put low-cardinality ownership keys in billing, and put high-cardinality identifiers in logs. Google's limits are the strictest, so design to them and the scheme works everywhere: lowercase keys, digits, underscores and dashes only, at most 63 characters, and no key that will ever exceed 1,000 values.
| Key | Example value | AWS | Azure | Google Cloud |
|---|---|---|---|---|
| cost_center | cc-4120. | Tag on the IAM role and on the inference profile. | Resource group tag with inheritance on. | Request body label and project label. |
| team | search-platform. | IAM principal tag, iamPrincipal/team. | Deployment tag, one deployment per team where possible. | Request body label and GKE namespace. |
| app | support-copilot. | One inference profile or Project per app. | Foundry project, using the preview project tag. | Request body label. |
| env | prod, staging, dev. | Tag on profile and role. | Resource tag. | Request body label. |
| feature | ticket-summary. | Session tag set by the gateway. | Custom dimension in API Management. | Request body label, if under 1,000 values. |
| tenant | acme-corp. | Session tag per tenant from the gateway. | Custom dimension only if under 100 tenants. | Header label for logs, not billing. |
| run_id | a UUID per agent run. | Request metadata in invocation logs. | Application trace, never a metric dimension. | Header label, never a body label. |
Billing keys versus log keys
The first five keys are ownership keys: they change rarely and belong in the bill. The last two are identity keys: they grow without limit and belong in logs or traces, joined back to billing on day, model and team.
Two rules make this scheme hold. First, issue a separate inference profile, Project, deployment or label value per team before anyone ships. Every cloud in the matrix refuses to rewrite history once tags arrive. Second, route all model traffic through one gateway that stamps the keys. Hand-applied tags decay the day an engineer copies a code sample without them. Our comparison of AI gateway fees and failover covers what that layer costs.
For per-run cost, the run_id has to travel with every model call into your tracing tool. The tracing products in our LangSmith, Braintrust and Arize review record tokens per span. Multiply by your rate card and you have an estimated cost per run that you reconcile against the daily bill by team.
Where native tools stop and finops AI spend tools start
The matrix shows four gaps that push teams to third-party cloud cost management tools.
The first is cross-cloud normalisation. AWS calls the owner an IAM principal tag, Azure a deployment tag, Google a request label. A team on two clouds has to map three schemas into one report.
The second is direct provider spend. Calls to OpenAI or Anthropic outside a cloud never touch these bills. Those invoices arrive by API key and day, as our State of FinOps reading documents.
The third is shared committed capacity. When two teams share a Provisioned Throughput or PTU block, someone must split the hourly charge by each team's share of tokens. A tool can, if it ingests your gateway metrics alongside the bill.
The fourth is cost per task. No native bill carries a run ID, so any tool claiming cost per agent run is joining billing data to your traces. Ask the vendor to show the join, not the dashboard. Variance at this level is large, as our measurement of agent token cost variance shows.
Our position: buy a third-party tool for normalisation and shared-capacity splitting if you run on two or more clouds. Do not buy one to get per-task cost.
Where this comparison is weakest
Three objections deserve a direct answer, and the first partly wins.
First, this is a documentation reading, not a product test. Azure's AKS add-on may well allocate GPU node cost correctly. We marked it partial because the page does not say so. The same applies to AWS Provisioned Throughput, where the API reference documents resource tags but we found no page describing how they flow into cost reports.
Second, the verdict scale is ours. "Native" versus "partial" is a judgement, and a reader could defensibly move two or three cells. Bedrock's daily-grain IAM attribution could be called partial. Google's request labels could be called native for callers in a small B2B product. The count of 7 native cells is a summary of our reading and should not be quoted as a measured market fact.
Third, the documentation is moving fast. Bedrock's IAM attribution is seven months old and its bedrock-mantle extension under three. Azure's project tag is in preview. Google's pages are mid-rebrand to new product names and paths. Any cell here could change within a quarter.
What survives all three objections: none of the clouds documents per-request cost in the bill, and all three degrade attribution on committed capacity. Those are design facts, and your tagging scheme should assume them.
Frequently asked questions
How do you track Amazon Bedrock costs by team?
Create one application inference profile per team on bedrock-runtime, or one Project per team on bedrock-mantle, and tag it. For per-user attribution, tag the IAM roles that call Bedrock and enable IAM principal data in a CUR 2.0 export. Activate the tags from the payer account. Attribution is daily at best, it is not retroactive, and cost data can take up to 24 hours to appear.
Can Azure Cost Management show Azure OpenAI cost per deployment?
Yes. Microsoft's Foundry cost guidance says you can filter cost analysis by deployment tags or user-defined tags to split cost by model deployment, and view a resource's cost across deployments. A preview feature tags project usage automatically for models sold by Azure. Scope the view to the resource group, since partner model meters appear there rather than under the Foundry resource.
How do you add labels to Vertex AI requests for billing?
For Gemini models, add a labels field to the generateContent or streamGenerateContent request body. For partner models such as Claude, send labels in the X-Vertex-AI-Labels header. Labels reach Cloud Billing on pay-as-you-go traffic, typically within a day. Each key allows up to 1,000 unique values over the billing account's life, and Provisioned Throughput requests silently ignore labels.
How do you allocate GPU costs by Kubernetes namespace?
On EKS, enable split cost allocation data, which writes pod-level GPU, CPU and memory records into the CUR. On GKE, enable cost allocation and read namespaces and pod labels from the detailed BigQuery export, noting A4 and A4X instances are excluded. On AKS, the cost analysis add-on breaks cost down by namespace. All three allocate on requests or reservations, not measured utilisation.
What is the best tagging scheme for AI cloud costs?
Use a small set of low-cardinality keys in billing, such as cost_center, team, app, env and feature, written in lowercase with dashes or underscores and under 63 characters. Keep high-cardinality identifiers such as tenant, request ID and agent run ID in logs or traces. Apply tags through one gateway rather than by hand, and tag before launch, because billing tags are not applied retroactively.
Do AWS, Azure or Google show cost per AI request?
No. None of the three documents per-request cost in its billing data. AWS states that its finest Bedrock attribution grain is per usage type per day. Per-request token counts are available in Bedrock invocation logs, Azure API Management token metrics and Vertex AI request logs. To get cost per request, multiply those token counts by your rate card and reconcile the total with the bill.
Where to start this week
Find out which Bedrock endpoint each of your services calls, which Azure deployments are shared between teams, and which Vertex AI workloads run on Provisioned Throughput. Those three lists mark exactly where your current tags are silently failing.
Then pick the five billing keys above and have one gateway owner stamp them on every model call. History will not backfill, so every week of delay is spend you can never allocate. When the data starts flowing, feed it into your AI spend forecasting process so the forecast is built on attributed spend rather than a single line.
Related on GPU economics
References
- AWS, Amazon Bedrock User Guide: IAM principal cost tracking, retrieved 7 November 2026, with the What's New posts of 9 April 2026 and 11 August 2026. Used for endpoint support, daily grain, retroactivity and tag limits.
- AWS, Billing User Guide: IAM principal cost allocation and Cost Explorer granularity, retrieved 7 November 2026. Used for the CUR column, row growth and 14-day hourly data.
- AWS, Bedrock application inference profiles, model invocation logging and CreateProvisionedModelThroughput, retrieved 7 November 2026.
- AWS, split cost allocation for EKS accelerators, 2 September 2025, the accompanying Cloud Financial Management blog, and the CUR split line item columns.
- Microsoft, Plan and manage costs for Microsoft Foundry, updated October 2026, and provisioned throughput, July 2026. Used for deployment and project splits and PTU billing.
- Microsoft, llm-emit-token-metric policy, September 2026, AKS cost analysis, July 2026, and tag inheritance, 2025.
- Google Cloud, Custom metadata labels for Vertex AI, retrieved 7 November 2026. Used for label limits, header labels and Provisioned Throughput behaviour.
- Google Cloud, GKE cost allocations and detailed usage cost export, retrieved 7 November 2026.
Weakest point in the source base: every verdict comes from vendor documentation rather than hands-on tests, and the native, partial and gap ratings are Zan Digital's judgement. Several pages are in preview or mid-rename. Figures current as of 7 November 2026.
Related reading