Skip to main content
INS // Insights

AWS RDS Snapshot Storage Cost Cleanup

Updated August 2026 · 5 min read

Automated RDS backups are not the line item that shocks finance. AWS RDS snapshot storage cost is: years of manual snapshots named before-change, cross-region copies from a migration that ended, and Aurora backup storage that grew because backup_retention_period was set to 35 and nobody restored from day 30 to prove it mattered.

We clean this as a FinOps sprint with a restore test at the end. Deleting snapshots without a restore proof is how you save money on the invoice and spend it on an incident.

Where the Charges Actually Live

RDS/Aurora billing splits:

  • Backup storage (automated retention beyond the free allocation tied to provisioned storage)
  • Manual snapshots (persist after you lower retention or delete the instance)
  • Cross-region snapshot copies
  • Export to S3 (different product; out of scope here)

AWS describes backup storage in the RDS backup docs. The operational problem is ownership. Automated backups die with retention. Manual snapshots do not.

Pair this cleanup with idle load balancer charges — same pattern: leftover resources from a project that shipped.

Inventory: Tag, Age, Source, Restore Proof

We pull DescribeDBSnapshots / cluster snapshots and join to:

Field Decision
SnapshotType automated vs manual Manual needs an owner tag
Age vs policy (e.g. 35 days) Older than policy → delete candidate
Encrypted / KMS key Lost key = unrestorable anyway
Shared / copied Extra copies in other accounts/regions
Last restore test date If never restored, it is not a backup; it is a souvenir
def delete_candidate(s: dict, policy_days: int, now_epoch: int) -> bool:
    if s["type"] != "manual":
        return False
    if s.get("owner_tag"):
        return False
    age_days = (now_epoch - s["create_epoch"]) / 86400
    return age_days > policy_days

Untagged manual snapshots older than policy go to a deletion queue with a 7-day warning to #engineering. Tagged snapshots with a living owner get a "confirm or we untag" ping. Untag then they join the queue. Social process, not a silent wipe.

Retention vs Snapshot Hoarding

Raising automated retention from 7 to 35 days increases backup storage. That can be correct for ransomware recovery. It is incorrect as a substitute for a tested snapshot in another account. We separate:

A SOC 2 story that says "we keep 35 days" still needs a restore test. Cost cleanup that deletes the only copy that ever restored is malpractice.

Aurora-Specific Footguns

  • Cluster snapshots vs instance snapshots — inventory both
  • Backtrack is not a snapshot; do not double-count it as backup storage
  • Copying a snapshot to another region for "DR" without a restore runbook is a bill with no capability

For instance rightsizing that is not snapshot related, Aurora Serverless v2 cost is a different lever. Do not mix ACU work with snapshot deletion in one change window.

A 2-week AWS cost audit includes the snapshot scorecard → rutagon.com/contact · 907-841-8407 · contact@rutagon.com.

Cross-Account Copies

DR copies in a second account are a capability only if restore was tested from that account. We see copies into a "backup" account with no IAM path to restore. That is spend. Either complete the DR runbook or stop the copy job.

Snapshot sharing to a vendor account should be time-boxed. Eternal shares are data movement. Treat ModifyDBSnapshotAttribute like a production change.

Naming Hygiene

final-final-before-upgrade-2 is not an owner. Terraform-created snapshots with Name and Owner tags from the pipeline can live. Console snapshots inherit the creator's identity for about a day in CloudTrail; after that you have a ghost. The 7-day warning in Slack is the social layer that makes deletion safe.

If PITR is on, lowering retention from 35 to 7 is a RPO change, not a snapshot-delete. Get the availability owner to sign that separately from souvenir cleanup.

AWS RDS snapshot storage cost after PITR is already on

AWS RDS snapshot storage cost is usually souvenir snapshots plus extra-region copies, not PITR. Automated backups die with retention. Manual snapshots do not. AWS describes the split in the RDS backup docs. We inventory snapshot_type, age, tags Owner/Ticket, and whether a restore was ever tested from that snapshot.

Cross-account copies into a “backup” account with no IAM path to restore are spend without DR. Either complete the restore runbook or stop the copy job. Sharing a snapshot to a vendor account is data movement: time-box ModifyDBSnapshotAttribute.

Lowering PITR from 35 to 7 days is an RPO change. Get the availability owner to sign it separately from deleting final-final-before-upgrade-2. Aurora clone storage and snapshot export to S3 are separate line items we include in the scorecard so finance does not think “RDS snapshots” is one number.

Naming: Terraform-tagged snapshots live. Console snapshots inherit a creator for about a day in CloudTrail, then they are ghosts. A 7-day Slack warning before delete is the social layer that makes cleanup survivable.

Frequently Asked Questions

Will deleting manual snapshots affect automated backups?

No. They are separate. Deleting a manual snapshot does not change backup_retention_period. Deleting the instance without a final snapshot is a different, usually worse, story.

How do we prove a snapshot is restorable before deleting others?

Restore to a isolated instance/cluster, run a checksum or app smoke query, terminate the restore. Record the ticket. Then delete the souvenirs.

What about snapshots shared from another account?

Treat them as inbound risk and cost. If you do not need them, unshare and delete your copies. If you need them, they need an owner in your org.

Can AWS Backup replace manual RDS snapshots?

For many teams, yes — policy-based copies and vaults. Migrating to AWS Backup is an infra project. Snapshot hygiene can happen first so you are not paying for both.

Why is backup storage still high after we deleted snapshots?

Automated retention, Aurora change volume, or another region. Cost Explorer by usage type (RDS:ChargedBackupUsage, etc.) before you guess.