Outcome
By the end of this lesson, you will be able to choose the right billing data source on AWS, GCP, or Azure for a given question, and explain when one source is wrong for the job.
| Tier | Operator |
| JTBD | ”Pull last month’s spend by team in under five minutes.” |
| Personas | Platform Engineer · FinOps Analyst · Finance Partner |
| Prerequisites | L1: What’s actually in a cloud bill |
| Time | 8 minutes |
| Bloom verb | Choose (Apply) |
1. Concept
Each provider publishes the same bill through more than one interface, and they do not all answer the same questions. Picking the wrong one wastes an afternoon, or worse, returns a number that looks right and is not.
There are four you will meet.
AWS Cost and Usage Report, the CUR. The raw data behind everything else: one row per resource, per charge type, per day, or per hour if you configure it that way. AWS drops it into a storage bucket as compressed CSV or Parquet, once a day, roughly 24 hours behind. You query it with Athena, Redshift or any warehouse.
It is the only AWS source that carries the full picture: tags, account, region, charge type, and how a reserved-instance discount was attributed.
AWS Cost Explorer. A query screen in the console, sitting on a pre-aggregated copy of the CUR. Up to 14 months of history, quick to filter and group.
The data is mostly the same, with three caveats worth knowing before you rely on it. Per-resource detail costs $0.01 per API call. Hourly detail costs more again. And tag filtering is less flexible than querying the CUR directly.
Azure Cost Management. Azure’s main cost interface, reading from the platform’s billing service.
It exposes two separate cost columns, ActualCost and AmortizedCost, and the difference matters more than it sounds. A reservation or savings plan shows $0 under ActualCost at subscription scope, and its full effective cost under AmortizedCost. Reading the wrong column is the most common mistake made on Azure bills, and it makes committed spend look free.
Google BigQuery billing export. Google has no equivalent file drop. Billing data lands directly in a BigQuery dataset instead, one row per charge type per resource per day, queried with ordinary SQL.
Two versions exist. The detailed export adds machine type and, if you have labelled them, Kubernetes namespace, in exchange for storing more data.
When to pick which
QUESTION → BEST SOURCE────────────────────────────────────────────────────────────"Quick monthly trend for a stakeholder" → Cost Explorer / Cost Mgmt / BigQuery dashboard"Per-resource cost yesterday" → CUR (AWS), BigQuery (GCP), Cost Mgmt with resource scope (Azure)"Reserved instance attribution" → CUR (AWS): RI distribution columns live here"Reservation cost for Azure resources" → Cost Mgmt with AmortizedCost: NEVER ActualCost at subscription scope"K8s namespace breakdown" → BigQuery detailed export (GCP), CUR with EKS labels (AWS), Cost Mgmt with AKS labels (Azure)"Multi-account roll-up" → CUR exported at Organization root (AWS), BigQuery billing-account export (GCP), Cost Mgmt at Billing Account scope (Azure)"Programmatic ingestion into FinOps tool" → CUR / BigQuery / Cost Mgmt Export API: pick whichever lands in object storageGranularity vs. freshness: the table
| Source | Granularity | Freshness | History | Cost to query |
|---|---|---|---|---|
| AWS CUR | Hourly, per resource, per usage type | 24 h lag | Configurable retention | S3 storage + Athena scan cost |
| AWS Cost Explorer | Daily default, hourly available | 24 h lag | 14 months | Free at daily, $0.01/req at hourly + resource |
| Azure Cost Management | Daily, per resource | 8-24 h lag | 13 months UI, 7 years via export | Free in portal |
| GCP BigQuery export | Daily | 24 h lag | Forever, you own the dataset | BigQuery query cost |
One non-obvious rule
The bill you read is at least a day behind reality. Every source here lags by 24 hours or more, and the earliest hours of yesterday are often still being written when you look.
So treat any claim of real-time cost with suspicion. A tool showing live numbers is doing one of two things. It is multiplying current usage by list prices, which gives the rack rate rather than what you will be charged. Or it is extrapolating from a day that has not finished. Both are useful; neither is the bill. A well-built tool says which it is doing: in ZopNight the Rack Rate column is calculated live and the Billing Cost column carries the lagged actual figures. (See L1 of M0.4 for the full two-source model.)
2. Demo
The same question, “What did EC2 cost yesterday across all my accounts?” answered three ways:
AWS CUR via Athena:
SELECT SUM(line_item_unblended_cost) AS cost_usdFROM cur.consolidated_2026_05WHERE product_code = 'AmazonEC2' AND line_item_usage_start_date >= DATE '2026-05-19' AND line_item_usage_start_date < DATE '2026-05-20';-- → returns $4,217.83AWS Cost Explorer via CLI:
aws ce get-cost-and-usage \ --time-period Start=2026-05-19,End=2026-05-20 \ --granularity DAILY \ --metrics UnblendedCost \ --filter '{"Dimensions":{"Key":"SERVICE","Values":["Amazon Elastic Compute Cloud - Compute"]}}'# → returns $4,217.83GCP BigQuery (Compute Engine equivalent):
SELECT SUM(cost) AS cost_usdFROM `billing_export.gcp_billing_export_v1_*`WHERE service.description = 'Compute Engine' AND usage_start_time >= TIMESTAMP('2026-05-19') AND usage_start_time < TIMESTAMP('2026-05-20');-- → returns the equivalent for GCEAll three answer the same question and agree on the number. They differ in what they let you ask next. The CUR through Athena drills furthest, down to a resource ID and how a discount was attributed. Cost Explorer returns quickest. On Google the BigQuery export is the only option, and it is the most flexible of the three if the team is comfortable with SQL.
(Demo asset to produce: side-by-side screenshot of the three console interfaces returning the same number. Path: assets/screenshots/M0.1_L2_three_sources.png.)
3. Hands-on (6 min: uses real bill, not ZopNight)
Pick the source that matches your primary cloud and pull yesterday’s total EC2 / Compute Engine / Azure VM spend.
AWS, if CUR is configured:
SELECT SUM(line_item_unblended_cost)FROM <your_cur_database>.<your_cur_table>WHERE line_item_product_code = 'AmazonEC2' AND DATE(line_item_usage_start_date) = CURRENT_DATE - INTERVAL '1' DAY;AWS, if CUR is not configured but Cost Explorer is: Use the CLI block from the Demo, swap dates for yesterday and today.
Azure:
az consumption usage list \ --start-date 2026-05-19 \ --end-date 2026-05-20 \ --query "[?contains(meterCategory, 'Virtual Machines')].pretaxCost" \ -o tsv | awk '{s+=$1} END {print s}'GCP:
SELECT SUM(cost)FROM `<your_dataset>.gcp_billing_export_v1_*`WHERE service.description = 'Compute Engine' AND DATE(usage_start_time) = CURRENT_DATE() - 1;Note the number. Now answer the next question without re-running:
Which resource ID accounts for the most of that spend?
If the original query cannot answer that without modification, the source is too coarse for resource-level work. Re-run at the right grain. CUR with line_item_resource_id, BigQuery with resource.global_name, and Azure Cost Management with resource group or resource ID scope are the right paths.
4. Knowledge check
Q1
A Finance Partner asks: “How much did our three reserved AWS instances actually cost the company in May?” Which source is right?
A. Cost Explorer at the resource level
B. CUR with reservation/EffectiveCost and pricing/unit columns
C. Azure Cost Management, reading from the AmortizedCost column
D. GCP BigQuery export
Show answer
Correct: B. Only CUR exposes the RI distribution columns that explain how a reservation’s amortized cost is attributed across resources. Cost Explorer can show aggregate RI usage but is not the right source for line-item attribution. C and D are wrong-cloud answers.
Q2
An Azure-focused engineer reports: “Our reserved VM costs $0 in Cost Management. The RI is broken.” What is the most likely true cause?
A. The RI is broken
B. Azure does not report RI cost at all
C. The engineer queried ActualCost. The right column is AmortizedCost
D. Cost Management has a 48-hour lag and the data is not yet posted
Show answer
Correct: C. Reservations show $0 there at subscription scope. Azure’s ActualCost column reflects the moment of purchase, which is when the reservation was bought, not when it was consumed. The AmortizedCost column distributes the purchase across the term and shows the effective daily cost per consuming resource. This is Azure’s most common FinOps trap. (See M0.4 L3 for the full treatment.)
Q3
The team wants to ingest yesterday’s per-resource AWS bill into an external FinOps tool every morning. Which source is built for that?
A. CUR with daily delivery to S3, picked up by a downstream pipeline
B. Cost Explorer (it has an API)
C. The AWS Console screenshot
D. The Cost Anomaly Detection alerts feed, instead of the export
Show answer
Correct: A. CUR is the only AWS source designed for programmatic ingestion at per-resource grain. Cost Explorer’s API exists but is rate-limited and charged per resource-level call. C and D are not data sources.
5. Apply
ZopNight reads from all four sources behind the scenes. The Billing Sync feature wires AWS Cost Explorer, Azure Cost Management (amortized), and GCP BigQuery billing exports into a single cost_records table so reports query one column regardless of provider.
To verify which source is currently feeding your account:
- Cloud Accounts → click an account → View Sync Status. Each provider shows the source it is reading and the timestamp of the most recent successful sync.
- Reports → Cost Overview displays the active cost-source label (“Unblended Cost” when billing sync is active across every account, “Rack Rate” if even one account is missing). When the label says Unblended Cost, every number on every report is provider-actual.
Open ZopNight Cloud Accounts → (deep link resolves once signed in)
Related lessons
- L1: What’s actually in a cloud bill (previous)
- L3: Granularity vs. timeliness (next)
- T0.M0.4.L3: Amortized cost: Azure’s gotcha
- T3.M3.5.L1: Showback design: pick the dimension
Rule references
RC-002Orphaned EBS Volume: uses CUR resource IDs to detect orphans
Glossary terms touched
CUR · Cost Explorer · Amortized cost · BigQuery billing export · Unblended cost · RI distribution columns