CloudBurn Logo
CloudBurnHome
  • Blog
  • Docs
  • Tools
  • Features
  • Roadmap
  • Changelog
Join the CloudBurn Discord community
1.8k
Join the CloudBurn Discord community1.8k
  • Home
  • Blog
  • Docs
  • Tools
  • Features
  • Roadmap
  • Changelog
Navigation
    • Overview
    • Understanding Rules
      • API Gateway
      • CloudFront
      • CloudTrail
      • CloudWatch
      • Cost Explorer
      • Cost Guardrails
      • DynamoDB
      • EBS
      • EC2
      • ECR
      • ECS
      • EKS
      • ElastiCache
      • ELB
      • EMR
      • Lambda
      • RDS
      • Redshift
      • Route 53
      • S3
      • SageMaker
      • Secrets Manager
      • Tagging
    • Overview
    • Understanding Rules
      • API Gateway
      • CloudFront
      • CloudTrail
      • CloudWatch
      • Cost Explorer
      • Cost Guardrails
      • DynamoDB
      • EBS
      • EC2
      • ECR
      • ECS
      • EKS
      • ElastiCache
      • ELB
      • EMR
      • Lambda
      • RDS
      • Redshift
      • Route 53
      • S3
      • SageMaker
      • Secrets Manager
      • Tagging
Loading documentation page
CloudBurn Logo
CloudBurn

AWS cost intelligence platform that automatically identifies waste, optimizes resources, and provides actionable recommendations to reduce cloud spend.

Product

  • Features
  • Roadmap
  • Changelog
  • About
  • Blog
  • Newsletter
  • Docs
  • Contact

Free Tools

  • Lambda Cost Calculator
  • EC2 Pricing Calculator
  • S3 Pricing Calculator
  • EBS Pricing Calculator
  • Fargate Pricing Calculator
  • RDS Pricing Calculator
  • Aurora Cost Calculator
  • See all tools →

Newsletter

Subscribe for CloudBurn product updates, changelogs, and actionable AWS cost optimization tips delivered to your inbox.

Newsletter signup form loading.
Enter your email…
Subscribe
---- subscribers
OR SIGN UP WITH
GGH

By signing up you agree to our privacy policy.

CloudBurn © 2026 | Terms & Privacy

Built with ❤️ by Towards the Cloud

CloudBurn Rules

RDS Rules

CloudBurn cost optimization rules for AWS RDS.

These rules cover the most common sources of unnecessary RDS spend: outdated instance classes, idle or stopped instances, missing reserved coverage, non-Graviton families, low utilization, extended support charges, orphaned or aging snapshots, and excessive Performance Insights retention.

Rule IDScan TypeSeverityName
CLDBRN-AWS-RDS-1Discovery and IaCMediumRDS Instance Class Not Preferred
CLDBRN-AWS-RDS-2DiscoveryHighRDS DB Instance Idle
CLDBRN-AWS-RDS-3DiscoveryHighRDS DB Instance Missing Reserved Coverage
CLDBRN-AWS-RDS-4Discovery and IaCMediumRDS DB Instance Without Graviton
CLDBRN-AWS-RDS-5DiscoveryHighRDS DB Instance Low CPU Utilization
CLDBRN-AWS-RDS-6Discovery and IaCHighRDS DB Instance Unsupported Engine Version
CLDBRN-AWS-RDS-7DiscoveryMediumRDS Snapshot Without Source DB Instance
CLDBRN-AWS-RDS-8IaCLowRDS Performance Insights Extended Retention
CLDBRN-AWS-RDS-9DiscoveryHighRDS DB Instance Stopped
CLDBRN-AWS-RDS-10DiscoveryMediumRDS Manual Snapshot Max Age Exceeded

CLDBRN-AWS-RDS-1

RDS Instance Class Not Preferred

Scan type: Discovery and IaC

Severity: Medium

What it checks

Flags RDS DB instances using older-generation instance classes. The preferred classes offer better performance per dollar and are AWS's recommended choices for new and existing workloads.

Preferred instance classes:

