What are Reserved Instances, EC2 Instance Savings Plans, and Compute Savings Plans?

All three are commitment discounts. You agree to a 1- or 3-year term, and AWS bills matching usage at a lower rate than On-Demand. Each term can be paid no upfront, partial upfront, or all upfront. Paying more upfront generally earns a deeper discount. The three options differ in what you commit to, and that determines how much your fleet can change without wasting the commitment.

  • Reserved Instances (RIs) commit to a configuration: instance family, size, region (or a specific Availability Zone), operating system, and tenancy. Regional Linux RIs with default tenancy get size flexibility within a family. Zonal RIs give up that flexibility in exchange for a capacity reservation in that AZ.
  • EC2 Instance Savings Plans commit to a dollar amount per hour of spend on one instance family in one region. Size, OS, and tenancy can change freely within that family.
  • Compute Savings Plans commit to hourly spend that applies across instance families, sizes, regions, and operating systems. They also cover Fargate and Lambda.
Option Commitment unit What can change without losing the discount Covers Fargate/Lambda
Reserved Instance Instance configuration Size within family (regional Linux, default tenancy only) No
EC2 Instance Savings Plan $/hour, one family + region Size, OS, tenancy No
Compute Savings Plan $/hour, any compute Family, size, region, OS, compute service Yes

Teams buy these commitments for the backend baseline: API servers, workers, and databases that run all day, every day. You would pay On-Demand for that capacity anyway, so committing to it lowers its rate. Autoscaled peaks above the baseline stay on On-Demand or Spot.

How does a Savings Plan commitment work in billing?

The commitment is a dollar amount per hour, measured at Savings Plan rates rather than On-Demand rates. A $10/hour commitment covers usage that would cost $10 at the discounted price, which is more than $10 of On-Demand usage. Each hour is settled independently. Eligible usage draws down the commitment, usage beyond it is billed On-Demand, and any unused portion of that hour is lost. Nothing carries over to the next hour, so a commitment sized to your daytime peak wastes money every night.

Discounts are applied in a fixed order. Reserved Instances apply first, then Savings Plans. Among Savings Plans, the most specific match applies first, so EC2 Instance Savings Plans apply before Compute Savings Plans. Within a plan, the usage with the highest discount percentage is covered first, which gets the most value out of each committed dollar.

One billing hour: eligible usage, top to bottom
┌──────────────────────────────┐
│ Reserved Instances           │ ← matching instances only
├──────────────────────────────┤
│ EC2 Instance Savings Plan    │ ← one family, one region
├──────────────────────────────┤
│ Compute Savings Plan         │ ← highest discount % first
├──────────────────────────────┤
│ On-Demand                    │ ← everything left over
└──────────────────────────────┘
Unused commitment this hour: forfeited

Under consolidated billing, commitments are shared across linked accounts. The purchasing account's usage is covered first, and any remaining commitment flows to the other accounts. You can turn off discount sharing per account. Sharing helps keep utilization high, but it distorts chargeback. The buying team's bill shows the full commitment fee, while other teams get discounted usage they didn't pay for. Use amortized cost views, which spread commitment fees across the usage they actually covered, so each team's cost reflects the discount it received.

   One billing hour: eligible usage across all linked accounts
                               │
                               ▼
 ┌────────────────────────────────────────────────────────────┐
 │ 1. Reserved Instances (applied first)                      │
 │    matching instances only                                 │
 └─────────────────────────────┬──────────────────────────────┘
                               │ uncovered usage
                               ▼
 ┌────────────────────────────────────────────────────────────┐
 │ 2. EC2 Instance Savings Plans (more specific)              │
 │    one instance family in one region                       │
 └─────────────────────────────┬──────────────────────────────┘
                               │ uncovered usage
                               ▼
 ┌────────────────────────────────────────────────────────────┐
 │ 3. Compute Savings Plans                                   │
 │    highest discount % usage covered first                  │
 └──────────────┬──────────────────────────────┬──────────────┘
                │ usage above commitment       │ unused commitment
                ▼                              ▼
 ┌──────────────────────────────┐ ┌──────────────────────────┐
 │ 4. On-Demand rates           │ │ Forfeited at hour end    │
 │    everything left over      │ │ no carryover to next hour│
 └──────────────────────────────┘ └──────────────────────────┘
 Commitment = $/hour measured at Savings Plan rates, not On-Demand.
 Sharing on: each plan covers the buyer's account, then linked accounts.

One billing hour: eligible usage flows through Reserved Instances, then EC2 Instance and Compute Savings Plans, and the remainder is billed On-Demand, while unused commitment for that hour is forfeited.

Savings plans vs reserved instances: what does flexibility cost you?

The more change a commitment survives, the smaller its discount. List prices vary, so the useful question is which of your likely changes each instrument covers.

Instrument New instance family (e.g., to Graviton) Region change EC2 to Fargate Exit option
Compute Savings Plan Yes, automatic Yes Yes None. Cannot be sold or exchanged
Convertible RI Yes, via exchange No No Exchange only, not sale
EC2 Instance Savings Plan No No No None
Standard RI No No No Sometimes sellable on the RI Marketplace, subject to eligibility and buyer demand

