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
- 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.
- Lock the bucket down (it holds resource IDs + costs), enable versioning if finance needs reproducibility, and lifecycle old months to Glacier.
- 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.
- Always filter on the partition key
bill_billing_period_start_date, not just usage dates, or Athena rescans all history every query. - Pick one cost column and document it — almost always
unblended(oramortizedfor 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
LineItemTyperows; 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.