ClassBest For
db.m8gGeneral-purpose workloads (Graviton4)
db.m8gdGeneral-purpose with local NVMe (Graviton4)
db.m8iGeneral-purpose workloads (Intel x86)
db.m7iGeneral-purpose workloads (Intel x86)
db.m7gGeneral-purpose workloads (Graviton3)
db.r8gMemory-intensive workloads (Graviton4)
db.r8gdMemory-intensive with local NVMe (Graviton4)
db.r8iMemory-intensive workloads (Intel x86)
db.r7iMemory-intensive workloads (Intel x86)
db.r7gMemory-intensive workloads (Graviton3)
db.t4gDev/test and burstable workloads (Graviton2)

Non-preferred classes that trigger findings: db.m1, db.m3–db.m6*, db.r3–db.r6*, db.t2–db.t3. Instance families not in either list (e.g. db.m2) are treated as unclassified and do not trigger a finding.

Why it matters

Older-generation RDS instance classes are less performant and often more expensive than their current-generation equivalents. Graviton-based classes (db.m8g, db.r8g, db.t4g) provide 20-35% better price/performance than equivalent Intel x86 classes.

What triggers a finding

The DB instance class family matches one of the non-preferred generations listed above.

How to remediate

Modify the DB instance to use a preferred class. For production instances, use a Multi-AZ failover to minimize downtime:

aws rds modify-db-instance \
  --db-instance-identifier my-db \
  --db-instance-class db.m8g.large \
  --apply-immediately

For Graviton migrations, verify engine compatibility first — most engines on RDS support Graviton, but check the specific engine version and region availability.

IaC resources checked

IaC ToolResource Type
Terraformaws_db_instance
CloudFormationAWS::RDS::DBInstance

CLDBRN-AWS-RDS-2

RDS DB Instance Idle

Scan type: Discovery

Severity: High

What it checks

Flags RDS DB instances that have had zero database connections over the past 7 days. An instance with no connections is not serving any application traffic and is a candidate for deletion or suspension.

Why it matters

RDS instances are billed by the hour for provisioned compute and storage, regardless of whether any application is connected. An idle db.m7i.large Multi-AZ instance costs over $300/month. Development and staging databases that are forgotten after a project ends are a common source of unnecessary RDS spend.

What triggers a finding

maxDatabaseConnectionsLast7Days is 0.

How to remediate

  1. Verify no application is using the instance (check application logs, not just the CloudWatch metric)
  2. If truly idle, choose one of:
    • Stop the instance: RDS can be stopped for up to 7 days at a time. Storage charges continue but compute stops.
    • Delete the instance: Take a final snapshot, then delete.
    • Migrate to Aurora Serverless v2: For intermittent workloads, Aurora Serverless v2 scales to zero ACUs when idle, eliminating compute cost between bursts.
# Create final snapshot and delete
aws rds create-db-snapshot \
  --db-instance-identifier my-db \
  --db-snapshot-identifier my-db-final-snapshot

aws rds delete-db-instance \
  --db-instance-identifier my-db \
  --skip-final-snapshot

CLDBRN-AWS-RDS-3

RDS DB Instance Missing Reserved Coverage

Scan type: Discovery

Severity: High

What it checks

Flags RDS DB instances that have been running for at least 180 days without matching active reserved instance coverage. The rule matches instances to reservations by region, instance class, Multi-AZ configuration, and normalized engine (Aurora MySQL maps to mysql, Aurora PostgreSQL to postgres). Wildcard engine coverage is also consumed.

Why it matters

RDS Reserved Instances offer 30-60% savings over on-demand pricing depending on the term and payment option. An instance running on-demand for 6+ months is a strong candidate for a reservation. The longer you wait, the more savings you leave on the table.

What triggers a finding

All of the following must be true:

  • Instance status is available
  • Instance has been running for 180 or more days
  • No active reserved instance matches the instance's accountId:region:instanceClass:multiAz:normalizedEngine combination

How to remediate

  1. Review the flagged instance's class, engine, and Multi-AZ configuration
  2. Check AWS Cost Explorer RI recommendations for RDS
  3. Purchase a matching reserved instance:
aws rds purchase-reserved-db-instances-offering \
  --reserved-db-instances-offering-id <offering-id> \
  --db-instance-count 1

CLDBRN-AWS-RDS-4

RDS DB Instance Without Graviton

Scan type: Discovery and IaC

Severity: Medium

What it checks

Flags RDS DB instances using non-Graviton instance families when a Graviton-based equivalent exists. The review set includes db.m5, db.m5d, db.m6i, db.m6id, db.m6in, db.m7i, db.m8i, db.r5, db.r5b, db.r5d, db.r6i, db.r6id, db.r6in, db.r7i, db.r8i, db.t2, and db.t3.