Do not count on the Marketplace as an exit. A listing only recovers value if a buyer wants that exact configuration.

Worked example

Illustrative estimate (assumed numbers, not a benchmark). These are not real AWS prices.

Assumed inputs:

  • A steady On-Demand baseline of $10,000/month.
  • A 36-month term.
  • Discounts of 30% for the Compute SP, 35% for the Convertible RI, and 40% for the EC2 Instance SP.
  • At month 18, 40% of the fleet moves to Graviton at the same On-Demand rate.

The formula is:

Total = (monthly commitment × 36) + (uncovered On-Demand × months uncovered)

  • Compute SP: $7,000 × 36 = $252,000. The commitment follows the workload.
  • Convertible RI (assuming a clean exchange): $6,500 × 36 = $234,000.
  • EC2 Instance SP: $6,000 × 36 = $216,000, plus $4,000 × 18 in uncovered On-Demand = $288,000.

In the EC2 Instance SP case, $2,400/month of commitment goes unused after the migration. The highest discount ends up as the most expensive result. If a family change on your roadmap is more than a remote possibility, give more weight to flexibility than to the discount rate.

When should you still use Reserved Instances instead of Savings Plans?

Flexibility is not always the deciding factor. In three situations Reserved Instances (RIs) give you something Savings Plans do not.

Services outside Savings Plans coverage. Compute Savings Plans apply to EC2, Fargate, and Lambda. Managed data services have historically used their own reservation models: RDS reserved instances, ElastiCache reserved nodes, OpenSearch reserved instances, and Redshift reserved nodes. AWS has changed which services Savings Plans cover over time, so check the current eligibility list in the AWS documentation before you assume a database fleet is covered.

Capacity in a specific Availability Zone. A zonal RI reserves capacity for a specific instance type in a specific AZ. This helps when a scale-out event or AZ failover must succeed even if On-Demand capacity is constrained. Regional RIs and Savings Plans do not reserve capacity. They only change the price you pay for usage that runs.

Resale on a fleet that will not change. Standard RIs can be listed on the RI Marketplace, subject to AWS eligibility rules. Convertible RIs and Savings Plans cannot be resold. Resale gives you a partial exit if a fleet you were certain about is retired early. That exit only has value if you were right not to need flexibility in the first place.

Need Savings Plans Regional RI Zonal RI On-Demand Capacity Reservation
Billing discount Yes Yes Yes No (combine with an RI or Savings Plan)
Guaranteed capacity in an AZ No No Yes Yes
Commitment term Yes Yes Yes No, cancel anytime
Resale option No Standard only Standard only Not applicable

If you need guaranteed capacity but not a term commitment, use On-Demand Capacity Reservations. They are billed at the On-Demand rate whether or not instances run in them. Pair them with a Savings Plan or regional RI to get the discount.

How do you size a commitment to a safe baseline?

Start with data, not the console's purchase button. Pull at least several weeks of hourly usage from Cost Explorer or, better, the Cost and Usage Report (CUR). Hourly granularity matters because a Savings Plan is billed per hour. Daily averages hide the overnight troughs where an oversized commitment goes unused.

Before computing anything, filter out what isn't steady. Remove batch jobs, CI runners, load tests, and anything that exists only because autoscaling reacted to a burst. Tags, account boundaries, or Auto Scaling group names usually make this possible. If they don't, fix your tagging before committing.

The query below runs against CUR data in Athena. It sums Savings Plans-eligible On-Demand compute spend per hour, then computes the minimum and low percentiles such as p5 and p10. Column names are illustrative, so check them against your own CUR schema. Your target sits at or below that low percentile. Remember that the commitment is expressed in dollars per hour at Savings Plan rates, not On-Demand rates. Multiply the On-Demand baseline by your expected discounted rate before choosing a number.

Treat Cost Explorer purchase recommendations as one input, not the answer. They look backward over a fixed window, so a migration, an incident, or a temporary scale-up inside that window can inflate them.

Aim for partial coverage that leaves headroom. Unused commitment is pure waste, while uncovered usage costs only the On-Demand premium. You can add another plan later, but you cannot shrink one you already bought.

-- Hourly Savings Plans-eligible compute baseline from CUR in Athena.
-- Column names follow the legacy CUR layout and are illustrative.
-- Check them against your own CUR schema and tag columns.
WITH hourly AS (
  SELECT
    date_trunc('hour', line_item_usage_start_date) AS usage_hour,
    -- Use the public On-Demand cost so hours already covered by
    -- existing plans still count toward the baseline.
    SUM(pricing_public_on_demand_cost) AS od_equiv_spend
  FROM cur_db.cur_table
  WHERE line_item_usage_start_date >= TIMESTAMP '2026-08-01 00:00:00'
    AND line_item_usage_start_date <  TIMESTAMP '2026-10-01 00:00:00'
    AND line_item_line_item_type IN ('Usage', 'SavingsPlanCoveredUsage')
    -- EC2 instance hours only. Add Fargate or Lambda filters if needed.
    AND line_item_product_code = 'AmazonEC2'
    AND line_item_usage_type LIKE '%BoxUsage%'
    -- Drop non-steady workloads. Replace with your own tag column.
    AND COALESCE(resource_tags_user_workload, '')
        NOT IN ('batch', 'ci', 'loadtest', 'burst')
  GROUP BY 1
)
SELECT
  COUNT(*)                              AS hours_observed,
  MIN(od_equiv_spend)                   AS min_hourly,
  approx_percentile(od_equiv_spend, 0.05) AS p5_hourly,
  approx_percentile(od_equiv_spend, 0.10) AS p10_hourly,
  approx_percentile(od_equiv_spend, 0.50) AS p50_hourly
