This check flags RDS instances running an outdated major engine version, which means you are missing security patches, bug fixes, and performance improvements. Plan a tested upgrade to a supported major version and enable automatic minor version upgrades.
Database engines do not age gracefully. The version of PostgreSQL, MySQL, MariaDB, or Oracle you launched two years ago is probably several releases behind now, and every release you skip stacks up more unpatched CVEs and missing features. The RDS Engine Version Outdated check catches Amazon RDS instances that are trailing the latest available major version so you can plan an upgrade before AWS forces one on you.
What this check detects
The rds_outdated_engine check inspects each RDS instance and compares its current engine major version against the latest version AWS offers for that engine family. If the gap is significant, or the version has reached (or is nearing) end of standard support, the instance is flagged.
Concretely, the check looks at the EngineVersion attribute returned by the RDS API and evaluates it against the available upgrade targets. An instance running PostgreSQL 11 when 16 is generally available, or MySQL 5.7 when 8.0 has been standard for years, is exactly what this surfaces.
Note: RDS distinguishes between minor and major versions. A minor upgrade (for example 15.3 to 15.7) is backward compatible and usually applied automatically. A major upgrade (15 to 16) can include breaking changes and must be triggered deliberately. This check is primarily concerned with major version drift.
Why it matters
An outdated engine is not just a cosmetic problem. It carries real, compounding risk.
Security patches stop arriving
When a major version reaches end of standard support, AWS stops shipping security patches for free. After that point you either pay for Extended Support or run a database with known, unpatched vulnerabilities exposed to your application. Database CVEs are not rare. PostgreSQL, MySQL, and Oracle all ship regular fixes for issues ranging from privilege escalation to denial of service.
AWS will eventually upgrade you automatically
AWS does not let instances run end-of-life engines forever. Once a version passes its end-of-standard-support date, AWS begins scheduling automatic major version upgrades during your maintenance window. An automatic major upgrade you did not test is a great way to discover that a deprecated function or a changed default broke production at 3 a.m.
Warning: Extended Support is billed per vCPU-hour and adds up fast on larger instances. Staying on an unsupported engine to avoid an upgrade can quietly become one of your bigger RDS line items.
You miss real improvements
Newer engine versions are not only about patches. PostgreSQL 16 brought parallel query and logical replication gains. MySQL 8.0 added window functions, common table expressions, and a far better optimizer. Sitting on an old version means writing around limitations that no longer need to exist.
How to fix it
Upgrading a major version is a controlled operation. Do not run it against production first. The workflow below restores a test copy, validates it, then upgrades the real instance during a planned window.
Step 1: Find what you are running and where you can go
aws rds describe-db-instances \
--query "DBInstances[].[DBInstanceIdentifier,Engine,EngineVersion]" \
--output table
Then list valid upgrade targets for a specific engine version:
aws rds describe-db-engine-versions \
--engine postgres \
--engine-version 13.13 \
--query "DBEngineVersions[].ValidUpgradeTarget[?IsMajorVersionUpgrade==\`true\`].[EngineVersion]" \
--output table
Step 2: Test the upgrade on a clone
Restore the latest snapshot to a temporary instance and upgrade that copy. This is where you catch deprecated functions, extension incompatibilities, and changed behavior.
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier myapp-db-upgradetest \
--db-snapshot-identifier myapp-db-latest-snapshot \
--db-instance-class db.t3.medium
# Once available, upgrade the clone
aws rds modify-db-instance \
--db-instance-identifier myapp-db-upgradetest \
--engine-version 16.4 \
--allow-major-version-upgrade \
--apply-immediately
Point a staging copy of your application at the upgraded clone and run your test suite. For PostgreSQL, run ANALYZE after the upgrade so the planner has fresh statistics, and check that all extensions came across cleanly.
Tip: RDS runs a pre-upgrade check and writes the results to the pg_upgrade or mysql upgrade logs, available in the RDS console under Logs & events. Read them. They flag incompatibilities before you touch production.
Step 3: Snapshot, then upgrade production
Danger: A major version upgrade is not reversible in place. If it goes wrong, your only path back is restoring from the snapshot you took beforehand. Always take a manual snapshot immediately before the upgrade and confirm it completed.
# Take a manual snapshot first
aws rds create-db-snapshot \
--db-instance-identifier myapp-db \
--db-snapshot-identifier myapp-db-pre-upgrade-16
# Wait for it to be available
aws rds wait db-snapshot-available \
--db-snapshot-identifier myapp-db-pre-upgrade-16
# Run the upgrade during your maintenance window
aws rds modify-db-instance \
--db-instance-identifier myapp-db \
--engine-version 16.4 \
--allow-major-version-upgrade \
--no-apply-immediately
Using --no-apply-immediately defers the upgrade to the next maintenance window. Use --apply-immediately only if you have an active maintenance period and accept the downtime now. A major upgrade takes the instance offline while it runs, so expect minutes of unavailability, more for large databases.
Warning: Multi-AZ does not eliminate downtime for a major version upgrade. The upgrade applies to both the primary and standby, and the instance is unavailable during the process. Plan for it.
Console route
- Open the RDS console and select the instance.
- Choose Modify.
- Under DB engine version, pick the target major version.
- Scroll down and select Apply during the next scheduled maintenance window (or apply immediately if you are ready).
- Confirm and review the summary of changes before saving.
How to prevent it from happening again
The fix is one-time. Staying current is the real goal. Bake version policy into your infrastructure and pipelines.
Enable automatic minor version upgrades
This keeps you on the latest patch level within a major version without manual effort. It does not handle major upgrades, but it closes the most common patch gap.
aws rds modify-db-instance \
--db-instance-identifier myapp-db \
--auto-minor-version-upgrade \
--apply-immediately
Pin versions in Terraform and review them
If you manage RDS with Terraform, set the engine version explicitly and make bumping it part of routine maintenance.
resource "aws_db_instance" "myapp" {
identifier = "myapp-db"
engine = "postgres"
engine_version = "16.4"
instance_class = "db.t3.medium"
allow_major_version_upgrade = true
auto_minor_version_upgrade = true
apply_immediately = false
maintenance_window = "sun:04:00-sun:05:00"
}
Gate it in CI with policy-as-code
Use a tool like OPA Conftest or Checkov to fail a pull request that introduces an RDS resource on an old engine. Here is a simple Rego rule that rejects unapproved PostgreSQL versions in a Terraform plan:
package rds.engine
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_db_instance"
resource.change.after.engine == "postgres"
version := resource.change.after.engine_version
not startswith(version, "15.")
not startswith(version, "16.")
msg := sprintf("RDS instance %s uses unsupported PostgreSQL version %s", [resource.address, version])
}
Tip: Pair the CI gate with a recurring scheduled scan. New CVEs and end-of-support dates appear after your code was merged, so a continuous check (like this Lensix check) catches drift that a one-time PR gate cannot.
Best practices
- Track end-of-standard-support dates. AWS publishes the calendar for each engine family. Put the dates in your team calendar and schedule upgrades a quarter ahead, not the week before forced upgrade.
- Never upgrade production first. Always validate on a snapshot restore. The cost of a temporary instance for a day is trivial next to an unplanned outage.
- Upgrade one major version at a time where the engine requires it. Some engines do not support skipping multiple major versions in a single jump. Check the valid upgrade targets and step through if needed.
- Keep minor auto-upgrade on. There is rarely a good reason to sit on an old patch level within a major version.
- Run
ANALYZEand re-check query plans after a major upgrade. Optimizer changes between versions can shift plan choices. Verify your critical queries still perform. - Test your application against the new engine's defaults. Changed defaults (stricter SQL modes, removed functions, new reserved keywords) are the most common source of post-upgrade breakage.
Staying on a supported engine version is low-effort once you treat it as routine maintenance rather than an emergency. Build the upgrade into your normal cadence, automate the patch level, and let a continuous check tell you when a new major version warrants a planned move.

