Why don't AWS invoice service charges match AWS Cost Explorer or AWS Cost and Usage Report charges?
Ever noticed that your AWS invoice charges don't match what you see in AWS Cost Explorer or the AWS Cost and Usage Report (CUR)? You're not alone. This happens because Data Transfer charges appear separately on your invoice but are bundled with their originating service in Cost Explorer and CUR. This guide walks you through the filtering and aggregation steps needed to reconcile charges across all your billing tools.
When you try to reconcile charges between your AWS invoice and AWS Cost Explorer or the AWS Cost and Usage Report (CUR) as part of your compliance processes, you might find that certain service charges don't match. You might first notice this with Amazon Elastic Compute Cloud (Amazon EC2), but discrepancies can also occur with Amazon Relational Database Service (Amazon RDS), Amazon Simple Storage Service (Amazon S3), and other services.
TL;DR: This happens because Data Transfer charges are reported as a separate service line item on the Bills page of the AWS Billing and Cost Management console. In Cost Explorer and CUR, those same charges are reported under the service that generated them.
To reconcile your invoice with Cost Explorer or CUR, aggregate costs by Unblended costs, filter in the desired service charges, and filter out Data Transfer charges for those services.
Read on for a detailed explanation and step-by-step instructions.
How charges appear on your invoice
Service charges on your invoice are split into multiple charge types that can vary according to your purchase options and commercial agreements.
Typically, both the total cost (excluding tax) and the Charges line item (which corresponds to on-demand usage) don't match the charges in Cost Explorer or CUR. However, the other charge types do match when you filter or group them separately. This discrepancy occurs because the service charges exclude Data Transfer charges, which are reported in their own section as a separate service.
Amazon EC2 is a particularly notable example because it typically involves multiple purchase options. In Cost Explorer, Amazon EC2 is split into two services: EC2-Instances (running hours and EC2 Data Transfer Out charges) and EC2 - Other (all other EC2 Data Transfer charges and supporting services, such as Amazon Elastic Block Store (Amazon EBS) and NAT gateways, among others). In CUR, this separation doesn't exist — all EC2 charges, including Data Transfer, Amazon EBS, and related charges, are reported with line_item_product_code = 'AmazonEC2'.
The Knowing the differences between Billing and Cost Explorer data documentation describes this behavior:
For example, let's say that you want to understand compute costs for Amazon Elastic Compute Cloud compared to ancillary cost, such as Amazon Elastic Block Store volumes or NAT gateways. Instead of a single group for Amazon EC2 costs, Cost Explorer will group costs into EC2 - Instances and EC2 - Other.
In another example, to help analyze data transfer costs, Cost Explorer groups your transfer costs by service. In billing data, data transfer costs are grouped into a single service named Data Transfer.
The following sections show how to apply the correct filters in Cost Explorer and CUR to reconcile your charges.
Cost Explorer
Amazon EC2
To match Amazon EC2 charges in AWS Cost Explorer, follow these steps:
- In Advanced options (near the bottom of the rightmost column), set Aggregate costs by to
Unblended Costs. - Set Dimension to
Charge Type. - Apply the following filters:
- Service — include
EC2 - OtherandEC2-Instances. - Usage Type Group — exclude all groups that start with
EC2: Data Transfer. - Usage Type — exclude all types that contain
VpcPeering.
- Service — include
Once filtered, sum these values to match your invoice costs:
- Service Total Cost — Sum the Cost Explorer Total Costs with the invoice Tax line item. Tax in Cost Explorer is reported as a separate service, so it's excluded from the filters above.
- Service Charges — Sum all non-negative Cost Explorer values, such as
Usage,Savings Plans Covered Usage, andRecurring Reservation Fee. - Other invoiced charges — These should match their equivalent charge type in Cost Explorer (for example,
Credits,RI Volume Discount, orCross-Service Discount).
Note: If you have a Savings Plans Private Pricing Agreement (PPA), your Cost Explorer
Savings Plan Covered UsageandPrivate Pricing Agreementvalues will not match the invoice values.This is due to how the PPA is applied to Savings Plans — fees are always reported as net costs, even if you don't select
Net AmortizedorNet Unblendedin Cost Explorer. PPA savings for Savings Plans are not reported separately from the fees in Cost Explorer, whereas on the invoice they are. As a result, the Cost Explorer Covered Usage will be larger than the invoice amount, while the PPA Discount will be smaller.
CUR
This section provides Amazon Athena queries for both CUR 2.0 and CUR Legacy formats. If you're setting up a new report, AWS recommends using CUR 2.0.
These queries assume you have a Cross-Service Discount Private Pricing Agreement (previously known as Enterprise Discount Program, or EDP) with AWS. If you don't, adjust the queries by removing the lines that reference EDP discounts, as noted in the SQL comments.
Prerequisites: You need Amazon Athena configured with your CUR data. Replace all <PLACEHOLDER> values in the queries below with your own account details.
CUR 2.0
Run this query in Amazon Athena. Replace the placeholders and adjust the billing_period to the invoice month you want to reconcile. For details on CUR 2.0 column names, see the CUR 2.0 data dictionary.
with filtered_data as ( select line_item_line_item_type, line_item_unblended_cost, -- If you don't have an EDP, delete the line below and the comma above discount['edp_discount'] as edp_discount from <CUR_TABLE> where -- Adjust to the invoice month (format: YYYY-MM) billing_period = '<YYYY-MM>' -- Adjust to the desired service and line_item_product_code = 'AmazonEC2' -- Adjust to your payer account ID and bill_payer_account_id = '<PAYER_ACCOUNT_ID>' and line_item_line_item_type not in ('DiscountedUsage', 'EdpDiscount') and coalesce(product_product_family, '') <> 'Data Transfer' and coalesce(line_item_usage_type, '') not like '%VpcPeering%' ) -- Aggregates charges by invoice charge type select case when line_item_line_item_type in ('Usage', 'SavingsPlanCoveredUsage', 'RIFee') then 'Charges' when line_item_line_item_type = 'RiVolumeDiscount' then 'Discount (RI Volume Discount)' when line_item_line_item_type = 'PrivateRateDiscount' then 'Discount (Private Rate Card)' when line_item_line_item_type = 'SavingsPlanNegation' then 'Savings Plan (Charges covered by Savings Plans)' else line_item_line_item_type end as "Invoice Charge Type", round(sum(line_item_unblended_cost), 2) as "cost" from filtered_data group by 1 -- If you don't have an EDP, delete everything below this line UNION ALL select 'Discount (Enterprise Discount Program)' as "Invoice Charge Type", round(sum(edp_discount), 2) as "cost" from filtered_data where line_item_line_item_type in ('Usage', 'RIFee') order by "cost" desc
CUR Legacy
Run this query in Amazon Athena. Replace the placeholders and adjust the year||month value to the invoice month you want to reconcile. For details on CUR Legacy column names, see the CUR Legacy data dictionary.
with filtered_data as ( select line_item_line_item_type, line_item_unblended_cost, -- If you don't have an EDP, delete the line below and the comma above discount_edp_discount as edp_discount from <CUR_TABLE> where -- Adjust to the invoice month (format: YYYYMM) year||month = '<YYYYMM>' -- Adjust to the desired service and line_item_product_code = 'AmazonEC2' -- Adjust to your payer account ID -- Note: the payer field might not be available in all CUR Legacy -- configurations. Adjust this filter based on your Athena table schema. and payer = '<PAYER_ACCOUNT_ID>' and line_item_line_item_type not in ('DiscountedUsage', 'EdpDiscount') and product_product_family <> 'Data Transfer' and line_item_usage_type not like '%VpcPeering%' ) -- Aggregates charges by invoice charge type select case when line_item_line_item_type in ('Usage', 'SavingsPlanCoveredUsage', 'RIFee') then 'Charges' when line_item_line_item_type = 'RiVolumeDiscount' then 'Discount (RI Volume Discount)' when line_item_line_item_type = 'PrivateRateDiscount' then 'Discount (Private Rate Card)' when line_item_line_item_type = 'SavingsPlanNegation' then 'Savings Plan (Charges covered by Savings Plans)' else line_item_line_item_type end as "Invoice Charge Type", round(sum(line_item_unblended_cost), 2) as "cost" from filtered_data group by 1 -- If you don't have an EDP, delete everything below this line UNION ALL select 'Discount (Enterprise Discount Program)' as "Invoice Charge Type", round(sum(edp_discount), 2) as "cost" from filtered_data where line_item_line_item_type in ('Usage', 'RIFee') order by "cost" desc
Other services
For other services such as Amazon RDS and Amazon ElastiCache, repeat the Amazon EC2 process above, changing the Service filter to the target service. Note that not all services have a Usage Type Group for Data Transfer. In those cases, filter out Usage Type values that contain:
- DataTransfer-Regional-Bytes
- DataTransfer-Out-Bytes
- -AWS-Out-Bytes
- VpcPeering
Some services also have charges reported in separate invoice sections. For example, Amazon S3 has Amazon S3 Glacier Deep Archive charges listed separately. Adjust the filters and sums accordingly.
- Language
- English
Relevant content
- asked a month ago
AWS OFFICIALUpdated 4 months ago
AWS OFFICIALUpdated 3 years ago
AWS OFFICIALUpdated 3 years ago
AWS OFFICIALUpdated a year ago