VMs saturated on CPU or memory across a 30-day window
What does ZopNight detect here?
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.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-262 |
| Category | performance |
| Severity | medium |
| Metric | none — pure configuration read |
| Source | vm_performance.go |
Where it applies
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
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 -5Sustained 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.