Dev/test MySQL Flexible Servers keeping backups beyond 7 days at real storage cost
What does ZopNight detect here?
Dev/test MySQL Flexible Servers retaining backups longer than 7 days are flagged by RC-246 when backup storage exceeds the free allowance (100% of provisioned storage). Savings multiply the billable excess GB by the over-retention share and the real per-GB LRS or GRS rate times 730; any missing input makes it abstain.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-246 |
| Category | rightsizing |
| Severity | low |
| Metric | none — pure configuration read |
| Source | flexserver_backup.go |
Where it applies
Backup storage is free only up to a line
Azure gives a MySQL Flexible Server backup storage free up to 100% of its provisioned storage size; only backup data beyond that allowance bills per GB. A dev/test server with long retention quietly walks past the line: each extra retained day adds recovery points, and once cumulative backup GB exceeds provisioned GB the meter starts. RC-246 exists for exactly that crossing: a dev/test server holding backups it will never restore, paying for storage above the free allowance.
Two facts must both be true
The server must match a dev/test name pattern, and its discoverer-stamped
backup_retention_days metadata must exceed 7, the threshold the rule treats as
sufficient for non-production. Production servers are never flagged by this rule
regardless of retention. The retention value comes from the ARM
properties.backup.backupRetentionDays field the discoverer writes into metadata; an
earlier revision read it from tags, where no producer ever put it, and could not fire.
How the dollar figure is assembled
Every component of the saving is real, and each missing component means abstain:
- Billable excess:
MySQLBackupStorageUsed(Azure Monitor, 30-day window) minus the provisioned storage size. Non-positive excess → nothing billed → nothing to save → abstain. - Retention share: (retentionDays − 7) / retentionDays, the portion of the excess attributable to over-retention.
- Rate: the per-GB-hour backup-storage rate for the server’s redundancy class, multiplied by 730 to get a month. The 730× step matters: the pricing layer serves storage rates per GB-hour, and omitting the conversion once under-reported savings by that factor.
The result is capped at the server’s monthly cost. No fraction-of-the-bill estimates, no $0 advisory rows. A missing metric, missing provisioned size, or missing rate all abstain.
Geo-redundancy roughly doubles the stakes
The discoverer stamps geo_redundant_backup for flexible servers; when it reads enabled
the rule prices against the GRS backup rate, which is roughly double LRS. When neither
redundancy signal exists, the rule conservatively assumes the cheaper LRS rate. It would
rather understate a saving than inflate one.
Read your own retention and redundancy
az mysql flexible-server show \ --resource-group <rg> --name <server> \ --query "{retentionDays:backup.backupRetentionDays, geoBackup:backup.geoRedundantBackup, storageGB:storage.storageSizeGb}"Reducing retention takes one setting change under Compute + Storage; recovery points beyond the new window age out on their own schedule. Confirm nobody depends on the older restore points before shortening; 7 days is plenty for most dev loops, but not for every one.