# EC2 On-Demand Instance, Evaluate Spot Adoption

> Flags standalone on-demand EC2 instances that look interruption-tolerant, priced from live Spot and on-demand rates.

Source: https://zop.dev/integrations/aws/recommendations/ec2-on-demand-instance-evaluate-spot-adoption

---

## What Spot saves and what it asks in return

[Spot Instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html) are
spare EC2 capacity sold at steep discounts, and the
[Spot page](https://aws.amazon.com/ec2/spot/) puts it at up to 90% off On-Demand. The Spot price for
each instance type and Availability Zone is set by EC2 and moves gradually with supply and demand.

The trade is interruption. EC2 can reclaim the capacity, and the
[interruption notice](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-instance-termination-notices.html)
arrives two minutes before the instance is stopped or terminated. Batch jobs, CI workers, stateless
services and test environments cope with that. Anything that holds unique state does not.

## Comparing prices for your own instances

List running instances that are not already Spot, then look at recent Spot prices for a type:

```bash
aws ec2 describe-instances --filters Name=instance-state-name,Values=running \
  --query 'Reservations[].Instances[?!InstanceLifecycle].[InstanceId,InstanceType]' --output table

aws ec2 describe-spot-price-history --instance-types m5.large \
  --product-descriptions "Linux/UNIX" --start-time 2026-09-24T00:00:00Z \
  --query 'SpotPriceHistory[].[AvailabilityZone,SpotPrice]' --output table
```

## Vetoes applied before any price is checked

The instance must be running on demand. It is skipped when any of these hold:

1. It is already Spot, or tagged as managed by Spot.io (`spotinst:` keys).
2. It belongs to an Auto Scaling group, where Spot is set in the group's mixed instances policy instead.
3. Its 30-day average `CPUUtilization` is under 5%; an idle box should be downsized first, see
   <a href="https://zop.dev/integrations/aws/recommendations/ec2-rightsizing">EC2 Rightsizing</a>.
4. Its name or environment tag marks it as production.
5. Its name marks a resilience role (dr, backup, standby, passive, failover, replica) or a bastion or
   jump host.
6. It runs a self-managed database, Kafka, Elasticsearch or Redis.
7. It runs Windows or SQL Server.

## Missing data and live rates

With no CPU series at all, the finding can still appear, at medium rather than high confidence. When
the operating system is unknown, that veto is not applied. What always stops the rule is a missing
price: without a billed cost and live on-demand and Spot rates for the instance type, nothing is
shown, because the saving would be invented.

## Pricing the move to Spot

```text
spot fraction = 1 - (live Spot rate / live on-demand rate)
saving        = current monthly cost x spot fraction
```

When a Savings Plan or Reserved Instance suggestion also fits, only the better-valued option is kept.

## Moving the workload to Spot

1. Confirm the workload survives being stopped with two minutes' notice.
2. Replace the instance with an
   [Auto Scaling group using multiple instance types and purchase options](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-mixed-instances-groups.html),
   or an EC2 Fleet for one-off replacements.
3. Allow several instance types and zones so capacity is easier to find.
4. Handle the interruption notice in the application to drain work cleanly.
5. Terminate the old on-demand instance once the Spot capacity is serving traffic.

**Warning**
Spot capacity can be reclaimed at any time. Never move a workload that keeps its only copy of data on local disk.