Why it matters

Graviton-based RDS classes (db.m8g, db.r8g, db.t4g) offer 20-35% better price/performance than their Intel equivalents. For most database engines, the migration is straightforward and doesn't require application changes.

What triggers a finding

The instance class family is in the Graviton review set and is not already using a Graviton family.

How to remediate

Modify the instance to use a Graviton class. Test with a read replica first if you want to validate compatibility:

aws rds modify-db-instance \
  --db-instance-identifier my-db \
  --db-instance-class db.r8g.large \
  --apply-immediately

Check engine version compatibility, as some older engine versions don't support Graviton. Upgrade the engine version first if needed.

IaC resources checked

IaC ToolResource Type
Terraformaws_db_instance
CloudFormationAWS::RDS::DBInstance

CLDBRN-AWS-RDS-5

RDS DB Instance Low CPU Utilization

Scan type: Discovery

Severity: High

What it checks

Flags available RDS DB instances whose 30-day average CPU utilization stays at or below 10%. Consistently low CPU suggests the instance is over-provisioned for its workload.

Why it matters

An db.r7i.xlarge running at 5% average CPU is paying for 20x more compute than it needs. Right-sizing to a smaller instance class, or moving to Aurora Serverless v2 for variable workloads, can cut compute costs significantly with no impact on application performance.

What triggers a finding

Both conditions must be true:

  • Instance status is available
  • The 30-day average CPU utilization is at or below 10%

How to remediate

  1. Verify that the low CPU isn't masking a memory or I/O bound workload (check FreeableMemory and ReadIOPS/WriteIOPS metrics)
  2. If the instance is genuinely over-provisioned, downsize:
aws rds modify-db-instance \
  --db-instance-identifier my-db \
  --db-instance-class db.r8g.medium \
  --apply-immediately
  1. For workloads with highly variable traffic, consider Aurora Serverless v2 which scales compute automatically

CLDBRN-AWS-RDS-6

RDS DB Instance Unsupported Engine Version

Scan type: Discovery and IaC

Severity: High

What it checks

Flags RDS DB instances running MySQL 5.7 or PostgreSQL 11, which are past their standard support end-of-life and now incur extended support charges from AWS.

Why it matters

AWS charges extended support fees for engine versions past their standard EOL date. For MySQL 5.7, this adds $0.0725 per vCPU-hour in Year 1, doubling in Year 2. For PostgreSQL 11, the same pricing applies. On a Multi-AZ db.r7i.xlarge (4 vCPUs), that's an extra ~$210/month in Year 1 on top of the regular instance cost.

What triggers a finding

Either of these conditions:

  • Engine is mysql and version starts with 5.7
  • Engine is postgres and version starts with 11

How to remediate

Upgrade to a supported major version. For MySQL, the upgrade path is 5.7 -> 8.0. For PostgreSQL, 11 -> 14 or higher:

aws rds modify-db-instance \
  --db-instance-identifier my-db \
  --engine-version 8.0.39 \
  --allow-major-version-upgrade \
  --apply-immediately

Test the upgrade on a snapshot restore first. Review the MySQL 8.0 or PostgreSQL 14+ breaking changes that may affect your application queries.

IaC resources checked

IaC ToolResource Type
Terraformaws_db_instance
CloudFormationAWS::RDS::DBInstance

CLDBRN-AWS-RDS-7

RDS Snapshot Without Source DB Instance

Scan type: Discovery

Severity: Medium

What it checks

Flags RDS snapshots older than 30 days whose source DB instance no longer exists. Orphaned snapshots from deleted instances often accumulate indefinitely because nobody remembers to clean them up.

Why it matters

RDS snapshot storage costs $0.095 per GB-month. A 500 GB snapshot from a deleted production instance costs ~$47/month and will keep billing forever unless someone explicitly deletes it. Teams that frequently create and delete development databases are especially prone to snapshot accumulation.

What triggers a finding

Both conditions must be true:

  • The snapshot's source dbInstanceIdentifier does not match any currently active RDS instance in the same account and region
  • The snapshot's snapshotCreateTime is more than 30 days in the past

How to remediate

  1. Verify the snapshot isn't needed for compliance or disaster recovery
  2. If it's no longer needed, delete it:
