FinOps Inform
Migrate to CUR 2.0: AWS Cost and Usage Report for FinOps & Engineers
Migrate to CUR 2.0 before the legacy report is deprecated. What it contains, how to query it in Athena, and how to turn raw billing data into action.
The AWS Cost and Usage Report (CUR) is the most detailed billing data AWS makes available, line-item level detail on every resource, every hour, every cost allocation tag. Most teams never query it directly, relying instead on Cost Explorer's rolled-up summaries. That's a mistake if you're trying to attribute spend to a specific service, team, or code path. AWS is deprecating the legacy CUR in favour of CUR 2.0, and the migration is straightforward enough that there's little reason to delay it.
What does a Cost and Usage Report actually contain?
CUR data is line-item granular. Every hour, every resource, every cost allocation tag gets its own row, which is a very different shape of data from the daily or monthly summaries Cost Explorer shows you by default.
Each line item typically includes:
- The resource ID and service that generated the charge
- The exact usage type and operation (for example,
BoxUsage:m5.xlargeorDataTransfer-Out-Bytes) - Usage quantity and the unblended, blended, and amortised cost for that line
- Any cost allocation tags applied to the resource
- The pricing term, on-demand, Reserved Instance, Savings Plan, or Spot
That level of detail is what makes CUR data useful for attributing spend to a specific team, service, or even a specific deployment, provided your tagging strategy is consistent enough to support it. Koritsu AI's tagging strategy guide covers what a workable tagging schema looks like in practice.
Why migrate to CUR 2.0 now
The legacy CUR format is being phased out, and CUR 2.0 is the replacement AWS is steering every account towards. Beyond the deprecation timeline, CUR 2.0 brings genuine improvements over the legacy format.
- A single, unified table structure instead of the legacy format's scattered manifest files and inconsistent schema versions across report updates.
- Native support for FOCUS (FinOps Open Cost and Usage Specification), which standardises billing data across cloud providers, useful if you run a multi-cloud environment alongside AWS.
- Simplified integration with Athena and QuickSight, since CUR 2.0's schema is designed around analytical querying from the start rather than bolted on afterwards.
- Incremental data refreshes that don't require reprocessing the entire historical dataset every time new usage lands.
Migrating early avoids a rushed cutover later, and gives you time to rebuild any dashboards or Athena queries against the new schema on your own timeline rather than a deprecation deadline's.
Setting up CUR 2.0 in your account
- In the Billing and Cost Management console, navigate to Data Exports and create a new export using the CUR 2.0 (Data Export) format.
- Choose an S3 bucket to receive the report, ideally a dedicated bucket with lifecycle policies configured, since CUR data accumulates quickly at hourly granularity.
- Select Parquet as the output format if you plan to query with Athena, it's significantly more efficient than CSV for analytical queries at this data volume.
- Enable resource IDs and any cost allocation tags you want included as queryable columns in the export.
- Confirm the export refresh schedule, daily updates are standard, and allow the first full report to generate before building queries against it.
Keep the legacy CUR running in parallel until you've validated CUR 2.0 data against it for at least one full billing cycle. Reconciling the two before cutting over entirely avoids discovering a schema mapping issue after the legacy report is gone.
Querying CUR data with Athena
Athena is the standard way to query CUR data directly without exporting it into a separate warehouse first. AWS automatically provisions a Glue Data Catalog table when you set up the export, so the schema is queryable as soon as the first report lands.
A few practical points worth knowing before you start writing queries:
- Partition pruning matters. CUR 2.0 exports are partitioned by billing period, so always filter on the partition column first, an unfiltered query against months of hourly line items will scan far more data than necessary and cost more to run.
- Use
line_item_unblended_costfor actual spend attribution, notline_item_blended_cost, unless you specifically need consolidated billing's blended rate across linked accounts. - Group by resource tags to attribute cost by team or service, but only if your tagging discipline is consistent enough to make the grouping meaningful.
- Save common queries as Athena views so the rest of the team isn't rewriting the same partition and join logic from scratch each time.
For teams already running dashboards in QuickSight, CUR 2.0's Parquet output connects far more cleanly than the legacy CSV format did, less transformation logic needed before the data is visualisation-ready.
Turning raw billing data into action
Line-item data is only useful if someone actually looks at it and acts on what it shows. Raw CUR access without a review process behind it tends to sit unused after the initial setup enthusiasm fades.
A workable cadence looks like this:
- Run a weekly query surfacing the top cost movers by service and team, anything that shifted meaningfully versus the prior week.
- Cross-reference untagged or inconsistently tagged resources, since those are the line items that can't be attributed to anyone and typically represent the easiest wins once identified.
- Feed anomalies into whatever alerting workflow your team already uses rather than relying on someone remembering to check the dashboard.
- Review Reserved Instance and Savings Plan utilisation against actual usage patterns monthly, CUR data will show you exactly where a commitment is going unused.
Common pitfalls when working with CUR data
A few mistakes come up repeatedly in teams new to working with CUR data directly.
- Querying blended cost when unblended is what the question actually calls for, producing figures that don't match what a specific account was actually charged.
- Ignoring partition columns in Athena queries, which drives up query cost unnecessarily on a dataset this size.
- Treating untagged resources as a rounding error rather than a signal that the tagging strategy has gaps worth closing.
- Building one-off queries instead of saved views, so the same analytical logic gets rewritten slightly differently each time someone needs it.
Sources
- AWS Cost and Usage Report user guide
- AWS Data Exports documentation
- FinOps Open Cost and Usage Specification (FOCUS)