Cloud Capacity Reservations
Capacity reservations guarantee that compute instances are available to launch in a specific zone, regardless of overall demand in the provider’s pool. You pay the on-demand rate whether the reserved capacity is used or not — the guarantee is what you’re buying.
Core tradeoff
Capacity reservation value = risk reduction from guaranteed availability. Capacity reservation cost = on-demand price of reserved capacity, including idle capacity. The question is always: “Is the business impact of not getting capacity greater than the cost of possibly paying for idle?”
AWS: On-Demand Capacity Reservations (ODCRs)
How they work
- Reserve capacity for a specific instance type, platform, tenancy, and Availability Zone.
- Billed at standard on-demand rate whether instances run or not.
- No built-in discount — but Savings Plans and Regional RIs apply on top, effectively giving you both capacity assurance and a discount.
- No long-term commitment for “immediate-use” ODCRs (create/modify/cancel anytime). Future-dated ODCRs can have minimum commitment durations.
If you need compute now and the instance should stay running, launch the instance. An immediate ODCR is not a better way to run current capacity. Its distinct use is holding launchable capacity while no instance is currently occupying that slot.
That only makes sense when “running the instance” has side effects that “holding the slot” does not:
- A running web worker joins load balancer rotation and receives traffic.
- A running queue consumer drains jobs before the business is ready.
- A running database replica, licensed Windows host, or GPU node adds software, storage, monitoring, or operational cost beyond the EC2 slot.
- A running Kubernetes node joins the cluster and can attract pods, daemonsets, log volume, security agents, and noisy background work.
Unused ODCR capacity is still expensive: it is billed like equivalent On-Demand instance usage. When a matching instance runs inside the ODCR, the reservation slot is consumed and billing follows the instance usage instead of charging the same slot twice. The economic question is therefore not “is ODCR cheaper than running?” It is “is paying for an empty launch slot better than running a real machine with real workload side effects?”
Immediate ODCR vs running instances
| Situation | Better action | Why |
|---|---|---|
Need 40 m7i.2xlarge API workers now and they can serve traffic | Launch 40 instances | The running instances consume capacity and do useful work. An ODCR adds no capacity benefit once the instances are already running. |
Need 40 m7i.2xlarge workers available if another AZ fails sometime this month | Immediate ODCR | You are paying to keep empty slots in the recovery AZ. If the failure happens, the failover fleet can launch without competing with every other customer failing into the same AZ. |
Need 40 m7i.2xlarge workers for a product launch on August 1 | Future-dated ODCR | The need has a known start date. Request the reservation ahead of time and avoid paying six weeks of idle immediate capacity. |
Concrete ODCR examples
Disaster recovery hold. A payments service normally runs 60
c7i.4xlarge instances across three AZs, 20 per AZ. The service’s recovery
objective says it must survive losing one AZ without waiting for provider
capacity. The platform team reserves 10 empty c7i.4xlarge slots in each AZ.
Most days those slots are unused and look wasteful in a pure utilization
report. During an AZ evacuation, the service shifts the failed AZ’s 20
instances onto the two healthy AZs: each healthy AZ scales from 20 to 30
instances and consumes its 10 reserved slots. Running all 90 instances every
day would keep extra application processes, load balancer targets, metrics,
agents, and database connections alive even though the business only needs 60
during normal operation.
Autoscaling headroom for a queue spike. A ticketing system has 25 normal workers and can temporarily need 150 workers when a high-demand event opens. Starting 125 extra workers early would drain queues, warm caches with event-day data, and increase downstream database pressure before the sale begins. Holding 125 immediate ODCR slots lets the autoscaler launch workers when the queue depth crosses the threshold. If the sale never spikes, the company paid for unused capacity; if it spikes while the AZ pool is exhausted, the workers still launch.
Known launch date. A streaming company knows a live event starts in six
weeks and needs 80 additional r7i.2xlarge cache nodes in one AZ. Immediate
ODCR would start billing today, even though the nodes are not needed for six
weeks. Future-dated ODCR is the right instrument: request now, specify the
event date as the start date, and treat the minimum commitment as part of the
event budget.
Configuration modes
| Mode | Behavior |
|---|---|
| Open | Any on-demand instance with matching attributes automatically uses the reservation |
| Targeted | Only instances that explicitly reference the reservation consume it |
Open mode is simpler operationally — matching instances “fall into” the reservation without code changes. Targeted mode gives finer control when multiple teams share an account and you want specific workloads to consume specific reservations.
Capacity Reservation groups
Groups let you target a collection of reservations rather than a single one. A group can include reservations with different attributes (different instance types, even reservations shared from other AWS accounts). Auto Scaling Groups can reference a group to preferentially consume reserved capacity before falling back to regular on-demand.
Interaction with Auto Scaling
ASGs can set a capacity reservation preference to prioritize reserved capacity. The ASG launches instances into matching ODCRs first, then overflows to regular on-demand. This is how organizations ensure their already-paid reservations get consumed by the right workloads.
Future-dated ODCRs
For planned events (launches, migrations, seasonal peaks), you can create ODCRs with a future start date. Constraints:
- Minimum vCPU requirements may apply
- Supported only for certain instance families
- May require a minimum commitment duration
ODCR economics
ODCR hourly cost = instance_count × on_demand_hourly_rate
Effective cost = ODCR hourly cost - Savings Plan discount (if covered)
Waste = (unused_instances / total_reserved) × ODCR hourly cost
The FinOps tension: you’re paying whether capacity is used or not. High utilization means the reservation is earning its keep. Low utilization means you’re paying insurance premiums for risk that may not exist.
Good ODCR candidates
- Critical online serving (outage = revenue loss)
- Scarce GPU capacity for inference/training
- Failover capacity that must exist pre-provisioned
- Launch-critical systems during ramp-up
- Constrained instance types with shallow AZ pools
Bad ODCR candidates
- Flexible batch jobs (can use any family, any AZ)
- Low-priority services that tolerate queueing
- Workloads with unknown capacity shape
- Exploratory/experimental workloads
ODCR anti-patterns
- Hidden idle pool — reserved “just in case” but nobody owns the idle cost
- Disconnected from autoscaling — ASGs don’t preferentially consume the reservation
- Shape drift — workloads migrate to new families, leaving old reservations stranded
- No release strategy — no periodic review to resize/cancel/share
- Confused with discount — “we have ODCRs so we’re saving money” (wrong — ODCR alone is not cheaper)
GCP: Reservations
GCP’s equivalent to ODCRs. Key differences from AWS:
| Property | AWS ODCR | GCP Reservation |
|---|---|---|
| Scope | AZ + instance type | Zone + machine type |
| Billing | On-demand rate always | On-demand rate always |
| Discount layering | Savings Plans / RIs apply on top | CUDs apply on top |
| Sharing | Cross-account via RAM | Cross-project via shared reservations |
| Consumption | Open or targeted | Automatically consumed or “specific” (targeted) |
| Commitment | No term (immediate), or future-dated with term | No minimum term |
GCP reservations can be consumed automatically by any VM with matching properties in the project, or marked as “specific” to require explicit targeting. Shared reservations extend across projects within an organization.
GCP-specific features
- Resize — increase or decrease reservation count without canceling
- Delete anytime — no penalty, stops billing immediately
- Bulk reservations — reserve large quantities for planned events
Azure: On-Demand Capacity Reservations
Azure’s version, introduced in 2021. Very similar to AWS ODCRs:
- Reserve capacity for a specific VM size in a specific zone
- Billed at on-demand rate whether used or not
- Azure Reserved VM Instances (discount instrument) apply on top
- No minimum term — cancel anytime
- Can be grouped and targeted
Operating an ODCR / reservation portfolio
Every reservation should have clear answers to:
- What workload does it protect?
- What is the business impact if capacity is unavailable?
- Why can’t Spot / flexible families solve this?
- What is target utilization?
- What is acceptable idle cost (the insurance premium)?
- What is the review cadence?
- Who sees the cost in chargeback/showback?
Key metrics
| Metric | Formula | Healthy range |
|---|---|---|
| Utilization | running matching instances / reserved count | 70–95% depending on workload criticality |
| Idle cost | (1 - utilization) × reservation hourly cost | As low as possible without risking availability |
| Coverage | reserved capacity / peak demand | Depends on risk tolerance |
Utilization states
| State | Interpretation |
|---|---|
| High utilization, critical workload | Good — reservation is earning its keep |
| Low utilization, failover capacity | Possibly acceptable — it’s insurance |
| Low utilization, non-critical workload | Likely waste — resize or cancel |
| Used by opportunistic workload | Good — if the workload is preemptible when the primary owner needs capacity back |