The FinOps Open Cost and Usage Specification (FOCUS) is the cloud industry’s first vendor-neutral billing data standard, governed by the FinOps Foundation. It normalizes cost and usage records from every major cloud provider into a single schema so that a single SQL query works across AWS, Azure, GCP, and Oracle Cloud without custom ETL per provider. FOCUS 1.0 was ratified in 2024; FOCUS 1.1 followed in November 2024; 1.2 shipped in mid-2025; 1.3 is the current release as of mid-2026.
The standard is relevant to AI/LLM spend because Bedrock, Azure OpenAI, and Vertex AI all generate billing data in their own proprietary formats. FOCUS provides—at least partially—the normalization layer needed to analyze model costs alongside compute and storage in a unified view. The gaps, however, are significant and form the core of this note.
1. FOCUS Specification — Key Columns and Normalization Goals
1.1 What FOCUS Normalizes
Before FOCUS, every cloud provider used different column names, cost definitions, and aggregation granularities. An AWS CUR file uses line_item_unblended_cost; Azure calls the equivalent CostInBillingCurrency; GCP uses cost. FOCUS collapses these into a single vocabulary.
The normalization goals are:
- Single query, multiple providers. One
SELECT SUM(EffectiveCost) GROUP BY ServiceNamereturns apples-to-apples spend across clouds. - Consistent cost semantics. Four cost columns with precise definitions prevent the ambiguity that plagues on-demand vs. reserved vs. amortized comparisons.
- Interoperable tooling. FinOps platforms can ingest any FOCUS-compliant export without custom parsers.
- Reduced dataset size. FOCUS consolidation typically reduces billing file size ~30% vs. raw CUR.
1.2 Full Column Inventory (FOCUS 1.2 — 57 columns)
FOCUS 1.2 defines 57 columns across six functional families:
Cost Columns (4)
| Column | Definition |
|---|---|
BilledCost |
The charge as it appears on your invoice. Includes all discounts, reduced rates, and prepaid amortization. |
EffectiveCost |
Amortized cost after applying all discounts and prepaid purchases. Preferred for trending and anomaly detection. |
ContractedCost |
ContractedUnitPrice × PricingQuantity. Reflects negotiated rates before further amortization. |
ListCost |
ListUnitPrice × PricingQuantity. Public on-demand rate; baseline for discount analysis. |
Charge Classification Columns (5)
| Column | Definition |
|---|---|
ChargeCategory |
Replaces CUR’s line_item_type. Values: Usage, Purchase, Tax, Credit, Adjustment. |
ChargeClass |
Distinguishes Correction rows (retroactive adjustments) from standard charges. |
ChargeDescription |
Human-readable description of the charge. |
ChargeFrequency |
One-Time, Recurring, Usage-Based. |
ChargePeriodStart / ChargePeriodEnd |
The time window this charge covers. |
Pricing Columns (9)
| Column | Definition |
|---|---|
PricingCategory |
Standard, Committed, Dynamic, Other. |
PricingQuantity |
Volume of SKU purchased or used. For tokens: the token count at the rate tier. |
PricingUnit |
Unit of measurement. For Bedrock this resolves to tokens (provider-specific); not standardized. |
ListUnitPrice |
Rack rate per pricing unit. |
ContractedUnitPrice |
Negotiated unit price. |
SkuId |
Provider SKU identifier. |
SkuMeter |
Human-readable SKU label, e.g., Claude Sonnet 4.6 Input Tokens. |
SkuPriceId |
Rate card identifier for the specific price applied. |
SkuPriceDetails |
Map of additional pricing attributes (new in 1.2). |
Service / Resource Columns (10)
| Column | Definition |
|---|---|
ServiceName |
The product name, e.g., Amazon Bedrock. |
ServiceCategory |
Highest-level taxonomy. Bedrock falls under AI and Machine Learning. |
ServiceSubcategory |
New in 1.2. For Bedrock: Foundational Models (provider-assigned). |
ResourceId |
ARN or equivalent unique resource identifier. |
ResourceName |
Human-readable resource name. |
ResourceType |
Resource class, e.g., InferenceProfile. |
RegionId |
Provider region code, e.g., us-east-1. |
RegionName |
Human-readable region name. |
AvailabilityZone |
Sub-region zone; typically null for Bedrock (managed service). |
Tags |
Normalized key-value map of resource tags. |
Commitment / Discount Columns (7)
| Column | Definition |
|---|---|
CommitmentDiscountId |
Identifier of the commitment (e.g., Savings Plan ARN). |
CommitmentDiscountName |
Human-readable commitment name. |
CommitmentDiscountType |
Savings Plan, Reserved, Committed Use, etc. |
CommitmentDiscountCategory |
Usage or Spend. |
CommitmentDiscountStatus |
Used, Unused. |
CommitmentDiscountQuantity |
Amount of commitment applied. |
CommitmentDiscountUnit |
Unit for the commitment quantity. |
Billing / Account Columns (12+)
| Column | Definition |
|---|---|
BillingAccountId |
Payer account. In AWS: management account ID. |
BillingAccountName |
Human-readable account name. |
BillingAccountType |
New in 1.2. Values: Management, Member. |
SubAccountId |
Linked / member account. |
SubAccountName |
Member account name. |
SubAccountType |
New in 1.2. |
BillingCurrency |
ISO 4217 currency code. |
BillingPeriodStart / BillingPeriodEnd |
Calendar billing period. |
InvoiceId |
Invoice reference. |
InvoiceIssuer |
Entity issuing the invoice. |
Provider |
Top-level cloud provider: Amazon Web Services, Microsoft Azure, etc. |
Publisher |
Entity that produced the resource. For Bedrock third-party models: Anthropic, Meta, Mistral, etc. |
2. AWS CUR 2.0 → FOCUS Column Mapping for Bedrock
AWS supports native FOCUS exports via AWS Data Exports (CUR 2.0). The mapping below covers the columns most relevant to Bedrock analysis.
2.1 Core Column Mapping
| CUR 2.0 Column | FOCUS Column | Notes for Bedrock |
|---|---|---|
line_item_usage_type |
SkuMeter |
Encodes region, model, token direction, tier, and routing. Most information-dense field. |
line_item_operation |
x_Operation (custom) |
In FOCUS report: values include InvokeModelInference, InvokeModelStreamingInference. Not a standard FOCUS column; AWS surfaces it as an extension column. |
line_item_line_item_type |
ChargeCategory |
Usage → Usage; Credit → Credit; Tax → Tax. |
line_item_unblended_cost |
BilledCost |
Post-discount invoice cost. |
line_item_blended_cost |
— | No direct FOCUS equivalent; EffectiveCost is the closest for amortized analysis. |
pricing_public_on_demand_cost |
ListCost |
Rack-rate cost for this usage. |
pricing_unit |
PricingUnit |
For Bedrock: varies by usage type (e.g., token, 1000 tokens). Not yet standardized to a universal AI unit. |
line_item_usage_amount |
PricingQuantity |
Token count for this line item. |
product_servicename |
ServiceName |
Always Amazon Bedrock for Bedrock. |
product_region |
RegionId |
AWS region code. |
line_item_resource_id |
ResourceId |
Inference profile ARN, if using application inference profiles; otherwise null. |
line_item_iam_principal |
No FOCUS equivalent | CUR 2.0 only. IAM ARN of caller. Critical for multi-tenant attribution. See Section 7. |
resourceTags/{key} |
Tags/{key} |
Resource-level tags (Projects, inference profiles). |
iamPrincipal/{key} |
No FOCUS equivalent | IAM-principal-derived tags. No FOCUS column exists for caller identity. |
2.2 Bedrock Usage Type Anatomy
The line_item_usage_type / SkuMeter field encodes five dimensions in a single string:
{region}-{model-id}-{token-type}[-{tier}][-cross-region-global]
Examples and decoded structure:
| Usage Type | Model | Token Type | Tier | Routing |
|---|---|---|---|---|
USE1-Claude4.6Sonnet-input-tokens |
Claude Sonnet 4.6 | Input | Standard | In-region |
USE1-Claude4.6Sonnet-output-tokens |
Claude Sonnet 4.6 | Output | Standard | In-region |
USE1-Claude4.6Sonnet-cache-read-input-token-count |
Claude Sonnet 4.6 | Cache Read | Standard | In-region |
USE1-Claude4.6Sonnet-cache-write-input-token-count |
Claude Sonnet 4.6 | Cache Write | Standard | In-region |
USE1-Claude4.6Sonnet-output-tokens-cross-region-global |
Claude Sonnet 4.6 | Output | Standard | Cross-region |
USE1-Nova2.0Lite-input-tokens-flex |
Amazon Nova 2 Lite | Input | Flex | In-region |
USE1-openai.gpt-oss-120b-mantle-input-tokens-standard |
OpenAI GPT-OSS-120B | Input | Standard | In-region (Bedrock Mantle) |
Reconciliation note: All four token types — input, output, cache read, cache write — generate separate CUR line items with different unit prices. A query summing only input + output tokens will undercount total spend. This is the most common reconciliation gap in Bedrock cost analysis.
2.3 ChargeCategory Values for Bedrock
For Bedrock, the ChargeCategory column is almost always Usage. Exceptions:
Credit— Bedrock promotional credits or enterprise credit memosTax— applicable where AWS charges VAT/GSTAdjustment— retroactive corrections (e.g., billing error remediation)
There is no Purchase row for Bedrock on-demand; Provisioned Throughput commitments generate a Purchase row at purchase time and Usage rows at consumption time.
3. FOCUS-Compliant Cost Tools for AI Spend
3.1 Apptio Cloudability (IBM)
IBM acquired both Cloudability (via Apptio) and Kubecost, creating the dominant enterprise FinOps stack. Cloudability ingests FOCUS-format exports natively from AWS Data Exports, Azure Cost Management, and GCP Billing. Its AI spend features as of 2026:
- Dashboards for Bedrock, Azure OpenAI, and Vertex AI line items grouped by model
- Showback/chargeback rules that allocate AI spend by cost center or team using tag mappings
- FOCUS
Tagscolumn surfaced as allocation dimensions in the UI - No native token-unit display; tokens appear in the
PricingQuantitycolumn but are rendered as raw numbers without model-aware context
Gap: Cloudability’s anomaly detection thresholds are calibrated for compute (hourly patterns). Token-based workloads have different temporal patterns (bursty, request-driven) that generate false positives.
3.2 CloudZero
CloudZero positions itself on unit economics — cost per customer, cost per feature — rather than raw spend dashboards. Its architecture captures spend at the code level by instrumenting API calls and correlating them to business dimensions.
- FOCUS ingest supported for AWS and Azure
- Bedrock costs can be mapped to feature/customer dimensions via CloudZero’s CostFormation rules
- Token volumes from Bedrock logs can be joined to CUR via model + time window, producing cost-per-token-per-feature metrics
- No first-class FOCUS export; CloudZero’s own data model is the canonical representation internally
3.3 Kubecost / OpenCost
Kubecost 3.0 (IBM) focuses on Kubernetes GPU and CPU cost allocation, with NVIDIA DCGM exporter integration for GPU utilization tracking. Relevant for self-hosted LLM inference (vLLM, TGI on EKS), not for managed API services like Bedrock.
OpenCost is the CNCF open-source project underlying Kubecost. It uses the FOCUS PricingUnit and ConsumedQuantity columns to represent GPU/CPU utilization but has no token-specific dimensions.
Use case split:
- Bedrock / managed API → Cloudability or CloudZero
- Self-hosted inference on Kubernetes → Kubecost/OpenCost
3.4 Finout
Finout is notable for its FOCUS-native data model — it stores all ingested billing data in FOCUS format internally, making cross-cloud queries first-class. Its “MegaBill” view merges Bedrock, Azure OpenAI, and GCP Vertex AI line items in a single FOCUS-normalized table. As of 2026, Finout added a dedicated AI spend module with model-level grouping using SkuMeter parsing.
3.5 nOps / Vantage
Both platforms support FOCUS ingest. Neither has AI-specific token-unit features as of mid-2026. They surface Bedrock as a standard ServiceName = 'Amazon Bedrock' filter with SkuMeter-based drill-down.
4. FinOps Foundation AI/ML Working Group
4.1 Scope and Outputs
The FinOps Foundation formalized the FinOps for AI practice area in 2025, with a working group that now has representation from AWS, Microsoft, Google, Anthropic, and major FinOps tool vendors. The 2026 State of FinOps survey found 98% of respondents managing AI spend — up from 31% two years prior — making AI cost governance the top forward-looking priority.
Working group outputs to date:
-
FinOps for AI Framework Guidance — extends the core FinOps lifecycle (Inform → Optimize → Operate) with AI-specific stages: Model Selection, Context Optimization, Caching Strategy, and Agentic Cost Control.
-
Recommended Tagging Taxonomy — a standardized tag key set for AI workloads (see Section 8).
-
Unit Economics Definitions — cost-per-token, cost-per-request, cost-per-resolved-task as the canonical AI FinOps metrics, replacing raw monthly spend.
-
FOCUS Gap Register — a documented list of AI-specific gaps in FOCUS 1.x submitted to the FOCUS steering committee for 1.4/1.5 consideration (see Section 6).
-
Agentic Cost Control Guidance — recommendations for capping agent loop steps, alerting on per-task cost overruns, and failing CI/CD builds when cost-per-request budgets are exceeded.
4.2 LLM Cost Attribution Model
The working group’s attribution model identifies four levels of granularity:
| Level | Attribution Grain | Tool |
|---|---|---|
| L1 | Cloud account / subscription | CUR + cost allocation tags |
| L2 | Team / cost center | IAM principal tags + project tags |
| L3 | Feature / application | Application inference profiles + custom tags |
| L4 | Request / prompt | Model invocation logs (not CUR; CUR does not carry request IDs) |
L4 attribution requires joining CUR data to model invocation logs at the model + time-window grain. CUR does not carry per-request identifiers; fine-grained prompt-level cost must be reconstructed from logs.
5. How FOCUS Handles Token-Based Pricing
Token-based pricing is structurally different from the compute and storage pricing FOCUS was designed for:
| Pricing Dimension | Compute (EC2) | Object Storage (S3) | LLM Tokens (Bedrock) |
|---|---|---|---|
| Unit | vCPU-hour | GB-month | 1,000 tokens |
| Direction | N/A | N/A | Input / Output / Cache Read / Cache Write |
| Model dimension | Instance type | Storage class | Model ID (10s of variants) |
| Pricing variability | Flat / savings plan | Flat | Varies by model, tier, direction, routing |
FOCUS accommodates token pricing through existing general-purpose columns:
PricingUnit: Holds the provider-specified unit string. For Bedrock, AWS uses1K tokensortokensdepending on the model. This is not standardized across providers — Azure OpenAI uses1,000 tokens, GCP Vertex usescharactersfor some models.PricingQuantity: Holds the token count (or token-count divided by 1,000, depending on the usage type). The denominator is encoded inPricingUnitand must be parsed.SkuMeter: The most information-rich field for AI workloads. Contains model ID, token direction, tier, and routing — all encoded in a single string with no machine-readable sub-fields.Publisher: Distinguishes Anthropic-model charges from Amazon-model charges within Bedrock, enabling cross-provider model family analysis.
The PricingCategory = Usage-Based applies correctly to token pricing. ChargeFrequency = Usage-Based is accurate.
For Azure OpenAI, the FinOps Toolkit normalizes FOCUS data and publishes derived TokensConsumed and CostPerToken calculated columns on top of the standard FOCUS export — but these are non-standard extensions, not part of the FOCUS specification.
6. Gaps in FOCUS 1.0–1.3 for AI Workloads
6.1 Confirmed Gaps (as of FOCUS 1.3)
| Gap | Impact | Workaround |
|---|---|---|
No ModelId column |
Cannot filter or group by model without string-parsing SkuMeter |
Parse SkuMeter with regex in SQL; add computed column |
No TokenDirection column |
Input vs. output vs. cache costs require SkuMeter parsing |
Parse usage type pattern |
No TokenCount column |
Token volumes buried in PricingQuantity with inconsistent denominators |
Normalize via PricingUnit |
No standardized PricingUnit for tokens |
1K tokens, tokens, characters all appear; cross-provider comparison requires manual mapping |
Maintain a provider-unit mapping table |
No ModelFamily or ModelVersion dimension |
Claude 3 Haiku vs. Claude Sonnet 4.6 are indistinguishable without parsing | Maintain a model taxonomy lookup |
No ServiceTier column |
Standard vs. Priority vs. Flex tier affects unit price; tier is embedded in usage type | Parse usage type |
No RoutingType column |
Cross-region inference priced differently; routing embedded in usage type | Parse usage type |
| No caller identity column | line_item_iam_principal exists in CUR 2.0 but has no FOCUS equivalent |
Use CUR 2.0 format instead of FOCUS format, or join FOCUS to CUR on row key |
SkuMeter not machine-parseable |
All model metadata is a freeform string with no schema | Regex + lookup table |
No PromptCacheId dimension |
Cache read/write tokens cannot be linked to the cache entry that produced them | Model invocation logs only |
6.2 FOCUS Steering Committee Roadmap
FOCUS 1.4/1.5 (expected late 2026 / early 2027) is anticipated to address:
- Structured SKU metadata columns (replacing freeform
SkuMeterfor AI models) - Token-specific pricing units standardization
- Caller/principal identity (likely as an optional extension column)
- Reasoning token support (separate pricing for chain-of-thought tokens, now offered by Anthropic and OpenAI)
Until those columns ship, every production Bedrock cost analysis requires parsing line_item_usage_type or SkuMeter with provider-specific regex patterns.
7. Building a FOCUS-Normalized Bedrock View in Athena
7.1 Prerequisites
- AWS Data Exports enabled with CUR 2.0 format (not legacy CUR)
- An Athena database and crawler configured against the S3 export bucket
- Cost allocation tags activated in AWS Billing console (24-hour propagation lag after activation)
- For IAM principal attribution: CUR 2.0 format required; FOCUS export format does not carry
line_item_iam_principal
7.2 CUR 2.0 Table Schema (Relevant Columns)
The Athena table created by the CUR 2.0 crawler exposes these columns for Bedrock analysis:
-- Key columns in the CUR 2.0 Athena table
line_item_usage_type VARCHAR -- encodes model, token type, tier, routing
line_item_operation VARCHAR -- InvokeModelInference | InvokeModelStreamingInference
line_item_unblended_cost DOUBLE -- BilledCost equivalent
line_item_usage_amount DOUBLE -- token count (raw; denominator in pricing_unit)
pricing_unit VARCHAR -- e.g. "tokens", "1K tokens"
pricing_public_on_demand_cost DOUBLE -- ListCost equivalent
line_item_iam_principal VARCHAR -- IAM ARN of caller (CUR 2.0 only)
product_servicename VARCHAR -- "Amazon Bedrock"
product_region VARCHAR -- AWS region
line_item_line_item_type VARCHAR -- Usage | Credit | Tax | Adjustment
resource_tags MAP -- resourceTags/* columns
iam_principal_tags MAP -- iamPrincipal/* columns
line_item_usage_start_date TIMESTAMP
line_item_usage_end_date TIMESTAMP
7.3 Model Extraction UDF (Athena / Presto)
Extract model ID, token direction, and tier from the usage type string:
-- Athena SQL: Parse Bedrock usage type into structured dimensions
-- Table: your_cur_database.cur_data
-- Adjust the regex patterns to match your active models
WITH bedrock_raw AS (
SELECT
line_item_usage_start_date AS charge_period_start,
product_region AS region_id,
line_item_usage_type AS sku_meter,
line_item_operation AS operation,
line_item_iam_principal AS caller_arn,
line_item_unblended_cost AS billed_cost,
pricing_public_on_demand_cost AS list_cost,
line_item_usage_amount AS pricing_quantity,
pricing_unit AS pricing_unit_raw,
-- Normalize token count to raw tokens
CASE
WHEN lower(pricing_unit) LIKE '%1k%'
OR lower(pricing_unit) LIKE '%1,000%' THEN line_item_usage_amount * 1000
ELSE line_item_usage_amount
END AS token_count,
-- Extract model ID from usage type
-- Pattern: {region_prefix}-{model_id}-{token_type}[-{tier}][-cross-region-global]
regexp_extract(
line_item_usage_type,
'^[A-Z0-9]+-(.+?)-(input-tokens|output-tokens|cache-read-input-token-count|cache-write-input-token-count)',
1
) AS model_id,
-- Extract token direction
CASE
WHEN line_item_usage_type LIKE '%-cache-read-input-token-count%' THEN 'cache_read'
WHEN line_item_usage_type LIKE '%-cache-write-input-token-count%' THEN 'cache_write'
WHEN line_item_usage_type LIKE '%-output-tokens%' THEN 'output'
WHEN line_item_usage_type LIKE '%-input-tokens%' THEN 'input'
ELSE 'unknown'
END AS token_direction,
-- Extract service tier
CASE
WHEN line_item_usage_type LIKE '%-priority%' THEN 'priority'
WHEN line_item_usage_type LIKE '%-flex%' THEN 'flex'
ELSE 'standard'
END AS service_tier,
-- Detect cross-region routing
CASE
WHEN line_item_usage_type LIKE '%-cross-region-global%' THEN true
ELSE false
END AS is_cross_region
FROM your_cur_database.cur_data
WHERE product_servicename = 'Amazon Bedrock'
AND line_item_line_item_type = 'Usage'
AND year = '2026' -- partition filter; adjust for your partition scheme
)
SELECT *
FROM bedrock_raw;
7.4 FOCUS-Normalized View
This view maps CUR 2.0 columns to their FOCUS equivalents and adds parsed AI dimensions:
-- Create a FOCUS-normalized view with AI extensions
CREATE OR REPLACE VIEW focus_bedrock_v1 AS
WITH parsed AS (
SELECT
-- FOCUS standard columns
'Amazon Web Services' AS provider,
'Amazon Bedrock' AS service_name,
'AI and Machine Learning' AS service_category,
'Foundational Models' AS service_subcategory,
'Usage' AS charge_category,
'Usage-Based' AS charge_frequency,
product_region AS region_id,
line_item_usage_start_date AS charge_period_start,
line_item_usage_end_date AS charge_period_end,
line_item_unblended_cost AS billed_cost,
pricing_public_on_demand_cost AS list_cost,
line_item_usage_amount AS pricing_quantity,
pricing_unit AS pricing_unit,
line_item_usage_type AS sku_meter,
line_item_resource_id AS resource_id,
-- Publisher derived from model prefix
CASE
WHEN lower(line_item_usage_type) LIKE '%-claude%' THEN 'Anthropic'
WHEN lower(line_item_usage_type) LIKE '%-llama%' THEN 'Meta'
WHEN lower(line_item_usage_type) LIKE '%-nova%' THEN 'Amazon'
WHEN lower(line_item_usage_type) LIKE '%-mistral%' THEN 'Mistral AI'
WHEN lower(line_item_usage_type) LIKE '%-openai%'
OR lower(line_item_usage_type) LIKE '%-gpt%' THEN 'OpenAI'
WHEN lower(line_item_usage_type) LIKE '%-titan%' THEN 'Amazon'
ELSE 'Unknown'
END AS publisher,
-- Non-standard AI extension columns (x_ prefix per FOCUS convention)
regexp_extract(
line_item_usage_type,
'^[A-Z0-9]+-(.+?)-(input-tokens|output-tokens|cache-read-input-token-count|cache-write-input-token-count)',
1
) AS x_model_id,
CASE
WHEN line_item_usage_type LIKE '%-cache-read-input-token-count%' THEN 'cache_read'
WHEN line_item_usage_type LIKE '%-cache-write-input-token-count%' THEN 'cache_write'
WHEN line_item_usage_type LIKE '%-output-tokens%' THEN 'output'
WHEN line_item_usage_type LIKE '%-input-tokens%' THEN 'input'
ELSE 'unknown'
END AS x_token_direction,
CASE
WHEN line_item_usage_type LIKE '%-priority%' THEN 'priority'
WHEN line_item_usage_type LIKE '%-flex%' THEN 'flex'
ELSE 'standard'
END AS x_service_tier,
CASE
WHEN line_item_usage_type LIKE '%-cross-region-global%' THEN true
ELSE false
END AS x_is_cross_region,
-- Normalize token count to raw tokens regardless of pricing_unit denominator
CASE
WHEN lower(pricing_unit) LIKE '%1k%'
OR lower(pricing_unit) LIKE '%1,000%' THEN line_item_usage_amount * 1000
ELSE line_item_usage_amount
END AS x_token_count,
-- Caller identity (CUR 2.0 only; no FOCUS equivalent)
line_item_iam_principal AS x_caller_arn,
split_part(line_item_iam_principal, '/', -1) AS x_caller_session_name
FROM your_cur_database.cur_data
WHERE product_servicename = 'Amazon Bedrock'
AND line_item_line_item_type = 'Usage'
)
SELECT * FROM parsed;
7.5 Analytical Queries Against the View
Cost by model and token direction, current month:
SELECT
x_model_id,
x_token_direction,
x_service_tier,
SUM(billed_cost) AS total_billed_cost,
SUM(x_token_count) AS total_tokens,
ROUND(
SUM(billed_cost) / NULLIF(SUM(x_token_count), 0) * 1000000,
6
) AS cost_per_million_tokens
FROM focus_bedrock_v1
WHERE charge_period_start >= DATE_TRUNC('month', CURRENT_DATE)
GROUP BY x_model_id, x_token_direction, x_service_tier
ORDER BY total_billed_cost DESC;
Cost by IAM caller (team attribution):
SELECT
x_caller_arn,
x_model_id,
SUM(billed_cost) AS total_billed_cost,
SUM(x_token_count) AS total_tokens
FROM focus_bedrock_v1
WHERE charge_period_start >= DATE_ADD('day', -30, CURRENT_DATE)
GROUP BY x_caller_arn, x_model_id
ORDER BY total_billed_cost DESC
LIMIT 50;
Cache efficiency analysis (cache read savings):
SELECT
x_model_id,
SUM(CASE WHEN x_token_direction = 'input' THEN billed_cost ELSE 0 END) AS input_cost,
SUM(CASE WHEN x_token_direction = 'output' THEN billed_cost ELSE 0 END) AS output_cost,
SUM(CASE WHEN x_token_direction = 'cache_read' THEN billed_cost ELSE 0 END) AS cache_read_cost,
SUM(CASE WHEN x_token_direction = 'cache_write'THEN billed_cost ELSE 0 END) AS cache_write_cost,
SUM(billed_cost) AS total_cost,
SUM(CASE WHEN x_token_direction IN ('cache_read','cache_write') THEN x_token_count ELSE 0 END)
/ NULLIF(SUM(x_token_count), 0) * 100 AS cache_token_pct
FROM focus_bedrock_v1
WHERE charge_period_start >= DATE_ADD('day', -30, CURRENT_DATE)
GROUP BY x_model_id
ORDER BY total_cost DESC;
Cross-region cost premium:
SELECT
x_model_id,
x_is_cross_region,
SUM(x_token_count) AS tokens,
SUM(billed_cost) AS cost,
ROUND(
SUM(billed_cost) / NULLIF(SUM(x_token_count), 0) * 1000000,
6
) AS cost_per_million_tokens
FROM focus_bedrock_v1
WHERE charge_period_start >= DATE_ADD('day', -30, CURRENT_DATE)
GROUP BY x_model_id, x_is_cross_region
ORDER BY x_model_id, x_is_cross_region;
8. Cost Allocation Tag Standards — FinOps Foundation Recommendations for AI Workloads
8.1 FinOps Foundation Recommended Tag Taxonomy
The FinOps for AI working group recommends a five-dimension tagging structure applied at both the IAM principal level and the application inference profile level:
| Tag Key | Example Values | Attribution Level |
|---|---|---|
Environment |
production, staging, development |
L2 |
Team |
data-science, product-ml, platform-eng |
L2 |
CostCenter |
cc-1234, product-ai, marketing-ai |
L2 |
Project |
rag-pipeline-v2, customer-support-bot |
L3 |
WorkloadType |
inference, batch-inference, fine-tuning, embedding |
L3 |
Application |
search-reranker, doc-summarizer |
L3 |
ModelFamily |
claude, nova, llama |
L3 (supplemental) |
8.2 AWS-Specific Implementation
AWS exposes tag-based attribution through three mechanisms, each with distinct CUR representation:
Mechanism 1: IAM Principal Tags
Attach tags directly to IAM users or roles. Tags flow through to CUR as iamPrincipal/{key} columns.
# Tag an IAM role used for Bedrock inference
aws iam tag-role \
--role-name bedrock-inference-role \
--tags Key=Team,Value=data-science \
Key=CostCenter,Value=cc-1234 \
Key=Project,Value=rag-pipeline-v2
Mechanism 2: Bedrock Projects
Group inference resources under a Bedrock Project. Project tags appear as resourceTags/{key} in CUR. Projects are the recommended mechanism for L3 (feature/application) attribution.
aws bedrock create-project \
--project-name "customer-support-bot" \
--tags Team=product-ml,Environment=production,WorkloadType=inference
Mechanism 3: Application Inference Profiles
Create named inference profiles that wrap a model with a fixed set of tags. All requests routed through the profile inherit the profile’s tags. This is the cleanest mechanism for multi-tenant gateway architectures where the gateway calls Bedrock on behalf of multiple downstream applications.
aws bedrock create-application-inference-profile \
--inference-profile-name "rag-pipeline-prod" \
--model-source '{"copyFrom": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-4-6-v1:0"}' \
--tags Application=rag-pipeline,Team=data-science,Environment=production
8.3 Tag Activation Requirement
Tags must be explicitly activated as cost allocation tags in the AWS Billing console before they appear in CUR or Cost Explorer. Propagation takes 24–48 hours after activation. This is a common operational gap: teams instrument their code correctly but forget to activate tags in Billing, resulting in silent data loss from the CUR perspective.
8.4 Recommended Tagging Governance
The FinOps Foundation working group recommends four governance controls for AI tagging:
-
Tag policy enforcement. AWS Organizations tag policies can require specific keys on IAM roles used for Bedrock. A role without
TeamandCostCentertags should fail a pre-deployment policy check. -
Tag coverage dashboards. Track what percentage of Bedrock
BilledCosthas a populatedTeamtag vs. falls into anUntaggedbucket. Target: ≥95% tagged within 90 days of program launch. -
Gateway-enforced tagging. For LLM gateway architectures (LiteLLM, custom routers), the gateway layer should assume a per-application IAM role (with
AssumeRole) that carries the correct tags. This prevents individual service teams from needing IAM knowledge to tag correctly. -
CI/CD validation. Bedrock deployment pipelines should validate that the inference profile or IAM role being deployed carries all required tag keys before the deployment is approved.
9. Limitations and Known Issues
CUR does not carry per-request identifiers. CUR aggregates charges by usage type, operation, and pricing/resource over an hour or a day. To attribute cost to a specific prompt or conversation, you must use Bedrock model invocation logs and join them to CUR at the model + time-window grain. This join is approximate, not exact.
FOCUS format vs. CUR 2.0 format tradeoff. AWS Data Exports can produce either FOCUS-format output or CUR 2.0 format output. FOCUS format omits line_item_iam_principal — the single most useful column for multi-tenant attribution. Teams that need caller identity attribution should use CUR 2.0 format and map to FOCUS columns manually (as in the view above) rather than using the native FOCUS export.
Regex fragility. The SkuMeter / line_item_usage_type parsing patterns in this note are based on the current AWS naming convention. AWS has historically changed model ID string formatting (e.g., anthropic.claude-3-haiku → Claude4.6Haiku) when releasing new model generations. Regex patterns require maintenance with each major model family update.
Prompt cache accounting. Cache write tokens are priced higher than standard input tokens; cache read tokens are priced lower. Workloads with large system prompts can see cache write costs that exceed inference costs in the first request of each context window. This is counterintuitive and frequently miscategorized in dashboards that only show “input” and “output” buckets.
Commitment discount representation. Bedrock Provisioned Throughput generates a Purchase ChargeCategory row at commitment time and Usage rows as it is consumed. FOCUS handles this correctly via CommitmentDiscountStatus (Used / Unused), but tools must explicitly handle the Bedrock Provisioned Throughput Purchase row to avoid double-counting spend.
10. Summary: What FOCUS Does and Does Not Solve for AI Spend
| Concern | FOCUS Solves? | Note |
|---|---|---|
| Multi-cloud cost in one schema | Yes | AWS, Azure, GCP, Oracle all support FOCUS export |
| Bedrock vs. Azure OpenAI comparison | Partial | ServiceName and Publisher work; SkuMeter formats differ and require parsing |
| Cost by model family | No (native) | Requires SkuMeter parsing; no ModelId column |
| Input vs. output token split | No (native) | Requires usage type parsing |
| Cache read/write cost tracking | No (native) | Requires usage type parsing |
| Cross-region pricing visibility | No (native) | Requires usage type parsing |
| IAM caller attribution | No | Not in FOCUS spec; use CUR 2.0 format |
| Commitment discount handling | Yes | CommitmentDiscountStatus covers Provisioned Throughput |
| Chargeback / showback | Partial | Tags column works; activation and governance required |
| Reasoning token pricing | No | Not in FOCUS 1.3; expected in 1.4/1.5 |
The practical conclusion: FOCUS is a necessary normalization layer but not a sufficient one for AI cost governance. Production Bedrock deployments require a supplemental parsing layer — either a SQL view of the type documented in Section 7, or a FinOps tool with native model-awareness — to expose the dimensions that FOCUS 1.3 does not yet standardize.
Sources: FinOps Foundation FOCUS specification v1.1/v1.2 (focus.finops.org); AWS Bedrock CUR documentation (docs.aws.amazon.com/bedrock); AWS Cloud Financial Management blog — IAM principal tracking post (2026); AWS Data Exports granular Bedrock visibility announcement (January 2026); FinOps for AI working group overview (finops.org/wg/finops-for-ai-overview); State of FinOps 2026 survey (data.finops.org); IAN Cloud FOCUS 1.3 analysis (iancloud.ai); Rick Pollick — LLM cost governance (rickpollick.com); Microsoft Community Hub — Azure OpenAI FOCUS unit economics (techcommunity.microsoft.com); Amnic FOCUS 2026 guide (amnic.com).