# RDS PITR Enabled on Non-Production

> 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.

Source: https://zop.dev/integrations/aws/recommendations/rds-pitr-enabled-on-non-production
Updated: 2026-08-19

---

## 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](https://aws.amazon.com/rds/pricing/))
- 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](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/monitoring-cloudwatch.html) 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

1. Confirm this is a non-production database
2. Modify the RDS instance backup retention period to 0 (disables PITR) or 1 day
3. Ensure automated snapshots still meet recovery requirements
4. 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)
