Photo by Kenny Eliason on Unsplash

Part 1: Analyzing AWS’ cost measures

Christopher Harris
Understanding the AWS CUR
5 min readMay 18, 2024

--

My name is Christopher Harris, and I am a maintainer on the FinOps FOCUS project. I’ve built cost management products at Datadog and CloudHealth (Broadcom) over the past 8 years, and I’m excited to share some of what I’ve learned with you.

The AWS CUR provides 3 broad cost types (Accrual, Amortized, and Blended) for customers to aggregate costs over billing periods.

What are accrual costs?

Investopedia defines accrual asexpenses recognized on the books before they have been paid [and] are recorded in the accounting period in which they are incurred”.

For example, when I rent a cloud resource, my charges will accrue hourly, but I will only pay the cloud at the end of the billing period for the sum of all the instance’s running hours — not after each hour.

What are amortized costs?

Investopedia defines amortization as “the accounting practice of spreading the cost of an intangible asset over its useful life”.

For example, if I prepay $31 for a service in Jan 2024 as my BilledCost, my amortized cost (or EffectiveCost) is $1/day.

+-------------------+-------------+------------+---------------+
| ChargePeriodStart | ResourceId | BilledCost | EffectiveCost |
+-------------------+-------------+------------+---------------+
| 2024-01-01 | i-123456789 | $31 | $1 |
| 2024-01-02 | i-123456789 | $0 | $1 |
| |
| ... 27 days ... |
| |
| 2024-01-30 | i-123456789 | $0 | $1 |
| 2024-01-31 | i-123456789 | $0 | $1 |
+-------------------+-------------+------------+---------------+

Amortized Cost: $31 / 31 days = $1/day

What are blended costs?

Investopedia defines a blended rate as “an interest rate charged on a loan that represents the combination of a previous rate and a new rate”. Translated, the total blended cost is derived from the rolled-up average of rates.

For example, if I rent a service for 1 day with an on-demand rate ($1/hour) and a subsequent day with a discounted rate ($0.50/hour), my blended cost across those 2 days is $18.

+-------------------+--------------+------------+-------------+
| ChargePeriodStart | ResourceId | BilledCost | BlendedCost |
+-------------------+--------------+------------+-------------+
| 2024-01-01 | cool-service | $24 | $18 |
| 2024-01-02 | cool-service | $12 | $18 |
+-------------------+--------------+------------+-------------+

Blended Cost: ($1/hour * 24 hours + $0.50/hour * 24 hours) / 2 = $18

How does this apply to the CUR?

The AWS CUR provides 2 accrual cost columns that (will) match the final invoice amount, barring any manually applied discounts from AWS:

  • lineItem/UnblendedCost: Accrued costs over a billing period
  • lineItem/NetUnblendedCost: Accrued costs over a billing period inclusive of AWS discounts. This column only exists if discounted rates are applied.

The sum of lineItem/UnblendedCost (or lineItem/NetUnblendedCost if included) matches the invoice’s total amount after all costs are included.

AWS also provides 1 blended cost column, lineItem/BlendedCost, as the cost that is based on the average rate across on-demand and commitment costs over a billing period.

The total unblended, net unblended, and blended cost over a billing period can be expressed in AWS Athena as:

SELECT 
SUM(line_item_unblended_cost) AS unblended_cost,
SUM(line_item_net_unblended_cost) AS net_unblended_cost,
SUM(line_item_blended_cost) AS blended_cost
FROM
<cur>
WHERE
month(bill_billing_period_start_date) = <month>
AND
year(bill_billing_period_start_date) = <year>

where each placeholder value should be replaced as:

  • <cur> is the database and table created from a CUR integration
  • <year> is YYYY (ex: 2024)
  • <month> is MM (ex: 05).

What about amortized and net amortized costs?

The AWS CUR does not provide amortized cost columns like lineItem/AmortizedCost and lineItem/NetAmortizedCost within the CUR. However, AWS does provide these cost measures through Cost Explorer.

So, how do you derive amortized and net amortized costs within the CUR?

Amortized Cost

Accurately calculating the CUR’s monthly, amortized cost is more complicated than calculating accrued costs.

There are 7 scenarios to consider when aggregating amortized cost for a billing period:

  • When line_item_line_item_type is SavingsPlanNegation or SavingsPlanUpfrontFee → 0
  • When line_item_line_item_type is Fee and reservation_reservation_a_r_n is empty → 0
  • When line_item_line_item_type is DiscountedUsagereservation_effective_cost
  • When line_item_line_item_type is SavingsPlanCoveredUsagesavings_plan_effective_cost
  • When line_item_line_item_type is RIFee then use the sum of reservation_unused_amortized_upfront_fee_for_billing_period + reservation_unused_recurring_fee
  • When line_item_line_item_type is SavingsPlanCoveredUsagesavings_plan_total_commitment_to_date -savings_plan_used_commitment
  • For all other rows → line_item_unblended_cost

