A step-by-step guide to manually create AWS Cost and Usage Report 2.0 with Athena integration.
Prerequisites
AWS Account with billing access
Permissions: S3, Glue, Athena, BCM Data Exports
AWS CLI configured (optional, for CLI steps)
Step 1: Create S3 Bucket
Console:
Go to S3 → Create bucket
Bucket name: wiv-cur2-{account-id} (e.g., wiv-cur2-123456789012)
Region: us-east-1 (recommended for CUR)
Keep defaults → Create bucket
CLI:
aws s3 mb s3://wiv-cur2-123456789012 --region us-east-1
Step 2: Add S3 Bucket Policy
Console:
Go to your bucket → Permissions → Bucket policy
Add this policy (replace 123456789012 with your account ID):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"billingreports.amazonaws.com",
"bcm-data-exports.amazonaws.com"
]
},
"Action": [
"s3:PutObject",
"s3:GetBucketPolicy"
],
"Resource": [
"arn:aws:s3:::wiv-cur2-123456789012",
"arn:aws:s3:::wiv-cur2-123456789012/*"
],
"Condition": {
"StringLike": {
"aws:SourceArn": [
"arn:aws:cur:us-east-1:123456789012:definition/*",
"arn:aws:bcm-data-exports:us-east-1:123456789012:export/*"
],
"aws:SourceAccount": "123456789012"
}
}
}
]
}
CLI:
aws s3api put-bucket-policy --bucket wiv-cur2-123456789012 --policy file://bucket-policy.json
Step 3: Create CUR 2.0 Export
Console:
Go to Billing and Cost Management → Data Exports
Click Create export
Select Standard data export (CUR 2.0)
Configure:
Export name: Wiv-CUR2
Select all columns or use this query:
SELECT * FROM COST_AND_USAGE_REPORT
Table configurations:
TIME_GRANULARITY: HOURLY
INCLUDE_RESOURCES: TRUE
INCLUDE_SPLIT_COST_ALLOCATION_DATA: TRUE
Destination:
S3 bucket: wiv-cur2-123456789012
S3 prefix: wiv
Click Create export
CLI:
aws bcm-data-exports create-export \
--export '{
"Name": "Wiv-CUR2",
"DataQuery": {
"QueryStatement": "SELECT bill_bill_type, bill_billing_entity, bill_billing_period_end_date, bill_billing_period_start_date, bill_invoice_id, bill_invoicing_entity, bill_payer_account_id, bill_payer_account_name, capacity_reservation_capacity_reservation_arn, capacity_reservation_capacity_reservation_status, capacity_reservation_capacity_reservation_type, cost_category, discount, discount_bundled_discount, discount_total_discount, identity_line_item_id, identity_time_interval, line_item_availability_zone, line_item_blended_cost, line_item_blended_rate, line_item_currency_code, line_item_legal_entity, line_item_line_item_description, line_item_line_item_type, line_item_net_unblended_cost, line_item_net_unblended_rate, line_item_normalization_factor, line_item_normalized_usage_amount, line_item_operation, line_item_product_code, line_item_resource_id, line_item_tax_type, line_item_unblended_cost, line_item_unblended_rate, line_item_usage_account_id, line_item_usage_account_name, line_item_usage_amount, line_item_usage_end_date, line_item_usage_start_date, line_item_usage_type, line_item_user_identifier, pricing_currency, pricing_lease_contract_length, pricing_offering_class, pricing_public_on_demand_cost, pricing_public_on_demand_rate, pricing_purchase_option, pricing_rate_code, pricing_rate_id, pricing_term, pricing_unit, product, product_comment, product_fee_code, product_fee_description, product_from_location, product_from_location_type, product_from_region_code, product_instance_family, product_instance_type, product_instancesku, product_location, product_location_type, product_operation, product_pricing_unit, product_product_family, product_region_code, product_servicecode, product_sku, product_to_location, product_to_location_type, product_to_region_code, product_usagetype, reservation_amortized_upfront_cost_for_usage, reservation_amortized_upfront_fee_for_billing_period, reservation_availability_zone, reservation_effective_cost, reservation_end_time, reservation_modification_status, reservation_net_amortized_upfront_cost_for_usage, reservation_net_amortized_upfront_fee_for_billing_period, reservation_net_effective_cost, reservation_net_recurring_fee_for_usage, reservation_net_unused_amortized_upfront_fee_for_billing_period, reservation_net_unused_recurring_fee, reservation_net_upfront_value, reservation_normalized_units_per_reservation, reservation_number_of_reservations, reservation_recurring_fee_for_usage, reservation_reservation_a_r_n, reservation_start_time, reservation_subscription_id, reservation_total_reserved_normalized_units, reservation_total_reserved_units, reservation_units_per_reservation, reservation_unused_amortized_upfront_fee_for_billing_period, reservation_unused_normalized_unit_quantity, reservation_unused_quantity, reservation_unused_recurring_fee, reservation_upfront_value, resource_tags, savings_plan_amortized_upfront_commitment_for_billing_period, savings_plan_end_time, savings_plan_instance_type_family, savings_plan_net_amortized_upfront_commitment_for_billing_period, savings_plan_net_recurring_commitment_for_billing_period, savings_plan_net_savings_plan_effective_cost, savings_plan_offering_type, savings_plan_payment_option, savings_plan_purchase_term, savings_plan_recurring_commitment_for_billing_period, savings_plan_region, savings_plan_savings_plan_a_r_n, savings_plan_savings_plan_effective_cost, savings_plan_savings_plan_rate, savings_plan_start_time, savings_plan_total_commitment_to_date, savings_plan_used_commitment, split_line_item_actual_usage, split_line_item_net_split_cost, split_line_item_net_unused_cost, split_line_item_parent_resource_id, split_line_item_public_on_demand_split_cost, split_line_item_public_on_demand_unused_cost, split_line_item_reserved_usage, split_line_item_split_cost, split_line_item_split_usage, split_line_item_split_usage_ratio, split_line_item_unused_cost, tags FROM COST_AND_USAGE_REPORT",
"TableConfigurations": {
"COST_AND_USAGE_REPORT": {
"TIME_GRANULARITY": "HOURLY",
"INCLUDE_RESOURCES": "TRUE",
"INCLUDE_SPLIT_COST_ALLOCATION_DATA": "TRUE"
}
}
},
"DestinationConfigurations": {
"S3Destination": {
"S3Bucket": "wiv-cur2-123456789012",
"S3Prefix": "wiv",
"S3Region": "us-east-1",
"S3OutputConfigurations": {
"OutputType": "CUSTOM",
"Format": "PARQUET",
"Compression": "SNAPPY",
"Overwrite": "OVERWRITE_REPORT"
}
}
},
"RefreshCadence": {
"Frequency": "SYNCHRONOUS"
}
}' \
--region us-east-1
Step 4: Wait for Data Delivery
First data delivery takes up to 24 hours
Data will appear at: s3://wiv-cur2-{account}/wiv/Wiv-CUR/data/BILLING_PERIOD=YYYY-MM/
Check status in Billing → Data Exports
Step 5: Create Glue Database (for existing customer skip to 7)
Console:
Go to AWS Glue → Databases → Add database
Database name: wivdb
Click Create database
CLI:
aws glue create-database \
--database-input '{"Name": "wivdb"}' \
--region us-east-1
Step 6: Create Athena Workgroup
Console:
Go to Athena → Workgroups → Create workgroup
Name: WivWorkspace
Query result location: s3://wiv-cur2-123456789012/query-results/
Click Create workgroup
CLI:
aws athena create-work-group \
--name WivWorkspace \
--configuration "ResultConfiguration={OutputLocation=s3://wiv-cur2-123456789012/query-results/}" \
--region us-east-1
Step 7: Create Athena Table with Partition Projection
Run this in Athena (replace 123456789012 with your account ID):
CREATE EXTERNAL TABLE wivdb.wiv_cur2 (
bill_bill_type string,
bill_billing_entity string,
bill_billing_period_end_date timestamp,
bill_billing_period_start_date timestamp,
bill_invoice_id string,
bill_invoicing_entity string,
bill_payer_account_id string,
bill_payer_account_name string,
capacity_reservation_capacity_reservation_arn string,
capacity_reservation_capacity_reservation_status string,
capacity_reservation_capacity_reservation_type string,
cost_category map<string,string>,
discount map<string,double>,
discount_bundled_discount double,
discount_total_discount double,
identity_line_item_id string,
identity_time_interval string,
line_item_availability_zone string,
line_item_blended_cost double,
line_item_blended_rate string,
line_item_currency_code string,
line_item_legal_entity string,
line_item_line_item_description string,
line_item_line_item_type string,
line_item_net_unblended_cost double,
line_item_net_unblended_rate string,
line_item_normalization_factor double,
line_item_normalized_usage_amount double,
line_item_operation string,
line_item_product_code string,
line_item_resource_id string,
line_item_tax_type string,
line_item_unblended_cost double,
line_item_unblended_rate string,
line_item_usage_account_id string,
line_item_usage_account_name string,
line_item_usage_amount double,
line_item_usage_end_date timestamp,
line_item_usage_start_date timestamp,
line_item_usage_type string,
line_item_user_identifier string,
pricing_currency string,
pricing_lease_contract_length string,
pricing_offering_class string,
pricing_public_on_demand_cost double,
pricing_public_on_demand_rate string,
pricing_purchase_option string,
pricing_rate_code string,
pricing_rate_id string,
pricing_term string,
pricing_unit string,
product map<string,string>,
product_comment string,
product_fee_code string,
product_fee_description string,
product_from_location string,
product_from_location_type string,
product_from_region_code string,
product_instance_family string,
product_instance_type string,
product_instancesku string,
product_location string,
product_location_type string,
product_operation string,
product_pricing_unit string,
product_product_family string,
product_region_code string,
product_servicecode string,
product_sku string,
product_to_location string,
product_to_location_type string,
product_to_region_code string,
product_usagetype string,
reservation_amortized_upfront_cost_for_usage double,
reservation_amortized_upfront_fee_for_billing_period double,
reservation_availability_zone string,
reservation_effective_cost double,
reservation_end_time string,
reservation_modification_status string,
reservation_net_amortized_upfront_cost_for_usage double,
reservation_net_amortized_upfront_fee_for_billing_period double,
reservation_net_effective_cost double,
reservation_net_recurring_fee_for_usage double,
reservation_net_unused_amortized_upfront_fee_for_billing_period double,
reservation_net_unused_recurring_fee double,
reservation_net_upfront_value double,
reservation_normalized_units_per_reservation string,
reservation_number_of_reservations string,
reservation_recurring_fee_for_usage double,
reservation_reservation_a_r_n string,
reservation_start_time string,
reservation_subscription_id string,
reservation_total_reserved_normalized_units string,
reservation_total_reserved_units string,
reservation_units_per_reservation string,
reservation_unused_amortized_upfront_fee_for_billing_period double,
reservation_unused_normalized_unit_quantity double,
reservation_unused_quantity double,
reservation_unused_recurring_fee double,
reservation_upfront_value double,
resource_tags map<string,string>,
savings_plan_amortized_upfront_commitment_for_billing_period double,
savings_plan_end_time string,
savings_plan_instance_type_family string,
savings_plan_net_amortized_upfront_commitment_for_billing_period double,
savings_plan_net_recurring_commitment_for_billing_period double,
savings_plan_net_savings_plan_effective_cost double,
savings_plan_offering_type string,
savings_plan_payment_option string,
savings_plan_purchase_term string,
savings_plan_recurring_commitment_for_billing_period double,
savings_plan_region string,
savings_plan_savings_plan_a_r_n string,
savings_plan_savings_plan_effective_cost double,
savings_plan_savings_plan_rate double,
savings_plan_start_time string,
savings_plan_total_commitment_to_date double,
savings_plan_used_commitment double,
split_line_item_actual_usage double,
split_line_item_net_split_cost double,
split_line_item_net_unused_cost double,
split_line_item_parent_resource_id string,
split_line_item_public_on_demand_split_cost double,
split_line_item_public_on_demand_unused_cost double,
split_line_item_reserved_usage double,
split_line_item_split_cost double,
split_line_item_split_usage double,
split_line_item_split_usage_ratio double,
split_line_item_unused_cost double,
tags map<string,string>
)
PARTITIONED BY (billing_period string)
STORED AS PARQUET
LOCATION 's3://wiv-cur2-123456789012/wiv/Wiv-CUR2/data/'
TBLPROPERTIES (
'classification'='parquet',
'compressionType'='snappy',
'parquet.compression'='SNAPPY',
'projection.enabled'='true',
'projection.billing_period.type'='date',
'projection.billing_period.format'='yyyy-MM',
'projection.billing_period.range'='2020-01,NOW',
'projection.billing_period.interval'='1',
'projection.billing_period.interval.unit'='MONTHS',
'storage.location.template'='s3://wiv-cur2-123456789012/wiv/Wiv-CUR2/data/BILLING_PERIOD=${billing_period}'
)
Step 8: Add permissions to WivAccessRole
Edit the WivPayerAccessPolicy policy with the new bucket ARN
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::wiv-cur-123456789012",
"arn:aws:s3:::wiv-cur-123456789012/*",
"arn:aws:s3:::wiv-cur2-123456789012",
"arn:aws:s3:::wiv-cur2-123456789012/*"
]
}
Step 9: Test Your Setup
Basic test:
SELECT * FROM wivdb.wiv_cur2
WHERE billing_period = '2025-12'
LIMIT 10
Cost by service:
SELECT
line_item_product_code AS service,
SUM(line_item_unblended_cost) AS cost
FROM wivdb.wiv_cur2
WHERE billing_period = '2025-12'
GROUP BY line_item_product_code
ORDER BY cost DESC
LIMIT 10
Cost by account:
SELECT
line_item_usage_account_id AS account_id,
line_item_usage_account_name AS account_name,
SUM(line_item_unblended_cost) AS cost
FROM wivdb.wiv_cur2
WHERE billing_period = '2025-12'
GROUP BY 1, 2
ORDER BY cost DESC
Summary
S3 Data Structure
After data delivery, your S3 will look like:
s3://wiv-cur-{account}/
└── wiv/
└── Wiv-CUR/
├── data/
│ ├── BILLING_PERIOD=2025-11/
│ │ └── Wiv-CUR-00001.snappy.parquet
│ └── BILLING_PERIOD=2025-12/
│ └── Wiv-CUR-00001.snappy.parquet
└── metadata/
└── BILLING_PERIOD=2025-12/
└── Wiv-CUR-Manifest.json
Troubleshooting
No data in S3
Wait up to 24 hours for first delivery
Check export status in Billing → Data Exports
Query returns no results
Verify S3 path matches table LOCATION
Check billing_period format matches folder name (YYYY-MM)
Type mismatch errors
Use the exact schema provided above
Key: savings_plan_savings_plan_rate must be double
Partition projection not working
Ensure all TBLPROPERTIES are set correctly
The storage.location.template must match actual S3 path structure
Notes
No Glue Crawler needed - Partition projection handles this automatically
No MSCK REPAIR TABLE needed - New months are discovered automatically
Glue shows 0 partitions - This is normal with partition projection
Multi-account: If using AWS Organizations, management account CUR includes all member accounts
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article