Compare Staging and Production MySQL Schemas Before a Release
Release day for a team on MySQL. The new code has been tested on staging for a week, and staging has had the release’s migrations for a week. The question before shipping is a plain one: what does staging have that production doesn’t, and what does production have that nobody put in staging?
Migration tools answer half of it, the half they applied. RadarModel Schema’s diff reads both databases as they are and lists every difference, whoever made it.

One command, both databases, every difference.
The setup
Both databases go in one config, each with its own connection string from the environment:
{
"databases": [
{"name": "prod", "driver": "mysql", "dsn_env": "PROD_MYSQL_DSN"},
{"name": "staging", "driver": "mysql", "dsn_env": "STAGING_MYSQL_DSN"}
]
}
On MySQL and MariaDB the user needs SELECT, SHOW VIEW and TRIGGER on each database, so a hidden table is never mistaken for a missing one.
What the diff found
This is the released binary against two real MariaDB databases, app and app_staging. Staging has the release’s migration: a new currency column and a wider status. Production has an index someone added by hand a month ago.
$ radarmodel-schema diff prod staging
RadarModel Schema: 1 breaking, 2 warnings: what staging has that differs from prod
prod vs staging WARNING column app.orders.currency new
prod vs staging BREAKING column app.orders.status type varchar(20) -> varchar(40)
prod vs staging WARNING index app.customers.customers_name gone
$ echo $?
1
The two databases have different names, app and app_staging, and the diff lines them up before comparing, so the report talks about app.orders on both sides.
The first two lines are the migration, as expected. Widening a column is usually harmless, but RadarModel Schema calls every type change breaking because it can’t know what the app does with it. Here it’s a reminder that the migration has to run before the new code. The third line is the surprise. Production has an index staging never had, so the release was tested without it, and a migration that rebuilds customers would quietly drop it.
diff exits 1 when the databases differ and 0 when they match, so it can sit in a release checklist or a pipeline. The reference has the details.