# Azure VM Rightsizing, Downscale Opportunity

> Downscaling fires on VMs averaging 5–30% CPU with network at or below 10 MB/s, disk under 500 IOPS, and at least $20 monthly cost, when a safe smaller in-family SKU exists. Savings use the real rate delta between current and target SKUs with a $5 noise floor; the ladder covers v5, Fs_v2, and Bs families.

Source: https://zop.dev/integrations/azure/recommendations/azure-vm-rightsizing-downscale-opportunity
Updated: 2026-08-19

---

## The 5 to 30% CPU band and its guard rails

CPU avg in the 5–30% band (below 5% is RC-201 idle, above 30% well-utilized), memory not high, network ≤ 10 MB/s, disk IOPS ≤ 500/s (storage-bound guard), cost ≥ $20/mo, and sizing.PickNextSmallerByCPUAndMemory (sized off the full-metric peak) names a safe smaller in-family SKU. Skips Databricks ephemeral VMs and VMSS member VMs. Network guard unit fix: VMNetworkIn/VMNetworkOut ("Network In/Out Total") are Azure Monitor Bytes/Total counters sampled at PT1M; the aggregator's default PT1H bucket (Average aggregation, no per-metric interval override) reports the mean of 60 such per-minute totals, so the raw Average is bytes-per-minute, not bytes-per-second. The rule converts via networkBytesPerSecond (÷60, applied to Average/Maximum/Minimum and every datapoint band) before comparing against the 10 MB/s threshold and before rendering the "B/s" prose/evidence, so the guard fires at the intended rate instead of ~60x too strict.

## Rate delta to the next smaller SKU

concrete-or-abstain (cost-driven rightsizing). Savings = the real on-demand SKU rate delta: savings = cost × (1 − dstRate/srcRate) where srcRate/dstRate are the current and named next-smaller SKU rates via LookupSKURate/SetSKURates. The rule abstains (returns nil) when no safe smaller SKU is nameable (burst-shaped peak, non-fitting p95, or the family is absent from the ladder), when either rate is missing or dstRate ≥ srcRate, when cost \< $20/mo, or when the real delta \< $5/mo noise floor. There is no flat-fraction fallback (the prior azureRightsizingSavingsFraction fabrication is removed, user directive 2026-06-27). Producer gap: skuladder.azureLadders covers only _v5 (Ds/Das/Es/Eas), Fs_v2, and Bs families; real fleets run _v3/_v4 SKUs (e.g. Standard_D16s_v3) whose family is absent, so the rule abstains on them correctly; delivering savings on v3/v4 VMs needs the ladder table extended (not this rule).

## Resizing during a maintenance window

1. Review VM Insights to confirm the 30-day utilization profile
2. Resize to the recommended SKU during a maintenance window
3. Update scale automation (ARM/Terraform) to pin the new size

## Which utilization series this rule reads

CPUUtilization, VMMemoryPercent, VMNetworkIn/Out, VMDiskReadOps/WriteOps (30d)
