Skip to main content
Your progress
0 of 5 lessons complete0%
T0 / M0.1 / L2 OF 5 / Operator TIER / 8 min

CUR, Cost Explorer, Cost Management, BigQuery: pick one

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.


TierOperator
JTBD”Pull last month’s spend by team in under five minutes.”
PersonasPlatform Engineer · FinOps Analyst · Finance Partner
PrerequisitesL1: What’s actually in a cloud bill
Time8 minutes
Bloom verbChoose (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

Terminal window
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 storage

Granularity vs. freshness: the table

SourceGranularityFreshnessHistoryCost to query
AWS CURHourly, per resource, per usage type24 h lagConfigurable retentionS3 storage + Athena scan cost
AWS Cost ExplorerDaily default, hourly available24 h lag14 monthsFree at daily, $0.01/req at hourly + resource
Azure Cost ManagementDaily, per resource8-24 h lag13 months UI, 7 years via exportFree in portal
GCP BigQuery exportDaily24 h lagForever, you own the datasetBigQuery 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:

Terminal window
SELECT SUM(line_item_unblended_cost) AS cost_usd
FROM cur.consolidated_2026_05
WHERE 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.83

AWS Cost Explorer via CLI:

Terminal window
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.83

GCP BigQuery (Compute Engine equivalent):

Terminal window
SELECT SUM(cost) AS cost_usd
FROM `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 GCE

All 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:

Terminal window
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:

Terminal window
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:

Terminal window
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)


Rule references

Glossary terms touched

CUR · Cost Explorer · Amortized cost · BigQuery billing export · Unblended cost · RI distribution columns


Start with the bill.

Foundations takes about five hours. The first lesson is nine minutes.

Open curriculum. No login. No paywall. 290 lessons across 7 courses, three publicly verifiable credentials. Read it on the train, take the exam on a Saturday, list the credential on your résumé Monday.

5h median time to finish Foundations
0 logins, paywalls, or marketing forms
open curriculum, public credential verifier
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·