Three clouds, three billing formats, and a director comparing apples to invoices

The CFO sends the engineering director one line: which cloud is cheapest for the data pipeline? So the director pulls the AWS Cost and Usage Report, the Azure cost export, and the GCP billing export, drops all three into one spreadsheet, and starts lining up rows. The quiet assumption is that the files describe the same thing in different fonts. They do not. The column names differ, the cost types differ, and each provider has its own rule for when a discount appears.

By the third tab the totals stop agreeing with each other, and the meeting becomes an argument about the spreadsheet instead of a decision about the workload.

Why three native billing exports never reconcile

Every provider built its billing schema before anyone agreed on a shared one, so the vocabularies drifted apart. AWS gives you a CostAndUsageReport with lineItem/UnblendedCost plus a separate amortized view. Azure exports CostInBillingCurrency against meter categories. GCP hands you a BigQuery table built around its own SKU and credit structure. The same managed database costs you money in all three, but the field holding the number, the sign convention on credits, and the way a reserved purchase gets spread across days differ in each export.

You can hand-map the columns, and teams do, every quarter. The mapping is best-effort and lives in nobody's documentation, so the next person rebuilds it from scratch and gets a different answer for the same month.

Cost types, amortization, and the apples-to-invoices gap

Amortization is where it really breaks. A one-year commitment lands as a single large charge on the day you buy it, but its effective cost is that charge spread across the term. AWS publishes both a blended and an amortized figure; Azure amortizes reservations on its own terms; GCP applies committed-use discounts as credits against usage rows. Set one provider's up-front number beside another's amortized number and the cheap cloud and the expensive cloud can quietly swap places, with nobody sure which view each column holds.

That is the apples-to-invoices gap. You are not comparing two costs; you are comparing one provider's accounting choice against another's and calling the difference a savings opportunity.

What the FOCUS specification actually standardizes

FOCUS, the FinOps Open Cost and Usage Specification, exists to delete the hand-mapping step. It defines required columns that each carry one meaning, so providers can emit cost and usage data in the same shape. BilledCost is the invoice number. EffectiveCost is the amortized number. ChargeCategory tells you whether a row is usage, a purchase, or a credit. Once every export speaks those columns, a cross-cloud comparison is a query instead of a reconciliation project.

Unified commitment reporting

Recent versions of the spec go after the part the director keeps getting wrong. A dedicated commitment dataset pulls contract terms, start and end dates, remaining units, and descriptions out of the cost-and-usage rows into their own table, which can be permissioned separately. One query then lists every active commitment across clouds, in place of three reservation reports that never lined up. Newer allocation columns also record how shared costs were split, so the methodology travels with the number.

Comparing clouds on numbers everyone agrees on

A cross-cloud cost decision is only as trustworthy as the schema underneath it, and the native exports do not share one. Normalize first, then compare. In a Cloud Horizons workspace each provider's billing data lands in the FOCUS schema, so EffectiveCost means the same thing whether the row came from AWS, Azure, or GCP, and every commitment shows up in one place. The argument goes back to being about the workload. See how the FOCUS normalization works.