aws rds delete-db-snapshot \
  --db-snapshot-identifier my-old-snapshot
  1. For long-term archival, export the snapshot to S3 first (cheaper storage) and then delete the RDS snapshot:
aws rds start-export-task \
  --export-task-identifier my-export \
  --source-arn arn:aws:rds:us-east-1:123456789012:snapshot:my-old-snapshot \
  --s3-bucket-name my-archive-bucket \
  --iam-role-arn arn:aws:iam::123456789012:role/rds-export-role \
  --kms-key-id alias/my-key

CLDBRN-AWS-RDS-8

RDS Performance Insights Extended Retention

Scan type: IaC

Severity: Low

What it checks

Flags DB instances that enable Performance Insights with retention beyond the included 7-day free period. Extended retention (up to 24 months) incurs additional charges.

Why it matters

Performance Insights includes 7 days of data retention at no extra cost. Extending retention to 731 days (24 months) costs $2.48/vCPU-month for instances outside the free tier. A db.r6g.4xlarge with 16 vCPUs would pay ~$39.68/month for extended retention. Unless you need long-term performance trend analysis, the free 7-day window is sufficient for most troubleshooting.

What triggers a finding

performanceInsightsEnabled is true AND performanceInsightsRetentionPeriod is a number greater than 7.

How to remediate

Set performance_insights_retention_period to 7 in Terraform, or set PerformanceInsightsRetentionPeriod to 7 in CloudFormation. Only extend retention if you have a specific need for long-term performance data.

IaC resources checked

IaC ToolResource Type
Terraformaws_db_instance
CloudFormationAWS::RDS::DBInstance

CLDBRN-AWS-RDS-9

RDS DB Instance Stopped

Scan type: Discovery

Severity: High

What it checks

Flags RDS DB instances that are currently in the stopped state. AWS only allows an RDS instance to stay stopped for up to 7 days before it auto-restarts, so a still-stopped instance found at scan time is either mid-cycle or has been manually kept down through repeated stop calls.

Why it matters

A stopped instance doesn't bill for compute, but its provisioned storage, any Multi-AZ standby storage, and retained snapshots keep billing the whole time. Left unattended, a stopped instance either auto-restarts and resumes full billing without anyone deciding that, or its storage quietly accumulates cost with no application using it.

What triggers a finding

dbInstanceStatus is stopped.

How to remediate

Decide whether the instance is still needed. If not, take a final snapshot and delete the instance — that ends the provisioned-storage and standby billing. The retained final snapshot may remain billable as backup storage once your regional backup usage exceeds the free allocation, so weigh that against keeping the recovery point rather than deleting it reflexively. If the instance needs to stay paused, note why so it isn't re-flagged as forgotten, and be aware AWS will auto-restart it after 7 days regardless.


CLDBRN-AWS-RDS-10

RDS Manual Snapshot Max Age Exceeded

Scan type: Discovery

Severity: Medium

What it checks

Flags manual RDS snapshots older than 90 days. Unlike CLDBRN-AWS-RDS-7, which only flags snapshots whose source instance is gone, this rule catches aging manual snapshots regardless of whether the source instance still exists — a broader safety net for snapshot sprawl.

Why it matters

Manual snapshots don't expire on their own and keep billing indefinitely once your total backup storage exceeds the free allocation (backup storage up to the size of your provisioned storage is free while the source instance exists; rates beyond that vary by region, around $0.095/GB-month in us-east-1). A 90-day-old manual snapshot has usually outlived the point-in-time recovery need it was created for; automated snapshots with a retention window already cover ongoing backup needs.

What triggers a finding

snapshotType is manual AND snapshotCreateTime is 90 or more days in the past.

How to remediate

Review the flagged snapshot and confirm it's not held for compliance or a specific recovery point. If it's no longer needed, delete it:

aws rds delete-db-snapshot \
  --db-snapshot-identifier my-old-manual-snapshot

For snapshots that must be retained as restorable recovery points, keep the RDS snapshot — an RDS snapshot export to S3 writes Parquet data for analytics and cannot be restored as a DB snapshot, so it is not a cheaper substitute for the snapshot itself.


See Also

  • CLI discover command — scan live RDS instances
  • CLI scan command — scan IaC templates for RDS issues
  • SDK Reference — run scans programmatically
← LambdaRedshift →