Amazon RDS – Consider Using Latest Generation Instances for m-Family

·

By

Infracost

Amazon RDS – Consider Using Latest Generation Instances for m-Family

·

By

Infracost

The Amazon RDS m-family latest generation policy flags general-purpose Amazon RDS DB instances on a previous class, such as db.m3 or db.m4, and recommends db.m5 or newer. In US East (N. Virginia), a db.m5.xlarge costs about 8% less per month than a db.m3.xlarge for RDS for MySQL, with more memory and a faster processor. Apply this policy to any aws_db_instance whose instance_class starts with db.m3. or db.m4..

Attribute

Detail

Cloud Provider

Amazon Web Services (AWS)

Resource Type

Amazon RDS general-purpose DB instances, m-family

Terraform Attribute

instance_class on aws_db_instance

Non-compliant Values

Previous m-family classes, for example db.m3.xlarge or db.m4.large

Compliant Value

A current generation class such as db.m5.xlarge, db.m6i.xlarge, or db.m7i.xlarge

Cost Impact

db.m5.xlarge is about $250/month vs about $270/month for db.m3.xlarge (RDS for MySQL, US East, Single-AZ), with 16 GiB instead of 15 GiB of memory

Why This Policy Matters

How It Helps Reduce Cloud Costs

Amazon RDS m-family DB instances are general-purpose. Teams use them for relational databases that need a balance of CPU, memory, and network, such as application backends and internal services.

An Amazon RDS db.m5 instance runs on a 1st or 2nd generation Intel Xeon Platinum 8000 series processor (Skylake-SP or Cascade Lake). It sustains an all-core turbo of up to 3.1 GHz. The older db.m3 and db.m4 classes run on earlier Intel Xeon E5 processors.

The db.m5 class also scales further. A db.m5.24xlarge offers 96 vCPUs and 384 GiB of memory, while the largest db.m4 class, db.m4.16xlarge, stops at 64 vCPUs and 256 GiB.

The Amazon RDS m-family upgrade makes the newer class both faster and cheaper per hour. For EC2, AWS states that M5 delivers up to 20% better price/performance than M4.

Staying on db.m3 or db.m4 is no longer a stable choice either. AWS has started retiring both classes on most Amazon RDS engines. An old class in Terraform code is now a liability as well as a cost.

Potential Savings

Amazon RDS m-family savings come from a lower hourly rate at the same size, plus the option to downsize once the faster processor is in place.

Instance class

vCPUs

Memory

Approx. monthly on-demand cost (RDS for MySQL, US East, Single-AZ)

db.m3.xlarge

4

15 GiB

$270

db.m4.xlarge

4

16 GiB

$255

db.m5.xlarge

4

16 GiB

$250

db.m6i.xlarge

4

16 GiB

$250

Monthly figures assume 730 hours at list on-demand rates. Prices vary by engine, region, deployment option, and purchase option, and Multi-AZ deployments cost roughly double.

The direct saving per instance is modest, about 8% moving from db.m3.xlarge to db.m5.xlarge and about 2% from db.m4.xlarge. Across a fleet of Multi-AZ databases, that gap adds up every month.

Downsizing is where larger savings appear. Each step down within the Amazon RDS m-family roughly halves the instance cost. A db.m4.2xlarge workload that fits on db.m5.xlarge after load testing cuts its instance spend by about half.

Implementation Guide

Infrastructure-as-Code Example (Terraform)

The following examples show an Amazon RDS DB instance on a previous m-family class, and the corrected configuration on db.m5.

Non-compliant configuration: Amazon RDS DB instance on db.m4

