Separate AWS Savings Plans utilization from coverage
On this page
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
BASHRun 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.
#!/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 jsonHow to confirm it
- 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.
- 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.
- 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.
- 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.