AWSCommitments5 min read

Separate AWS Savings Plans utilization from coverage

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

Run utilization and coverage requests for the same dates and scope. High utilization with low coverage means the existing commitment is being used while eligible usage remains uncovered. Review workload stability, commitment fit, and scope before considering another purchase.

Why this is worth a look

Utilization and coverage describe different relationships. AWS defines UtilizationPercentage as UsedCommitment divided by TotalCommitment. CoveragePercentage is existing Savings Plans covered usage divided by all eligible Savings Plans usage. Compare both over the same window. Grouped coverage can show where uncovered eligible usage is concentrated by service, instance family, or Region. Coverage granularity and grouping are separate request modes because GetSavingsPlansCoverage does not allow both together.

Start with this query

BASH

AWS CLI commands for utilization, ungrouped time-series coverage, and complete grouped coverage views. Replace the example dates before reviewing another period.

Run a read-only AWS Savings Plans review
#!/usr/bin/env bash
set -euo pipefail

START_DATE="2026-08-01"
END_DATE="2026-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 \
  --metrics SpendCoveredBySavingsPlans \
  --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 \
  --metrics SpendCoveredBySavingsPlans \
  --query 'SavingsPlansCoverages[].{Service:Attributes.Service,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=INSTANCE_FAMILY \
  --metrics SpendCoveredBySavingsPlans \
  --query 'SavingsPlansCoverages[].{InstanceFamily:Attributes.InstanceFamily,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=REGION \
  --metrics SpendCoveredBySavingsPlans \
  --query 'SavingsPlansCoverages[].{Region:Attributes.Region,SpendCoveredBySavingsPlans:Coverage.SpendCoveredBySavingsPlans,OnDemandCost:Coverage.OnDemandCost,CoveragePercentage:Coverage.CoveragePercentage}' \
  --output table

How to confirm it

  1. 01

    Set the review dates

    Edit START_DATE and END_DATE in the command. Start is inclusive, End is exclusive, End must be after Start and before the current date, and Start must be within 13 months.

  2. 02

    Run utilization

    Run the first command with DAILY or MONTHLY granularity. Read UtilizationPercentage, TotalCommitment, UsedCommitment, and UnusedCommitment. AWS returns these values as strings, so compare results from the same request and period.

  3. 03

    Run time-series coverage

    Run the second command separately with DAILY or MONTHLY granularity. Read SpendCoveredBySavingsPlans, OnDemandCost, and CoveragePercentage for the ungrouped period. OnDemandCost is eligible usage cost at the public On-Demand rate.

  4. 04

    Run grouped coverage

    Run the grouped commands without Granularity. Each command changes both the group key and its output projection: Service with Attributes.Service, InstanceFamily with Attributes.InstanceFamily, or Region with Attributes.Region. Read the coverage fields by returned group.

  5. 05

    Choose the next investigation

    Compare utilization and coverage for the same dates and scope. High utilization with low coverage means the existing commitment is being used while eligible usage remains uncovered. Low utilization means some purchased commitment was not consumed during the period. Review workload stability, commitment fit, and scope before considering another purchase.

Before making changes

Assumes the AWS CLI is configured for the intended account or organization scope and that your organization authorizes these read-only Cost Explorer operations. The commands use the same dates and return documented values as strings. SpendCoveredBySavingsPlans and OnDemandCost use the On-Demand equivalent of eligible usage; OnDemandCost specifically means the public On-Demand rate, not contracted pricing or a complete billed-cost total. An organization management account can see associated member-account coverage and utilization, so confirm the scope before interpreting totals.

Skip this review when the intended scope has no Savings Plans or an approved FinOps report already provides the same utilization and coverage view.

Primary sources