All cheat sheets
Cost Governancecheat sheet

AWS Cost and Usage Reports

Cost Explorer is a dashboard; CUR is the database. Every billing line item — one resource × one hour × one usage type, hundreds of columns — dumped to S3 for Athena/QuickSight when the question doesn't fit Cost Explorer's dropdowns. Use CUR 2.0 via Data Exports.

Last reviewed: July 14, 2026

TL;DR: Cost Explorer is a pre-aggregated dashboard; CUR is the raw database it summarizes — a daily dump to your S3 bucket of every billing line item (roughly one resource × one hour × one usage type, up to hundreds of columns, tens of millions of rows). When the question doesn't fit Cost Explorer's dropdowns — "which EC2 instances ran 2–6 AM with zero data transfer?" — you query CUR in Athena. For a new setup in 2026, use CUR 2.0 via Data Exports.

The numbers

  • Volume: a $50k/mo account produces ~30–60M rows/month; Parquet, not CSV, unless you have a reason.
  • Athena cost: $5/TB scanned — but with Parquet + partitioning on bill_billing_period_start_date, a "last month by team" query scans a few MB and costs under a cent.
  • Setup choices that matter: hourly granularity, Parquet, resource IDs = YES (can't backfill — the #1 regret), refresh-on-backfill = YES.
  • Running cost rounds to zero: ~5–10 GB/yr of Parquet (<$1/mo S3), a few dollars of Athena, $9/reader/mo QuickSight if used.
  • Field examples: one Athena query found 174 orphaned EBS volumes = $1,860/mo (~$22k/yr); an EC2 spike localized to a single mis-configured On-Demand backfill in 89 seconds; a traceable-to-line-item chargeback got Finance sign-off in one meeting.

Do this

  1. Enable CUR 2.0 via Data Exports — hourly, Parquet, resource IDs YES, refresh-on-backfill YES — to an S3 bucket you control; wait ~24h for the first report.
  2. Lock the bucket down (it holds resource IDs + costs), enable versioning if finance needs reproducibility, and lifecycle old months to Glacier.
  3. Wire CUR → Athena (let AWS auto-create the Glue table), then write 3 saved queries: top-50 resources by cost, cost-by-team-by-month, untagged-spend-by-service.
  4. Always filter on the partition key bill_billing_period_start_date, not just usage dates, or Athena rescans all history every query.
  5. Pick one cost column and document it — almost always unblended (or amortized for SP/RI accounting); mixing columns across reports causes finance fights.

Gotchas

  • Resource IDs can't be backfilled — enable from day one or every row just says "1 hour of m5.xlarge" without which one.
  • The schema changes month to month — AWS adds columns for new services; hardcoded DDL silently misses data, so use Glue schema discovery or refresh monthly.
  • Files are overwritten during the month — query the latest snapshot via the manifest, not a stale mid-month file.
  • Cross-account CUR is the payer account's job — in an Org, only the management account enables Org-wide CUR.
  • CUR is post-discount but pre-credit by default — taxes/refunds/credits are separate LineItemType rows; decide upfront whether "total cost" includes them.

Skip this if

  • You're under ~$10k/mo and Cost Explorer answers your questions — CUR is overkill; over ~$50k/mo with Cost Explorer feeling limiting, it's a no-brainer (the middle band is judgment: ~half a day to stand up).
  • You want pre-built views rather than SQL — AWS Cost Explorer is the friendlier layer. CUR shines once Cost Allocation Tags and Cost Categories are solid (they become columns), and it complements the rules-based checks in Trusted Advisor and the roll-up in Cost Optimization Hub.

Run this audit with your AI assistant

Paste this into Claude, ChatGPT, or any agent that can run the AWS CLI with read-only credentials. It audits your account for exactly the waste this sheet describes — and changes nothing.

You are auditing an AWS account/Org's Cost and Usage Report (CUR) setup
and using it for forensic cost analysis. Use the AWS CLI with READ-ONLY
credentials. Do not create, modify, or delete anything — report findings
and recommended (unapplied) fixes only.

1. Setup: aws cur describe-report-definitions (and bcm-data-exports
   list-exports for CUR 2.0) — confirm hourly granularity, Parquet,
   RESOURCE IDS enabled, and refresh-on-backfill. Flag any legacy CUR
   without resource IDs (can't backfill — the #1 regret).
2. S3 hygiene: check the CUR bucket policy is restrictive (contains
   resource IDs + costs), versioning for auditability, and a lifecycle
   rule tiering >12-month data to Glacier.
3. Athena queries: recommend partition-filtering on
   bill_billing_period_start_date (not just usage dates) to avoid
   scanning all history ($5/TB). Provide 2-3 forensic query patterns
   (top-N resources by cost, orphaned EBS, cost-by-team-by-month).
4. Cost-column consistency: confirm one cost column (usually unblended,
   or amortized for SP/RI accounting) is used consistently.

Report: setup gaps (esp. resource IDs, granularity), S3 hygiene findings,
and a short list of high-value forensic queries to run. Change nothing.
Works with any assistant that can run shell commands.

Want the guided version?

The AWS Cost and Usage Reports walkthrough covers this topic interactively — it asks about your setup, branches to what’s relevant, and quizzes you on the tricky parts. Free and anonymous.

Start the walkthrough