Skip to main content
Practices5 min read

Why database schemas drift, and what to do about it

Drift is not caused by carelessness. It is the predictable result of several people fixing urgent problems in different places. Here is where it comes from and how to make it visible.

SchemaSync Engineering

Product engineering · NG&NR Technologies

Every team that runs more than one database environment eventually finds that they no longer match. A column exists in staging that nobody remembers adding. An index is in production but not in the migration history. A stored procedure has a different body in each of three places.

This is usually treated as a discipline problem, and answered with a stricter process. That answer rarely works, because drift is not caused by people being careless. It is the predictable outcome of several competent people solving urgent problems in different places at different times.

Where drift actually comes from

In our experience it comes from four places, roughly in order of how often they occur.

  1. The emergency index. A query is slow at 2am, someone adds an index directly on production, and the incident closes. The index is real, it is helping, and it exists in no migration anywhere.
  2. The partially applied migration. A migration fails halfway. Someone fixes the immediate error by hand and moves on. The migration is marked as applied, but what it actually did differs from what it says it did.
  3. The environment-specific exception. Staging gets a smaller varchar, or a different DEFINER, or a table that only the test harness uses. It was deliberate at the time and nobody wrote it down.
  4. The abandoned branch. A feature branch adds a column, the branch is never merged, but the developer's local database and the shared development database keep the column.

None of these involve anyone doing anything unreasonable. Three of the four involve someone doing exactly the right thing under pressure.

Why migration history is not enough

Most teams already have a migration tool, and assume that its history is a record of the schema. It is not. It is a record of the changes the tool was asked to make. The difference matters, because every one of the four cases above produces a schema that the history cannot describe.

A migration history tells you what you intended. Only the database itself can tell you what is true. The only reliable way to know whether two environments match is to read both structures and compare them.

Making drift visible

Drift is not dangerous because it exists. It is dangerous because it is invisible until a deployment fails. Three habits move it into the open, in increasing order of effort:

  1. Compare before every release

    Compare the schema you are deploying from against the one you are deploying to, and read the differences. This takes a minute and catches the emergency index before it becomes a conflict.

  2. Keep a baseline snapshot

    Immediately after a successful release, save a snapshot of production. Comparing against it later tells you precisely what has changed since a known-good point, with no ambiguity about when.

  3. Fail the build on unexpected differences

    Once comparison is routine, automate it. A pipeline step that compares staging against production and fails on unexpected differences turns drift into a red build rather than a failed deployment.

Decide what is allowed to differ

Some differences are legitimate and permanent: AUTO_INCREMENT values will never match, and routine definers are usually environment-specific. If your comparison reports them every time, people stop reading the results — which costs you the real findings along with the noise.

Write those exceptions down as filter rules instead. The list itself becomes valuable documentation: it is an explicit statement of how your environments are permitted to differ, which is exactly the thing that was previously only in someone's head.

The point

You will not eliminate drift, because you cannot eliminate 2am incidents. What you can do is shorten the time between a schema diverging and someone knowing about it — from *the next failed deployment* to *the next comparison*. That is a change in process worth far more than a stricter policy.

  • schema drift
  • database practices
  • environments
  • migrations
All articles
Keep reading

Start comparing in the next five minutes

Download the 14-day trial and run it against your own databases. Full feature set, no credit card, nothing to configure first.

  • Windows 10 and 11 (64-bit)
  • Code-signed installer with a published checksum
  • Email support during the trial