Skip to main content
discount · azure

Non-production VMs consuming reservation or savings plan hours that Spot could replace

resource types
1
rule IDs covered
1
severity
medium

What does ZopNight detect here?

ZopNight flags a dev or test VM, not recorded as Windows, that is covered by a reservation or savings plan when the same size's Spot rate is cheaper than its 1-year reserved rate. Moving that VM to `--priority Spot` frees the committed hours for production usage, and ZopNight prices the gap as 1 minus Spot over reserved.

Signal and threshold

How ZopNight evaluates Non-production VMs consuming reservation or savings plan hours that Spot could replace.
Field Value
Rule IDsRC-1381
Categorydiscount
Severitymedium
MetricPercentage CPU, Network In Total (evidence only)
Thresholdcovered by a commitment, positive non-production signal
Evaluation window30d
SourceZopNight
Permissions usedMicrosoft.Compute/virtualMachines/read · Microsoft.Capacity/reservationorders/reservations/read

Why a reserved dev VM can still be overpaying

A reservation makes a VM cheaper than pay-as-you-go, but for a workload that tolerates being interrupted it is not the cheapest option. Azure Spot VMs run on spare capacity at a variable price, with no SLA and eviction on 30 seconds’ notice. Microsoft names dev/test environments and batch jobs as good fits.

There is a second benefit. Reservation discounts float to any matching VM in scope, so when a dev VM stops consuming reserved hours, those hours can cover a production VM that is currently paying full price.

Spotting dev and test VMs under a commitment

A name filter gives a first list; confirm coverage in the portal under Reservations or in the reservation’s utilization report:

Terminal window
az vm list \
--query "[?priority!='Spot' && (contains(name,'dev') || contains(name,'test'))].{name:name, rg:resourceGroup, size:hardwareProfile.vmSize}" \
-o table

Conditions ZopNight checks

  1. ZopNight’s billing data shows the VM covered by a reservation or savings plan. Pay-as-you-go VMs belong to Azure Spot VM Opportunity.
  2. The VM is not already Spot or low priority.
  3. A positive non-production signal: a dev or test environment tag, or a dev/test name, with no production environment tag.
  4. The operating system is not recorded as Windows or SQL Server.
  5. It is not an M-series VM, a Databricks-managed VM or a scale set member.
  6. Its name does not suggest a data store (database, Kafka, Elasticsearch, Redis and similar) or a standby role such as dr, standby, failover or replica.

CPU and inbound network over 30 days are shown as context only.

Where the migration is not suggested

The operating system check only excludes VMs recorded as Windows or SQL Server; a VM with no OS recorded is not excluded on that ground, so confirm the OS before acting. Missing Spot or 1-year reserved rates for the size, or a zero cost, also mean no finding, since ZopNight will not assume a typical Spot discount. One known gap: a member of a Flexible orchestration scale set can look like a standalone VM and may still be listed.

Spot priced against the reserved rate, not list price

Terminal window
discount = 1 - (Spot hourly rate / 1-year no-upfront reserved hourly rate)
saving = current monthly VM cost x discount

The denominator is the reserved rate because the VM’s current cost is already discounted by the commitment. Comparing Spot with pay-as-you-go would overstate the gain. Discounts outside a 5% to 92% band are treated as bad rate data.

Moving the VM to Spot

  1. Confirm the workload handles eviction; az vm simulate-eviction --resource-group my-rg --name my-spot-vm lets you test that on a Spot copy.
  2. Recreate it as Spot, for example az vm create ... --priority Spot --max-price -1 --eviction-policy Deallocate, from a snapshot or image of the current disk.
  3. Delete the original VM once the Spot copy is serving.
  4. Check that the reservation’s utilization stays high; if nothing else in scope uses the freed hours, widen its scope or plan an exchange.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

472 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

472 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·