Standalone on-demand EC2 instances that could move to Spot
What does ZopNight detect here?
ZopNight flags a running on-demand EC2 instance outside an Auto Scaling group that looks interruption-tolerant and whose live Spot price is below its on-demand rate. Production, disaster-recovery, bastion, database and Windows instances are excluded, as are boxes averaging under 5% CPU. Spot runs up to 90% below On-Demand but gives only a two-minute warning.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-097 |
| Category | discount |
| Severity | low |
| Metric | CPUUtilization |
| Threshold | at least 5% average CPU |
| Evaluation window | 30d |
| Source | ZopNight |
| Permissions used | ec2:DescribeInstances · ec2:DescribeSpotPriceHistory · cloudwatch:GetMetricStatistics |
Where it applies
What Spot saves and what it asks in return
Spot Instances are spare EC2 capacity sold at steep discounts, and the Spot page 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 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:
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 tableVetoes applied before any price is checked
The instance must be running on demand. It is skipped when any of these hold:
- It is already Spot, or tagged as managed by Spot.io (
spotinst:keys). - It belongs to an Auto Scaling group, where Spot is set in the group’s mixed instances policy instead.
- Its 30-day average
CPUUtilizationis under 5%; an idle box should be downsized first, see EC2 Rightsizing. - Its name or environment tag marks it as production.
- Its name marks a resilience role (dr, backup, standby, passive, failover, replica) or a bastion or jump host.
- It runs a self-managed database, Kafka, Elasticsearch or Redis.
- 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
spot fraction = 1 - (live Spot rate / live on-demand rate)saving = current monthly cost x spot fractionWhen a Savings Plan or Reserved Instance suggestion also fits, only the better-valued option is kept.
Moving the workload to Spot
- Confirm the workload survives being stopped with two minutes’ notice.
- Replace the instance with an Auto Scaling group using multiple instance types and purchase options, or an EC2 Fleet for one-off replacements.
- Allow several instance types and zones so capacity is easier to find.
- Handle the interruption notice in the application to drain work cleanly.
- Terminate the old on-demand instance once the Spot capacity is serving traffic.