RDS PITR Enabled on Non-Production
What does ZopNight detect here?
Point-in-time recovery on dev/test RDS instances bills backup storage only beyond 100% of provisioned capacity, so savings equal the billable excess GB times the rds-snapshot rate times 730 hours. ZopNight abstains on all live data today because the backup_storage_used metric has no producer yet, and enforces a $5 floor.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-168 |
| Category | rightsizing |
| Severity | low |
| Metric | none — pure configuration read |
| Source | rds_pitr.go |
Where it applies
Spotting PITR from the retention period
- PITR-active gate from Metadata (fail-closed): backupRetentionPeriod>0 (or alias backup_retention_days>0), or the GCP fallback string pitr_enabled=“true”; the prior Tags[“pitr_enabled”] gate was dead (no AWS producer writes it)
- resource.Name: dev/test pattern (isDevTestName, which already implies !isProdName, so the redundant isProdName check was removed)
- Metadata[“storage”] (int AllocatedStorage, the free-allowance baseline: backup storage is free up to 100% of provisioned DB storage)
- PricingAware: per-resource monthly cost
- Producer-gap backup_storage_used metric (GB-as-bytes of automated-backup storage, AWS/RDS): the CloudWatch series RDS publishes include no native total-backup-storage counter, so it must come from Cost Explorer BackupUsage / a DescribeDBInstanceAutomatedBackups rollup; absent today → the rule abstains
- SKURatesAware rds-snapshot SKU rate (per-GB backup-storage, RDS:ChargedBackupUsage): already ingested into the aws rate map by the aggregator (pricing/aws/pricing.go), and it is the same key sibling RC-032 (rds_backup_retention.go) resolves. (A prior rds-backup-storage key had zero producers and always resolved to 0; fixed by re-keying onto this live SKU, so no producer work is needed for the rate.)
Billing only backup beyond the free allowance
Concrete or abstain (cost-driven rightsizing). billableGB = max(0, backupUsedGB − provisionedGB), savings = billableGB × perGBHourRate × 730. The rds-snapshot rate from model.LookupSKURate is per-GB-hour (pricing ingest divides the catalog per-GB-month figure by 730; see pricing/aws/stream.go isStorageRate), so the ×730 is mandatory to get a monthly figure (mirrors GCP RC-147). The rule is fail-closed: it returns nil on any missing input (no backup_storage_used metric, the current live gap; no provisioned size; no billable excess; no rate) or below the $5 minSavingsUSD floor. It never emits a $0/advisory rec, and never the prior cost*0.30 fabricated fraction. The prior “performance”/SavingsUSD=0 advisory dodge is removed.
Disabling PITR on a dev database
- Confirm this is a non-production database
- Modify the RDS instance backup retention period to 0 (disables PITR) or 1 day
- Ensure automated snapshots still meet recovery requirements
- Consider manual snapshots for longer retention needs
The missing backup storage producer
backup_storage_used (30d, MetricsAware; SKURatesAware: rds-snapshot). The non-prod gate now uses the authoritative env tag (prod-tag hard veto; name only as corroborating fallback), not a name heuristic; abstains on live data until the backup_storage_used metric producer lands (the rds-snapshot rate is already live)