Altogether, the amortized cost of a billing period can be expressed in AWS Athena as:

SELECT
SUM(
CASE
WHEN line_item_line_item_type IN ('SavingsPlanNegation', 'SavingsPlanUpfrontFee') THEN
0
WHEN line_item_line_item_type = 'Fee' AND reservation_reservation_a_r_n <> '' THEN
0
WHEN line_item_line_item_type = 'SavingsPlanCoveredUsage' THEN
savings_plan_savings_plan_effective_cost
WHEN line_item_line_item_type = 'SavingsPlanRecurringFee' THEN
savings_plan_total_commitment_to_date - savings_plan_used_commitment
WHEN line_item_line_item_type = 'RIFee' THEN
reservation_unused_amortized_upfront_fee_for_billing_period + reservation_unused_recurring_fee
WHEN line_item_line_item_type = 'DiscountedUsage' THEN
reservation_effective_cost
ELSE line_item_unblended_cost
END
) AS amortized_cost
FROM
<cur>
WHERE
month(bill_billing_period_start_date) = <month>
AND
year(bill_billing_period_start_date) = <year>

where each placeholder value should be replaced as:

  • <cur> is the database and table created from a CUR integration
  • <year> is YYYY (ex: 2024)
  • <month> is MM (ex: 5).

Net Amortized Cost

Accurately calculating the CUR’s monthly, net amortized cost differs slightly from calculating non-net amortized costs:

  • When line_item_line_item_type is SavingsPlanNegation or SavingsPlanUpfrontFee → 0
  • When line_item_line_item_type is Fee and reservation_reservation_a_r_n is empty → 0
  • When line_item_line_item_type is DiscountedUsagereservation_net_effective_cost
  • When line_item_line_item_type is SavingsPlanCoveredUsagesavings_plan_net_effective_cost
  • When line_item_line_item_type is RIFeereservation_net_unused_amortized_upfront_fee_for_billing_period + reservation_net_unused_recurring_fee
  • When line_item_line_item_type is SavingsPlanCoveredUsage then:
    - When savings_plan_payment_option is No Upfront → COALESCE(savings_plan_net_recurring_commitment_for_billing_period, 1) / COALESCE(savings_plan_recurring_commitment_for_billing_period, 1) * (savings_plan_total_commitment_to_date — savings_plan_used_commitment)
    - When savings_plan_payment_option is Partial Upfront or All Upfront → COALESCE(savings_plan_net_amortized_upfront_commitment_for_billing_period, 1) / COALESCE(savings_plan_amortized_upfront_commitment_for_billing_period, 1) *
    (savings_plan_total_commitment_to_date — savings_plan_used_commitment)
  • For all other rows → line_item_net_unblended_cost

Additionally, while a Partial Upfront savings plan can calculate its net discount ratio from net amortized and amortized recurring fee column values, an All Upfront savings plan cannot.

Altogether, the net amortized cost of a billing period can be expressed in AWS Athena as:

SELECT
SUM(
CASE
WHEN line_item_line_item_type IN ('SavingsPlanNegation', 'SavingsPlanUpfrontFee') THEN
0
WHEN line_item_line_item_type = 'Fee' AND reservation_reservation_a_r_n <> '' THEN
0
WHEN line_item_line_item_type = 'SavingsPlanCoveredUsage' THEN
savings_plan_net_savings_plan_effective_cost
WHEN line_item_line_item_type = 'SavingsPlanRecurringFee' THEN
CASE
WHEN savings_plan_payment_option IN ('No Upfront', 'Partial Upfront') THEN COALESCE(savings_plan_net_recurring_commitment_for_billing_period, 1) / COALESCE(savings_plan_recurring_commitment_for_billing_period, 1)
WHEN savings_plan_payment_option = 'All Upfront' THEN COALESCE(savings_plan_net_amortized_upfront_commitment_for_billing_period, 1) / COALESCE(savings_plan_amortized_upfront_commitment_for_billing_period, 1)
END * (savings_plan_total_commitment_to_date - savings_plan_used_commitment)
WHEN line_item_line_item_type = 'RIFee' THEN
reservation_net_unused_amortized_upfront_fee_for_billing_period + reservation_net_unused_recurring_fee
WHEN line_item_line_item_type = 'DiscountedUsage' THEN
reservation_net_effective_cost
ELSE
line_item_net_unblended_cost
END
) AS net_amortized_cost
FROM
<cur>
WHERE
month(bill_billing_period_start_date) = <month>
AND
year(bill_billing_period_start_date) = <year>

where each placeholder value should be replaced as:

  • <cur> is the database and table created from a CUR integration
  • <year> is YYYY (ex: 2024)
  • <month> is MM (ex: 5)

Check out my other stories about Understanding the AWS CUR.

--

--

Christopher Harris
Understanding the AWS CUR

I am a maintainer on the FinOps FOCUS project and have built cost management products at Datadog and CloudHealth (Broadcom) over the past 8 years.