AWSCommitments4 min read

Separate AWS Savings Plans utilization from coverage

Sources checked September 10, 202615 minutes
On this page
THE SHORT ANSWER

Unused commitment means purchased commitment was not consumed, so investigate it before buying more. Compare utilization and coverage for the same dates and accounts. High utilization with low coverage calls for a workload and commitment-fit review, not an automatic purchase.

What you need first

Tool
The AWS Command Line Interface (AWS CLI) sends requests from a terminal. Use a Bash terminal with the CLI configured for the intended account. These commands read Cost Explorer utilization and coverage results.
Access
If you cannot run the AWS CLI, ask a colleague who can retrieve Cost Explorer results for the intended scope to provide these two read-only outputs.
If you do not use that tool
Send an AWS billing or FinOps colleague the account scope and dates. Ask for monthly utilization, monthly coverage, and coverage grouped by SERVICE, INSTANCE_FAMILY and REGION.

Why this is worth a look

Skipping this comparison can lead to a new purchase while existing commitment remains unused. AWS defines utilization from UsedCommitment divided by TotalCommitment, while coverage is the share of eligible usage covered by Savings Plans using On-Demand equivalents.

Run these commands

BASH

Run in a configured Bash terminal. Replace the example dates with a completed historical window before running. The commands retrieve monthly results and coverage groupings without changing resources.

Read Savings Plans utilization and coverage
#!/usr/bin/env bash
set -euo pipefail

# Replace both values with a completed historical window.
# Start must be within 13 months. End is exclusive and must be before today.
START_DATE="2025-08-01"
END_DATE="2025-09-01"

aws ce get-savings-plans-utilization \
  --time-period Start="$START_DATE",End="$END_DATE" \
  --granularity MONTHLY \
  --query 'SavingsPlansUtilizationsByTime[].{Period:TimePeriod,UtilizationPercentage:Utilization.UtilizationPercentage,TotalCommitment:Utilization.TotalCommitment,UsedCommitment:Utilization.UsedCommitment,UnusedCommitment:Utilization.UnusedCommitment}' \
  --output table

aws ce get-savings-plans-coverage \
  --time-period Start="$START_DATE",End="$END_DATE" \
  --granularity MONTHLY \
  --query 'SavingsPlansCoverages[].{Period:TimePeriod,SpendCoveredBySavingsPlans:Coverage.SpendCoveredBySavingsPlans,OnDemandCost:Coverage.OnDemandCost,CoveragePercentage:Coverage.CoveragePercentage}' \
  --output table

aws ce get-savings-plans-coverage \
  --time-period Start="$START_DATE",End="$END_DATE" \
  --group-by Type=DIMENSION,Key=SERVICE \
  --query 'SavingsPlansCoverages[].{Period:TimePeriod,Attributes:Attributes,SpendCoveredBySavingsPlans:Coverage.SpendCoveredBySavingsPlans,OnDemandCost:Coverage.OnDemandCost,CoveragePercentage:Coverage.CoveragePercentage}' \
  --output json

aws ce get-savings-plans-coverage \
  --time-period Start="$START_DATE",End="$END_DATE" \
  --group-by Type=DIMENSION,Key=INSTANCE_FAMILY \
  --query 'SavingsPlansCoverages[].{Period:TimePeriod,Attributes:Attributes,SpendCoveredBySavingsPlans:Coverage.SpendCoveredBySavingsPlans,OnDemandCost:Coverage.OnDemandCost,CoveragePercentage:Coverage.CoveragePercentage}' \
  --output json

aws ce get-savings-plans-coverage \
  --time-period Start="$START_DATE",End="$END_DATE" \
  --group-by Type=DIMENSION,Key=REGION \
  --query 'SavingsPlansCoverages[].{Period:TimePeriod,Attributes:Attributes,SpendCoveredBySavingsPlans:Coverage.SpendCoveredBySavingsPlans,OnDemandCost:Coverage.OnDemandCost,CoveragePercentage:Coverage.CoveragePercentage}' \
  --output json

How to confirm it

  1. 01

    Choose matching dates and accounts

    Replace START_DATE and END_DATE with a completed historical review window. Start is inclusive and must be within 13 months. End is exclusive, must follow Start, and must be before today. Use the same account context for every request. An organization management account can see member-account results.

  2. 02

    Read commitment use and coverage together

    Run the first two commands and compare matching monthly periods. Record UnusedCommitment beside UtilizationPercentage and CoveragePercentage. Treat them as different measures because utilization describes consumed commitment while coverage describes eligible usage covered.

  3. 03

    Locate uncovered usage

    Run the remaining commands to review coverage by SERVICE, INSTANCE_FAMILY and REGION. Read Attributes for each group. Keep these requests separate from monthly coverage because coverage cannot combine grouping with granularity, and utilization cannot be grouped.

  4. 04

    Choose the next review

    Pause a purchase decision when UnusedCommitment is above zero and ask the workload owner to investigate why commitment was not consumed. When utilization is high but coverage is low, review workload stability and commitment fit. Do not treat a coverage percentage as a purchase amount.

Before making changes

Assumes the CLI is configured for the intended account scope and that the requested dates are completed historical dates. These unfiltered commands do not isolate a selected member account. Coverage includes the public On-Demand rate and On-Demand equivalents, not contracted pricing or a complete bill. Percentage, commitment and cost fields are returned as strings. Confirm currency before using amounts in a financial calculation.

Skip this review if the intended accounts have no Savings Plans, or an approved FinOps report already provides utilization, unused commitment and coverage for the same accounts and dates.

Primary sources