resource "aws_db_instance" "billing" {
  identifier              = "billing-db"
  engine                  = "postgres"
  engine_version          = "16"
  instance_class          = "db.m4.xlarge"
  allocated_storage       = 200
  storage_type            = "gp3"
  db_subnet_group_name    = aws_db_subnet_group.private.name
  vpc_security_group_ids  = [aws_security_group.db.id]
  multi_az                = true
  backup_retention_period = 7
  username                = var.db_username
  password                = var.db_password
}
resource "aws_db_instance" "billing" {
  identifier              = "billing-db"
  engine                  = "postgres"
  engine_version          = "16"
  instance_class          = "db.m4.xlarge"
  allocated_storage       = 200
  storage_type            = "gp3"
  db_subnet_group_name    = aws_db_subnet_group.private.name
  vpc_security_group_ids  = [aws_security_group.db.id]
  multi_az                = true
  backup_retention_period = 7
  username                = var.db_username
  password                = var.db_password
}
resource "aws_db_instance" "billing" {
  identifier              = "billing-db"
  engine                  = "postgres"
  engine_version          = "16"
  instance_class          = "db.m4.xlarge"
  allocated_storage       = 200
  storage_type            = "gp3"
  db_subnet_group_name    = aws_db_subnet_group.private.name
  vpc_security_group_ids  = [aws_security_group.db.id]
  multi_az                = true
  backup_retention_period = 7
  username                = var.db_username
  password                = var.db_password
}

This configuration pays more per hour than db.m5.xlarge for an older processor. It also names a class that Amazon RDS no longer lets you create for PostgreSQL, MySQL, MariaDB, or SQL Server.

Compliant configuration: Amazon RDS DB instance on db.m5

resource "aws_db_instance" "billing" {
  identifier              = "billing-db"
  engine                  = "postgres"
  engine_version          = "16"
  instance_class          = "db.m5.xlarge"
  allocated_storage       = 200
  storage_type            = "gp3"
  db_subnet_group_name    = aws_db_subnet_group.private.name
  vpc_security_group_ids  = [aws_security_group.db.id]
  multi_az                = true
  backup_retention_period = 7
  username                = var.db_username
  password                = var.db_password
  apply_immediately       = false
}
resource "aws_db_instance" "billing" {
  identifier              = "billing-db"
  engine                  = "postgres"
  engine_version          = "16"
  instance_class          = "db.m5.xlarge"
  allocated_storage       = 200
  storage_type            = "gp3"
  db_subnet_group_name    = aws_db_subnet_group.private.name
  vpc_security_group_ids  = [aws_security_group.db.id]
  multi_az                = true
  backup_retention_period = 7
  username                = var.db_username
  password                = var.db_password
  apply_immediately       = false
}
resource "aws_db_instance" "billing" {
  identifier              = "billing-db"
  engine                  = "postgres"
  engine_version          = "16"
  instance_class          = "db.m5.xlarge"
  allocated_storage       = 200
  storage_type            = "gp3"
  db_subnet_group_name    = aws_db_subnet_group.private.name
  vpc_security_group_ids  = [aws_security_group.db.id]
  multi_az                = true
  backup_retention_period = 7
  username                = var.db_username
  password                = var.db_password
  apply_immediately       = false
}

The instance_class value is the only functional change. Setting apply_immediately = false defers the class change to the next preferred maintenance window instead of restarting the database on apply.

Terraform updates the existing Amazon RDS DB instance in place. The data, endpoint, and identifier stay the same.

Step-by-Step Fix Instructions

  1. Search Terraform code for instance_class values that start with db.m3. or db.m4. in aws_db_instance resources.

  2. Check shared modules, .tfvars files, and variable defaults. Old instance classes often live in a variable "instance_class" default rather than the resource block.

  3. Run terraform plan on each affected workspace. If AWS has already upgraded the database, the plan shows a change from db.m5 back to the old class, which signals drift.

  4. Confirm the target class supports your engine and engine version with aws rds describe-orderable-db-instance-options.

  5. Decide whether to keep the same size or test one size smaller. Use CloudWatch CPUUtilization and FreeableMemory from the last 30 days.

  6. Change instance_class, and set apply_immediately = false if the change should wait for the maintenance window.

  7. Run terraform plan again and confirm it shows an in-place update to instance_class, not a replacement of the Amazon RDS DB instance.

  8. Apply the change to non-production databases first, then production.

  9. Add Infracost to CI/CD so new previous-generation Amazon RDS m-family classes are flagged in pull requests before they merge.

