We run workloads on AWS and GCP, and an acquisition added an Azure footprint. For two years our "total cloud cost" report was a spreadsheet stitched together from three exports by one person, with hand-written mappings for each provider's columns, and it disagreed with finance every month. AWS calls it lineItem/UnblendedCost, Azure has costInBillingCurrency, GCP has cost plus a list of credits in a nested field, and each handles discounts, commitments and taxes differently.
The FinOps Open Cost and Usage Specification (FOCUS) is a common schema for billing data, maintained by the FinOps Foundation with the major cloud providers involved. The providers now offer FOCUS-formatted exports natively. This guide is what we learned moving our reporting onto it.
What FOCUS gives you
FOCUS defines columns with precise meanings that every provider fills in the same way. One query works across providers, and one definition of "cost" can be agreed with finance. Version 1.0 was released in 2024 and later versions added columns and clarifications; check which version each provider's export implements, since they move at different speeds.
The columns that matter most
| Column | Meaning |
|---|---|
BillingAccountId, SubAccountId |
Where the invoice goes; the account, subscription or project |
ProviderName, PublisherName, InvoiceIssuerName |
Who provides the service, who publishes it (marketplace), who invoices |
ServiceName, ServiceCategory |
Provider's service name and a standard category (Compute, Storage, Databases...) |
ChargeCategory |
Usage, Purchase, Tax, Credit, Adjustment |
ChargePeriodStart, ChargePeriodEnd |
When the usage happened |
BillingPeriodStart |
Which invoice period |
ResourceId, ResourceName |
The resource, when there is one |
RegionId |
Provider region code |
Tags |
Key-value tags/labels, normalised |
PricingCategory |
Standard, Dynamic (Spot), Committed |
CommitmentDiscountId, CommitmentDiscountType |
Which Savings Plan, reservation or committed use discount applied |
ListCost, ContractedCost, BilledCost, EffectiveCost |
Four views of cost |
Four costs, and which one to use
This is where most confusion lives.
- ListCost: public price times quantity. Useful to show savings from discounts.
- ContractedCost: price after your negotiated rates, before commitment discounts are amortised.
- BilledCost: what appears on the invoice for that charge period. A three-year upfront commitment purchase appears as one large charge in the month you bought it; usage covered by it shows zero billed cost.
- EffectiveCost: cost with commitment purchases amortised across the usage they covered. This is what you want for allocation and trend charts, because it reflects what each resource really cost.
Rule we adopted: finance reconciles invoices with BilledCost; engineering showback and unit costs use EffectiveCost. Both come from the same rows, so the numbers are explainable.
Pitfalls we hit
- Double counting commitments. Summing
EffectiveCostover all rows is correct. SummingBilledCostand then adding amortised commitment cost counts commitments twice. Pick one cost column per report. - Charge categories. Credits and adjustments are negative rows. Dashboards that filter to
ChargeCategory = 'Usage'miss refunds and taxes; reports that sum everything include taxes in engineering costs. Decide per report. - Charge period versus billing period. Late adjustments for last month show up in this month's billing period with last month's charge period.
- Tags. FOCUS normalises the column, but tag keys still differ between providers by convention (
teamon AWS,teamlabel on GCP,Teamon Azure). Normalise keys in your pipeline. - Version differences. Providers may implement different FOCUS versions and leave optional columns empty. Check null rates per column per provider.
A practical pipeline
- Enable native FOCUS exports: AWS Data Exports with the FOCUS table, Azure Cost Management exports in FOCUS format, and the GCP FOCUS BigQuery view over the detailed billing export.
- Land them in one warehouse. We use BigQuery; the AWS and Azure exports arrive as Parquet or CSV files in object storage and load into partitioned tables daily.
- Union with a thin view that adds
provider_export_versionand normalises tag keys:
CREATE OR REPLACE VIEW finops.focus_all AS
SELECT 'aws' AS source, * EXCEPT(Tags), finops.normalize_tags(Tags) AS Tags FROM finops.focus_aws
UNION ALL
SELECT 'azure', * EXCEPT(Tags), finops.normalize_tags(Tags) FROM finops.focus_azure
UNION ALL
SELECT 'gcp', * EXCEPT(Tags), finops.normalize_tags(Tags) FROM finops.focus_gcp;
(In practice, align column lists explicitly, since versions differ.)
-
Reconcile monthly against invoices:
SUM(BilledCost)by billing account and billing period must match invoice totals per provider within rounding. Any gap is investigated before reports go out. -
Build reports on
EffectiveCost: cost by team, service category, environment, and unit costs.
SELECT Tags['team'] AS team, ServiceCategory, ROUND(SUM(EffectiveCost), 2) AS cost
FROM finops.focus_all
WHERE ChargePeriodStart >= '2025-10-01' AND ChargePeriodStart < '2025-11-01'
GROUP BY 1, 2
ORDER BY cost DESC;
Getting finance on board
The technical work took weeks; agreement on definitions took longer. What helped was a one-page glossary signed off by finance and engineering: which cost column each report uses, which charge categories are included, how credits and taxes are treated, and which period field defines "the month". Every dashboard links to it. When numbers differ between two reports now, the first question is "which definition does each use", and the answer is usually found in minutes instead of days.
Common mistakes
| Mistake | Why it hurts | Do this instead |
|---|---|---|
| Mixing BilledCost and EffectiveCost | Commitments counted twice or not at all | One cost column per report, documented |
| Filtering only Usage charges | Misses credits, refunds, taxes | Decide charge categories per report |
| Ignoring version differences | Silent nulls in some providers | Check column null rates per provider |
| No invoice reconciliation | Reports lose finance's trust | Monthly BilledCost vs invoice check |
| Raw tag keys | Same team appears three times | Normalise keys in the pipeline |
Key takeaways
- FOCUS gives all providers one billing schema; use native exports.
- Use BilledCost for invoices, EffectiveCost for allocation and trends.
- Be explicit about charge categories and periods.
- Normalise tags and reconcile against invoices every month.
- Check which FOCUS version each provider implements.
References
- FOCUS specification — https://focus.finops.org/
- FinOps Foundation, FOCUS overview — https://www.finops.org/focus/
- AWS Data Exports, FOCUS — https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws.html
- Azure Cost Management FOCUS exports — https://learn.microsoft.com/en-us/azure/cost-management-billing/dataset-schema/cost-usage-details-focus
- Google Cloud FOCUS BigQuery view — https://cloud.google.com/billing/docs/how-to/export-data-bigquery-focus
Comments
0No comments yet. Be the first to comment!
Sign In to post a comment.