Production MySQL Flexible Servers still on pay-as-you-go compute pricing
What does ZopNight detect here?
Azure MySQL Flexible Servers with a production name or env tag, 60+ days of history, roughly 70% uptime, and measured MySQLCpuPercent or MySQLMemoryPercent at 30%+ get a reserved-capacity recommendation (RC-245). The saving is a sanity-banded fraction of monthly cost, defaulting to 35%, because raw tier-rate lookups can collide with VM pricing.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-245 |
| Category | discount |
| Severity | low |
| Metric | none — pure configuration read |
| Source | flexserver_reserved.go |
Where it applies
Why this saving is a bounded fraction, not a raw rate delta
Most commitment rules want to price directly off the reserved-vs-on-demand rate pair. RC-245 deliberately does not. The tier-rate lookup is keyed on the server’s raw SKU token, a VM-style string like “Standard_D2ds_v4”, and the rate table is not filtered by service, so that lookup can silently return the Virtual Machines reserved-instance row instead of the Azure Database for MySQL one. Billing a database commitment at a bare-VM RI rate would be undetectably wrong. So the dollar figure is cost × a derived discount fraction that is sanity-checked against a plausibility band and rate-inversion guard, falling back to a fixed 35% when the derived ratio looks unsound. Break-even math is still used, but only as a veto: when the reservation can be priced and would cost more than current spend, the rule abstains rather than book a losing commitment.
The dead-rule history baked into this check
An earlier eligibility gate read the EC2-style metric names CPUUtilization and
MemoryUtilization, names the Azure producer never writes for this resource type, so the
gate reported “utilization unverified” on every real server and the rule abstained 100% of
the time. The fix reads the exact producer-written series, MySQLCpuPercent and
MySQLMemoryPercent, and declares them so the platform pre-fetches both over a 30-day
window via Monitoring Reader.
Three fail-closed hurdles before recommending a year
- History: at least 60 days of observed coverage; unknown coverage abstains.
- Uptime: known and at or above the 0.70 commitment floor. A part-time server should be scheduled, not committed.
- Utilization: a measured CPU or memory average at or above 30%. An empty series from a stopped server counts as unverified, never as measured 0%.
The server must also carry a production signal (a prod name pattern or an authoritative
environment tag) and must not already be covered by a Reservation, a SavingsPlan, or a
reserved=true tag. Missing pricing abstains.
Confirm which servers are candidates
az mysql flexible-server list \ --query "[].{name:name, sku:sku.name, tier:sku.tier, state:state}" -o tableCross-reference the running production servers against your reservations in Portal → Reservations. Purchasing reserved capacity itself takes billing-account permissions your own admin holds; ZopNight only reads state (Reader, Cost Management Reader) and never buys commitments on your behalf.