Best Practices

  • Pin approved Amazon RDS instance classes in shared Terraform modules with a validation block, so previous-generation classes fail at terraform plan.

  • Fix the code even when AWS has already upgraded the database. An outdated instance_class in Terraform is drift that the next apply will try to reverse.

  • Review Reserved Instances before migrating. An Amazon RDS Reserved Instance covers a specific instance family, so a db.m4 reservation does not apply to db.m5 usage.

  • Treat Graviton classes such as db.m6g as a separate decision. They cost less per hour but need engine version support and testing.

  • This policy matters most for databases created years ago and never revisited. New databases rarely start on db.m4 unless an old module default is still in use.

An example validation block for a shared module:

variable "instance_class" {
  type    = string
  default = "db.m5.large"

  validation {
    condition     = !can(regex("^db\\.m[34]\\.", var.instance_class))
    error_message = "Previous-generation db.m3 and db.m4 classes are not allowed. Use db.m5 or newer."
  }
}
variable "instance_class" {
  type    = string
  default = "db.m5.large"

  validation {
    condition     = !can(regex("^db\\.m[34]\\.", var.instance_class))
    error_message = "Previous-generation db.m3 and db.m4 classes are not allowed. Use db.m5 or newer."
  }
}
variable "instance_class" {
  type    = string
  default = "db.m5.large"

  validation {
    condition     = !can(regex("^db\\.m[34]\\.", var.instance_class))
    error_message = "Previous-generation db.m3 and db.m4 classes are not allowed. Use db.m5 or newer."
  }
}

Tools and Scripts

How does Infracost detect previous-generation Amazon RDS m-family instances automatically?

The Amazon RDS m-family latest generation policy is available in Infracost, including in the free trial. When Infracost runs in CI/CD, it checks Amazon RDS resources in each pull request. Previous-generation m-family classes are flagged in the PR comment, with the file and line to change.

The same Infracost pull request comment shows the estimated monthly cost of the change. Reviewers see what the database costs before it merges, not on next month's AWS bill.

Infracost also scans connected repositories for previous-generation Amazon RDS m-family classes already in code. FinOps and platform teams can burn down that backlog over time, tracking issues prevented in pull requests separately from existing issues fixed.

Teams can set the policy to warn engineers or block pull requests. Limiting it to new resources keeps an unrelated pull request from forcing a database restart.

To find previous-generation m-family classes in a Terraform codebase:

grep -rnE '"db\.m[34]\.[0-9]*x?large"' --include="*.tf" --include="*.tfvars"
grep -rnE '"db\.m[34]\.[0-9]*x?large"' --include="*.tf" --include="*.tfvars"
grep -rnE '"db\.m[34]\.[0-9]*x?large"' --include="*.tf" --include="*.tfvars"

To list running Amazon RDS DB instances on db.m3 or db.m4 with the AWS CLI:

aws rds describe-db-instances \
  --query "DBInstances[?starts_with(DBInstanceClass, 'db.m3') || starts_with(DBInstanceClass, 'db.m4')].{id:DBInstanceIdentifier,class:DBInstanceClass,engine:Engine,multiAz:MultiAZ}" \
  --output

aws rds describe-db-instances \
  --query "DBInstances[?starts_with(DBInstanceClass, 'db.m3') || starts_with(DBInstanceClass, 'db.m4')].{id:DBInstanceIdentifier,class:DBInstanceClass,engine:Engine,multiAz:MultiAZ}" \
  --output

aws rds describe-db-instances \
  --query "DBInstances[?starts_with(DBInstanceClass, 'db.m3') || starts_with(DBInstanceClass, 'db.m4')].{id:DBInstanceIdentifier,class:DBInstanceClass,engine:Engine,multiAz:MultiAZ}" \
  --output

If the database is managed by Terraform, change instance_class in code rather than in the console. Otherwise the next terraform apply tries to set the old class again.

Examples of Impact

Amazon RDS m-family upgrades pay off through a lower rate, more headroom, and cleaner Terraform, because the per-resource change is one attribute.

Illustrative example: a fleet of service databases. A platform team finds a dozen PostgreSQL databases on db.m4.xlarge from an old module default, all Multi-AZ. Updating the module default to db.m5.xlarge lowers the hourly rate, adds headroom, and removes the drift left by AWS automatic upgrades.

