MySQL 8.0 reaches the end of Oracle's extended support in April 2026. After that there are no more security fixes for the version that most of the LAMP estate moved onto over the last five years. The successor is 8.4 LTS, supported into the early 2030s; the 9.x Innovation releases are short-lived and are not where a production business application belongs.
The good news first: 8.0 to 8.4 is a much smaller change than 5.7 to 8.0 was. There is no data dictionary rebuild, no charset migration, no mysql_upgrade step. Most applications' SQL runs unchanged. What bites is configuration and authentication — the server refuses to start on options it no longer recognizes, and old clients stop being able to log in. Both are findable in advance, which is the entire job.
If you are still on 5.7, ignore 8.4 for now and read the 5.7 to 8.0 checklist instead. Go 5.7 → 8.0 → 8.4, in that order, one hop at a time. In-place jumps across two majors are unsupported and go wrong in ways nobody enjoys diagnosing.
1. Get current on 8.0 first
Upgrade to the latest 8.0.4x release and run it in production for a week before you plan anything else. Two reasons: the deprecation warnings you need are only complete in late 8.0 releases, and it separates "broken by 8.4" from "broken by a patch we were twelve releases behind on."
Then read the error log. Late 8.0 emits a deprecation warning for nearly everything 8.4 removes:
grep -iE 'deprecat|will be removed' /var/log/mysql/error.log | sort -u
Every distinct line there is a work item. This one command usually produces the whole task list.
2. The authentication change is the one that takes sites down
mysql_native_password still exists in 8.4 but is disabled by default — it ships as a plugin the server does not load unless you ask. Any account still using it cannot authenticate after the upgrade, and the error the application logs is unhelpful.
Inventory before you touch anything:
SELECT user, host, plugin FROM mysql.user
WHERE plugin = 'mysql_native_password';
If the list is empty, you are clear. If it is not, decide per account:
-
Application accounts on PHP 7.4+: migrate them. mysqlnd has spoken
caching_sha2_passwordsince PHP 7.4, so this is usually a one-line change per account:ALTER USER 'app'@'10.0.%' IDENTIFIED WITH caching_sha2_password BY '<password>';Do this while still on 8.0, in a maintenance window, and verify the application reconnects. It is reversible on 8.0; it is not something you want to discover on the new server.
-
Old clients you cannot change yet — a PHP 5.6 admin tool, a reporting box, a vendor integration: start
mysqldwith--mysql-native-password=ONin 8.4 as a temporary bridge, and put a date on removing it. The plugin is on its way out entirely, so treat this as a loan, not a solution.
While you are in there, check that connections use TLS. 8.4 tightens the defaults, and an application that was quietly connecting in the clear across a VPC is worth catching now.
3. Config file archaeology
This is what actually stops the upgraded server from starting. 8.4 removed a long list of options and system variables that 8.0 merely deprecated, including the old replication terminology (--master-info-repository, --slave-* options and the SLAVE syntax, replaced by SOURCE/REPLICA forms), several binlog_transaction_dependency_* knobs, and assorted legacy compatibility flags.
Do not audit this by eye. Install 8.4 on a scratch VM, copy your my.cnf onto it, and run:
mysqld --defaults-file=/etc/mysql/my.cnf --validate-config
It will name each unknown variable and exit. Fix, repeat until it is silent. Ten minutes of work that turns a failed 2 a.m. restart into a non-event.
Do the same pass over anything else that talks SQL to the server: replication setup scripts, monitoring checks, backup wrappers, and any application code that still issues SHOW SLAVE STATUS or CHANGE MASTER TO. Grep the repository:
grep -rniE 'slave|change master' --include='*.php' --include='*.sh' .
4. Also check the defaults that changed
8.4 changes some defaults rather than removing them — most notably around InnoDB buffer pool sizing behaviour, redo log capacity (innodb_redo_log_capacity supersedes the old innodb_log_file_size pair), and replication retry behaviour. If your my.cnf sets these explicitly you keep your values and nothing surprises you; if you relied on 8.0's defaults, note the new ones and re-check your memory arithmetic against the box's actual RAM before you promote.
5. Rehearse on a replica, then fail over
The upgrade path we use, and the one worth the extra day:
- Take a fresh backup and restore it onto a scratch host — the drill doubles as proof the backup restores.
- Upgrade that copy to 8.4. Time it. A well-fed 8.0 dataset typically upgrades in minutes, but you want the real number, not a typical one.
- Point a staging copy of the application at it and run the real work: logins, checkout, the month-end report, the nightly cron jobs. Compare
EXPLAINoutput on your five slowest queries against 8.0 — optimizer changes between majors occasionally reshuffle a plan, and it is cheaper to find that here. - In production, upgrade the replica first. MySQL supports a replica running a higher version than its source, so an 8.4 replica following an 8.0 source is a supported, low-risk state you can sit in for days while it takes read traffic.
- When the replica has been healthy under real load, promote it and fail the application over. Keep the old 8.0 source running, stopped but intact, as the warm rollback path for a week.
That sequence gives you a rollback that is a DNS or config change rather than a restore. It costs one extra server for a week.
6. What this is not
It is not a performance project. Do not tune, resize, or re-platform in the same change window — you will not know which change caused what. Upgrade, verify, then look at numbers.
It is also not urgent in the panic sense. April 2026 is a date on a calendar; a plan that lands the upgrade in the quarter before it is a normal piece of maintenance. What is not fine is arriving at the date having never checked the auth plugin column. That query takes five seconds. Run it today.
If you would rather have someone else do the compatibility inventory and the replica rehearsal, that is exactly what our upgrade work is. And if your --validate-config run comes back clean and mysql.user shows no native-password accounts, you have a boring upgrade ahead of you and you do not need us for it.