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 EffectiveCost over all rows is correct. Summing BilledCost and 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 (team on AWS, team label on GCP, Team on 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

  1. 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.
  2. 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.
  3. Union with a thin view that adds provider_export_version and 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.)

  1. 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.

  2. 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