FROM hourly;
-- If hours_observed is less than the number of hours in the window,
-- some hours had zero spend, and the true minimum is 0.
-- The results are in On-Demand dollars. Multiply the chosen value by
-- your expected Savings Plan rate ratio to get the hourly commitment.

An Athena query over CUR data that sums steady, Savings Plans-eligible EC2 spend at On-Demand prices for each hour and reports the minimum and low percentiles, which form the baseline you commit below.

When should you avoid or delay a commitment?

Commit only after you know what the workload will look like for the length of the term. A commitment fixes your current footprint in place, so if the fleet is oversized you keep paying for that excess for one to three years. Rightsize first, using CPU, memory, and latency data from a representative period, so the baseline you commit to reflects actual need.

Architecture changes on your roadmap matter more than current usage. A Standard Reserved Instance or EC2 Instance Savings Plan bought for an x86 family will not follow you to Graviton, because Graviton instances belong to different families. Buying one a quarter before a planned migration guarantees stranded spend. The same applies when a service shrinks, is decommissioned, or moves to something the commitment does not cover, such as a managed database or a container platform outside EC2, Fargate, and Lambda.

Three-year all-upfront terms carry the most drift risk. Over that period you can expect new instance generations with better price-performance, possible architecture shifts, and some services moving to serverless. The deeper discount only holds up if the workload stays put.

Commitments do not guarantee capacity. Savings Plans and regional Reserved Instances only change billing. During a regional capacity shortage they will not get you instances. Only zonal Reserved Instances or On-Demand Capacity Reservations hold capacity, and only in a specific Availability Zone.

Recommendation tools base their suggestions on past usage and have no view of your roadmap. When the two conflict, go with the roadmap. Rightsize first, then modernize, and commit last.

How do you monitor commitments and keep the purchase cadence low-effort?

Track two numbers after every purchase. Utilization is the share of your commitment that actual usage consumed. If it sits well below full, you overbought and are paying for capacity nobody ran. Coverage is the share of eligible usage that received a discount. If it is low while utilization is high, your baseline grew and you have room to buy more. Review both monthly. Act only on trends that persist across several weeks, not single-day dips.

Buy in quarterly tranches instead of one large purchase. Each tranche covers a slice of the baseline, so expirations arrive in a staggered ladder. A mistake therefore costs at most one small slice, and an expiring tranche can be renewed, resized, or allowed to lapse as the architecture changes. Small, repeatable decisions also need less engineering review than a three-year bet on the whole fleet.

When the payer account buys commitments centrally, the discounts spread across linked accounts. This blurs each team's cost signal. A team that wastes capacity may still look cheap, and dev environments may absorb discounts meant for production. Report each team's spend at an amortized or on-demand-equivalent rate so their numbers reflect what they actually ran. The platform or FinOps owner should run the cadence, with service teams flagging roadmap changes.

Workload shape Best fit
Steady, changing families/regions Compute Savings Plan
Steady, fixed family and region EC2 Instance Savings Plan
Needs zonal capacity reservation Reserved Instances
Bursts, batch, experiments On-Demand and Spot

How OneEnv can help

Disclosure: OneEnv is the product behind this blog.

OneEnv (oneenv.io) is a workspace-based governance platform for the things services share — environment variables, database structure, API routes and validation rules. A change to a shared value is staged on a branch, reviewed once, and then every affected service explicitly approves or rejects it before it goes live, so you can see who a change touches before it ships instead of finding out in production.

Applied to savings plans vs reserved instances, this is where it helps:

Saves time

  • Every service that inherits a shared value is listed in one place, so nobody searches repos and chats to find out who is affected.
  • One review per branch replaces coordinating each team separately; each service still keeps its own approve/reject.
  • Changing a shared variable is one edit and one review instead of editing every service's .env by hand.

Saves cost

  • Fewer production incidents and rollbacks caused by a shared value, route or column changing under a consumer unannounced.
  • Less duplicated configuration to maintain: one shared definition inherited by many services.
  • A wrong or stale value is caught at review time by the services it affects, not by a failed deploy.
  • OneEnv has a free plan (1 workspace, unlimited services and members, full governance), so trying it costs nothing.

These are qualitative benefits, not measured results — how much you save depends on how many services share the value.

Want to try it? Start at oneenv.io.