Zero-downtime MySQL 8.0 → 8.4 upgrades on RDS with Blue/Green deployments
Published 21 October 2026 · AWS RDS · MySQL · Zero downtime
Amazon RDS ended standard support for MySQL 8.0 on 31 July 2026. From 1 August, every instance still on 8.0 started paying RDS Extended Support charges on top of its normal bill, for a version that only gets critical fixes. For a US healthcare platform we operate, that meant moving three production RDS MySQL instances to 8.4 LTS before the deadline, with no downtime beyond the switchover itself.
This is the runbook we used. It is written for the engineer who has to do the same thing, so it includes the parts that went sideways on paper before they could go sideways in production.
The starting point
- Three production instances, all on MySQL 8.0, plus a test instance we used as the rehearsal target.
- One custom parameter group whose only user-set value was a
max_connectionsformula override. - One instance with a cross-Region read replica — which, as you'll see, changes the plan.
- No SSH, no public endpoints. Database access for engineers runs through AWS Systems Manager (SSM) port forwarding, so every check below was done through the same tunnels the team uses daily.
Step 1: Inventory before anything else
For each instance we wrote down: engine version, instance class, parameter group and option group, replicas (and their Regions), automated-backup retention, and every client that connects — the app, queue workers, scheduled jobs and the GUI tools engineers use. The inventory is what turns a scary migration into a checklist, and it is the first page of the runbook.
Step 2: Compatibility prechecks
We ran the MySQL Shell upgrade checker (util.checkForServerUpgrade()) against each instance with
8.4 as the target, and fixed every error before creating anything. RDS also runs its own prechecks
when it upgrades and refuses to proceed if they fail, but finding problems in the checker output on a
Tuesday afternoon beats finding them mid-upgrade.
Two things to look at closely:
- Authentication. Community MySQL 8.4 disables the old
mysql_native_passwordplugin by default. On RDS for MySQL 8.4 it is still available, so existing users kept working — but check that every driver your applications use supportscaching_sha2_passwordbefore you create new users, and keep TLS enforced. - Changed defaults. MySQL 8.4 changed several InnoDB defaults (the adaptive hash index, for example, is now off). Don't assume 8.4 behaves like 8.0 under your workload; that's what the bake is for.
Step 3: Build the 8.4 parameter group deliberately
Create a new custom parameter group in the mysql8.4 family and port settings on purpose, not by
copying everything across. Our group had a single override — the max_connections formula — so we
carried that one value and left everything else at the 8.4 defaults. That override got its own review
step: a formula tuned for one instance class silently changes meaning if the green instance ever runs
on a different class.
Step 4: Create the Blue/Green deployment
An RDS Blue/Green deployment creates a "green" copy of your production ("blue") instance that stays in sync through replication. You upgrade green to 8.4, test it, and switch over when you're ready.
Things that bit, or nearly bit:
- Cross-Region read replicas aren't supported by Blue/Green deployments. The instance with a replica in another Region needed its own order of operations, decided in advance: what happens to the replica, how it is rebuilt on 8.4 afterwards, and how long you can accept running without cross-Region coverage. Write that sequence into the runbook before you start.
event_schedulermust be disabled on the green environment.- Custom option groups prevent specifying the major version upgrade at creation; in that case you create the deployment first and upgrade green afterwards.
Step 5: The full bake
This is the step teams skip, and the one that matters most. We let green run on 8.4 with replication active and checked it against production-shaped reads before anyone talked about switching:
- replica lag stays near zero under normal daytime load;
- error logs on green stay clean;
- the application's heaviest read queries return the same results with acceptable latency;
- CloudWatch metrics (CPU, freeable memory, connections) look like blue's.
For the most critical instance the full bake was mandatory. We staggered the work — test instance first, then production instances one at a time — so every switchover used a runbook that had already been run, and finished with a buffer before the 31 July deadline.
Step 6: Switchover go/no-go
Switchover was a scheduled event with a written go/no-go list, not a button press:
- Replica lag is effectively zero.
- No long-running transactions or DDL on blue.
- Application error rates are at baseline, and someone who knows the app is watching.
- A fresh snapshot exists and backups are healthy on both sides.
- The rollback decision (below) has been made in advance.
During switchover RDS swaps the endpoints, so applications keep their connection strings. AWS says
switchover typically completes in under a minute. The old blue instance is renamed (for example with an
-old1 suffix) and kept.
Step 7: Be honest about rollback
Before switchover, rollback is trivial: delete the Blue/Green deployment and nothing in production
has changed. After switchover, there is no automatic replication back to the old 8.0 instance.
Going back means restoring from the retained old instance or a snapshot and reconciling anything
written since — which is why the go/no-go list exists. Keep the -old1 instance for at least your
required recovery window (it keeps its own backups and point-in-time recovery), and note that you
restore it by its resource ID, not its old name.
After the switchover
- Re-check IAM role associations, tags and anything that referenced resource IDs.
- Confirm alarms and dashboards point at the new instance.
- Rebuild the cross-Region replica on 8.4.
- Delete the old instance once the recovery window has passed, so you stop paying for it.
Lessons learned
- The runbook is the deliverable. The second and third migrations took a fraction of the first one's effort because the first produced a tested, written runbook.
- Custom parameter groups deserve their own review step, even when they hold a single value.
- Cross-Region read replicas change the order of operations. Find them in the inventory, not on switchover day.
- The bake is where you buy confidence. Skipping it saves a day and risks the whole migration.
Still on MySQL 8.0 and paying Extended Support? We do this as a fixed-price engagement: a Zero-Downtime Database Upgrade is $3,000 per database, with a written runbook, a full bake and a rehearsed rollback plan.
Book a 20-minute call
