AWS Cost Explorer’s default Reserved Instance coverage report will show you a single percentage. If that number is above 80%, most FinOps dashboards colour it green. The problem is that the number is an aggregate across every instance family in your account — and T2, T3, and T4g instances behave so differently from compute-optimised or memory-optimised families that averaging them together produces a metric that can mislead you about your actual exposure.
A fleet that is 95% covered on T3 and 0% covered on C6i is a fleet with an unprotected compute tier. The aggregate report will show you something like 72% and flag it amber. Nobody panics. Nobody fixes C6i. The on-demand overage keeps accumulating.
What the aggregation does wrong
Cost Explorer’s RI coverage calculation is straightforward: covered_hours / total_hours across all EC2 usage in the selected scope, time range, and any filters you’ve applied. When you look at the default “All instance families” view without filtering, that denominator includes every T3, T4g, M6i, C6i, R6i, and X2iezn hour your account consumed. The numerator is every hour that had a matching RI applied.
Burstable instances (the T family) have two properties that inflate this ratio in misleading ways.
First, T-family instances are cheap per hour. A t3.medium On-Demand rate is $0.0416/hour. A c6i.4xlarge is $0.68/hour — 16x more expensive. If you have 1,000 T3 hours/day covered by RIs and 100 C6i hours/day running unprotected On-Demand, the aggregate coverage looks high while the uncovered spend is overwhelmingly in C6i. The metric is hour-weighted, not dollar-weighted, by default.
Second, T-family RIs are cheap to buy. A 1-year No-Upfront t3.medium RI costs roughly $0.026/hour. The savings rate is real but the absolute cost is low. Teams buy T-family RIs to hit coverage targets — they are the easiest hours to cover — and then de-prioritise the compute-optimised family where the On-Demand exposure is ten times larger per instance.
The result is a coverage metric that is technically correct and operationally useless.
The corrected query: per-family coverage via AWS CLI
Cost Explorer’s API gives you the raw data to compute per-family coverage correctly. The following query returns RI coverage broken down by instance family for the trailing 30 days:
aws ce get-reservation-coverage \
--time-period Start=$(date -d '30 days ago' '+%Y-%m-%d'),End=$(date '+%Y-%m-%d') \
--granularity MONTHLY \
--group-by Type=DIMENSION,Key=INSTANCE_TYPE_FAMILY \
--filter '{
"Dimensions": {
"Key": "SERVICE",
"Values": ["Amazon Elastic Compute Cloud - Compute"],
"MatchOptions": ["EQUALS"]
}
}' \
--metrics CoverageHours CoverageNormalizedUnits \
--output json \
| jq -r '
.CoveragesByTime[].Groups[]
| [
.Attributes.INSTANCE_TYPE_FAMILY,
.Coverage.CoverageHours.CoverageHoursPercentage,
.Coverage.CoverageNormalizedUnits.CoverageNormalizedUnitsPercentage
]
| @tsv
' \
| sort -t$'\t' -k2 -n
The output is a tab-separated list: instance family, hour-based coverage %, normalised-unit coverage %. Sort ascending so the worst-covered families surface at the top.
On a typical mid-market AWS account, this query produces something like:
| Instance family | Hour coverage | Normalised unit coverage |
|---|---|---|
| c6i | 12% | 11% |
| r6i | 23% | 19% |
| m6i | 41% | 38% |
| c5 | 67% | 64% |
| t3 | 94% | 91% |
| t4g | 89% | 87% |
The aggregate number for this account might read 68% — nominally acceptable. The C6i family is at 12% and nobody flagged it because the green-amber-red dashboard only looked at the top-line.
Why burstable workloads are a poor RI target anyway
Before you pivot to buying a stack of C6i RIs, it is worth understanding why T-family instances are covered at high rates in the first place — and why that strategy is rational for the T family even if it obscures C6i exposure.
Burstable instances run on CPU credits. When a T3 instance bursts above its baseline, it draws credits; when it sits idle, it earns them. The actual CPU utilisation pattern for most T-family workloads is low and variable — a dev server that sits at 5% CPU for 23 hours and spikes to 80% for one hour. This is the definition of a workload that is worth reserving: it is always running (so the RI hours never go to waste) but rarely consuming much compute (so you are not buying compute headroom you never use).
The problem is that “always running” and “cheap per hour” together make T-family the easiest possible RI purchase. It is also the one that contributes the least absolute dollar savings.
For C6i and R6i, the calculus is different. These instances are more likely to be running batch or ETL workloads that are highly variable in count — you might run 20 c6i.4xlarge instances for a nightly batch window and zero the rest of the day. That is a poor RI match for a standard commitment. The right instrument is a Compute Savings Plan, not an instance-family RI, because a Savings Plan covers any compute usage matching your commitment rate regardless of instance type, family, region, or OS.
| Workload pattern | Best coverage instrument | Why |
|---|---|---|
| Always-on, same instance type (dev/staging) | Instance RI, 1-year No-Upfront | Maximum discount, predictable usage |
| Always-on, instance type varies (EKS node groups) | Compute Savings Plan | Covers across families as nodes scale |
| Bursty batch (nightly ETL) | Compute Savings Plan or Spot + On-Demand blend | RIs waste during idle hours |
| Highly variable (auto-scaling web tier) | Compute Savings Plan at baseline commitment | Covers baseline, On-Demand handles burst |
| Dev/non-prod that could be stopped | No RI — schedule stop/start | Don’t commit to hours you can eliminate |
The three failure modes that inflate aggregate coverage
Failure mode 1: RI purchases timed to beat the quarterly review. When the FinOps report is due at quarter-end, teams buy cheap T-family RIs to move the aggregate needle before the all-hands. C6i RIs cost ten times as much per reservation and take longer to justify. They get pushed to next quarter.
Failure mode 2: Legacy RIs from a different workload shape. A 3-year RI purchased in 2022 for a fleet of m5.xlarge instances might have 18 months left on it and no matching On-Demand usage in that family — because the team migrated to ARM-based m7g instances in 2023. The RI is counted as covered in the report even though the instance it was bought for no longer exists in the fleet. The metric is correct by definition; the business value is gone.
Failure mode 3: Shared-account aggregation across teams. When multiple engineering teams share an AWS organisation and RI coverage is reported at the Payer account level, a team that bought deep coverage for a T3-heavy staging environment subsidises the coverage metric for a team running unprotected C6i production workloads. Neither team knows this without the per-family breakout.
What to do with the per-family view
Once you have the per-family coverage query output, the workflow is:
- Identify any compute-optimised or memory-optimised family below 40% coverage.
- For each under-covered family, check the usage pattern: is it steady-state (always on, consistent count) or bursty?
- Steady-state families with consistent instance types: price a 1-year No-Upfront RI. The break-even versus On-Demand is typically 5-7 months; year one savings net of the commitment are in the 20-30% range on the compute line.
- Bursty families: model a Compute Savings Plan at 60-70% of average hourly commitment. The remaining 30-40% runs On-Demand or Spot.
- Families with under 20% utilisation of existing RIs: you have over-purchased. Stop buying in this family until the existing RIs are absorbed.
The per-family view does not require any third-party tooling — it is available through the Cost Explorer API with the query above. Run it once a month, track the per-family trend, and stop using the aggregate number as your primary RI health metric.
If you want a structured view of which instance families are costing the most On-Demand per month alongside your existing RI and Savings Plan coverage, the Cost X-Ray produces this breakout as part of the initial cloud spend assessment.