# Azure VM High CPU -- Upsize Recommendation

> RC-262 recommends upsizing when a running Azure VM averages above 80% CPU or above 90% memory used (memory computed as 100 minus the Available Memory % series) over 30 days. Savings are $0 by design, since a larger SKU costs more; without metrics or pricing the rule abstains.

Source: https://zop.dev/integrations/azure/recommendations/azure-vm-high-cpu-upsize-recommendation
Updated: 2026-08-19

---

## Saturation on either axis is enough

The rule watches two 30-day series and fires when either crosses its line: average CPU above
80%, or average memory used above 90%. The OR matters. An earlier CPU-only version had a
blind spot where a memory-bound VM cruised at moderate CPU while the application thrashed
swap, and no upsize was ever suggested. Both dimensions now carry evidence on the finding,
each with its own threshold, so the panel shows which resource is actually starved.

## Memory arrives inverted

Azure Monitor exposes VM memory as Available Memory Percentage, so the rule computes
utilisation as 100 minus the series average. The evidence attached to the finding keeps the
native available-memory orientation with a "below 10%" threshold, which is the same statement
in the metric's own units. CPU is read strictly from the name-keyed `CPUUtilization` series.
A VM harvests 18+ metrics, and an older fallback that grabbed the first available series
could gate the decision on the wrong metric entirely.

## A recommendation that costs money on purpose

Upsizing is the opposite of a saving, and the finding says so: SavingsUSD is zero and the
optimized cost equals current cost, because the target SKU's price isn't known at evaluation
time. What the rule can carry is a concrete resize target: within the burstable B family it
proposes the next size up (for example Standard_B1ls to Standard_B1s) so the resize workflow
has something executable. Cross-family jumps, say into memory-optimized E-series, stay
advisory, since there is no in-family target to name.

## Pull the same series ZopNight evaluates

```bash
az monitor metrics list \
  --resource $(az vm show -g <rg> -n <vm> --query id -o tsv) \
  --metric "Percentage CPU" --interval PT1H \
  --start-time $(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ) \
  --query "value[0].timeseries[0].data[].average" -o tsv | sort -n | tail -5
```

Sustained values above 80 corroborate the finding.

## Acting on it

Resizing a VM means a stop-deallocate, a size change, and a restart, so plan a window. Verify
the saturation is the workload and not a runaway process before paying for a bigger SKU.
Metrics access is the Monitoring Reader role; discovery is Reader.
