Guide
Flyway and Liquibase drift: what migrations miss
flyway validate checks migration files, not the live schema. What Flyway and Liquibase drift checks see, what they miss between deploys, and how to watch it.
Guide
flyway validate checks migration files, not the live schema. What Flyway and Liquibase drift checks see, what they miss between deploys, and how to watch it.
A team that runs every schema change through Flyway or Liquibase has good reason to believe production matches the migration folder. The belief holds right up to the first hotfix applied by hand at two in the morning, the index a DBA added during an incident, or the column a vendor's installer created on its own. The migration tool did not make those changes, so it does not know about them, and most of its checks are not designed to notice.
flyway validate compares the migrations recorded in flyway_schema_history with the migration files on disk: versions, descriptions and checksums. It fails when a file was edited after it was applied or when an applied migration is missing locally. It never reads the tables, columns or indexes of the database. A column dropped by hand passes validation, because the history table still says the migration that created it ran successfully.
Flyway's paid editions add a drift check that compares the database with a snapshot taken after the last deployment and reports objects that differ. It answers the question at deployment time, when someone runs it.
Liquibase works the same way at its core. The DATABASECHANGELOG table records which changesets ran, and checksums catch edited changesets. Its diff command does inspect real schemas, comparing two databases or a database with a saved snapshot:
liquibase snapshot --snapshot-format=json --output-file=after-release.json
liquibase diff \
--reference-url="offline:postgresql?snapshot=after-release.json" \
--url="jdbc:postgresql://db.internal:5432/sales"
Saving a snapshot after each release and diffing against it later is a workable drift check built entirely from the open source tool. Liquibase also offers drift reports in its commercial edition.
All of these checks run when someone runs them, usually inside a deployment pipeline. Drift happens between deployments. A column dropped on Tuesday is discovered at the next release, or when the code that reads it fails, whichever comes first. The checks are also scoped to the schemas the tool manages, so objects created by other applications, reporting schemas and objects in other databases on the same server are outside their view.
There is a second subtlety. When a drift check fails in the pipeline, the deployment stops, which is correct, and the person fixing it now has to work out what changed, when and whether it matters, under release pressure.
Continuous drift detection reads the live catalog on a schedule, independently of deployments, and compares it with the previous reading. Changes made by migrations show up as expected entries right after a release. Changes made any other way show up within one scan interval, with enough detail to decide whether to write a migration that records them or to revert them.
Taavik's schema change detection does this for PostgreSQL, MySQL, SQL Server and Redshift. An agent inside the network reads the catalog with a read-only login every 6, 12 or 24 hours or weekly, with daily as the most frequent option on the free plan, and the workspace compares each scan with the previous one. Each change carries a severity: a removed column, a changed type or a nullability flip is likely breaking, a modified view or routine needs attention, an added object is informational. Renamed tables are recognised as renames. Alerts can send only the likely breaking changes to the channel the on-call team watches.
It complements the migration tool rather than replacing it. Taavik does not know which migration file a change came from and does not generate migrations; it reports what the catalog looks like and how that differs from the last scan. Snapshot detection also misses a change made and reverted between two scans and does not record who made a change, which is where the database's own audit log comes in.
The working combination is the migration tool as the only sanctioned way to change the schema, its drift check in the pipeline, and a continuous comparison that says, between releases, when the sanctioned way was bypassed.
Engine-specific ways to record who changed what: PostgreSQL, MySQL, SQL Server and Azure SQL Database.