Illustrative example: an oversized application database. A team runs a MySQL application database on db.m3.2xlarge with low CPU use. After load testing confirms the working set fits in 16 GiB, the team moves it to db.m5.xlarge, cutting the instance cost by more than half.

(These are illustrative scenarios, not specific customer accounts.)

Considerations and Caveats

The Amazon RDS m-family upgrade is low risk, but it does restart the database.

  • Restart required. Changing instance_class restarts the Amazon RDS DB instance. Single-AZ databases are unavailable during the change.

  • Engine version support. Older engine versions may not support db.m5 or newer classes. Check orderable options before planning the change.

  • Reservations do not transfer. Amazon RDS Reserved Instances are tied to an instance family. A db.m4 reservation keeps billing until it expires.

  • AWS may move first. AWS has started automatic upgrades from db.m3 and db.m4 to db.m5 on several engines, during the maintenance window. Planning the change yourself keeps control of timing.

  • Provider-specific. This policy targets Amazon RDS through the aws Terraform provider. Azure and Google Cloud managed databases have different generations and attribute names.

Related Policies and Concepts

  • Amazon RDS - consider using latest generation instances for r family instances: the same generation upgrade for memory-optimized Amazon RDS classes such as db.r3 and db.r4.

  • Amazon RDS - consider using latest generation instances for t family instances: the burstable-class equivalent of this policy, moving db.t2 to db.t3.

  • Amazon RDS - consider using Graviton instances: a related Compute-group policy for moving Amazon RDS databases to Arm-based classes such as db.m6g, which cost less per hour.

  • Amazon EC2 - consider using latest generation instances for m family instances: the same general-purpose upgrade applied to EC2 instances.

  • RDS - consider upgrading gp2 storage type to gp3: a companion Amazon RDS policy that lowers storage cost on the same aws_db_instance resource.

Frequently Asked Questions (FAQs)

Is this policy supported in Infracost?

Yes. The Amazon RDS m-family latest generation policy is supported in Infracost and available in the free trial. Infracost flags Amazon RDS DB instances that use a previous m-family instance class, such as db.m3.xlarge, in the pull request that introduces them.

Can this policy be customized?

Yes. Teams can configure how Infracost enforces the Amazon RDS m-family latest generation policy. A finding can warn engineers or block the pull request. The policy can also be limited to new resources, so an unrelated change does not force a database restart.

Does Infracost automatically fix violations?

No. Infracost reports each previous-generation Amazon RDS m-family instance class in the pull request, with the file and line to change. The team chooses the target class and applies the change during a maintenance window.

Is this policy cloud-agnostic?

No. The Amazon RDS m-family latest generation policy targets Amazon RDS through the aws Terraform provider. Azure SQL Database and Google Cloud SQL have their own machine generations, with different resource and attribute names.

Can I still create Amazon RDS DB instances on db.m3 or db.m4?

No, for most engines. Amazon RDS no longer allows new db.m3 instances for MySQL, MariaDB, or PostgreSQL, or new db.m4 instances for MySQL, MariaDB, PostgreSQL, SQL Server, or Oracle. AWS has also started automatically upgrading existing Amazon RDS db.m3 and db.m4 instances to db.m5.

Does upgrading an Amazon RDS instance class cause downtime?

Yes, usually a short outage. Changing the instance class on an Amazon RDS DB instance restarts it. Multi-AZ deployments reduce the interruption to a failover, which typically takes one to two minutes.

How often should I review Amazon RDS instance classes?

Teams running Infracost in CI/CD get an Amazon RDS m-family check on every pull request that touches an RDS instance. For existing databases, a quarterly review of Amazon RDS instance classes is a reasonable cadence for most teams.

Create Free Account

This policy is supported in Infracost and available in the free trial. Sign up today and scan your code using our entire library of FinOps policies.

Get started
with Infracost

© 2026 Infracost Inc

Manage cookies

Get started
with Infracost

© 2026 Infracost Inc

Manage cookies

Get started
with Infracost

© 2026 Infracost Inc

Manage cookies