# Azure RI to Spot Migration for Non-Production

> Flags dev/test VMs using reservation or savings plan hours and prices moving them to Spot against the reserved rate.

Source: https://zop.dev/integrations/azure/recommendations/azure-ri-to-spot-migration-for-non-production

---

## 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](https://learn.microsoft.com/en-us/azure/virtual-machines/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:

```bash
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 <a href="https://zop.dev/integrations/azure/recommendations/azure-spot-vm-opportunity">Azure Spot VM Opportunity</a>.
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

```text
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.

**Warning**
Deallocated Spot VMs still count against quota and keep charging for their disks. Use the Delete eviction policy if the disks are disposable.
