Your migration passed. Will the version that is still running?

During a rollout, the previous application version keeps serving traffic against the new schema. Skewcheck runs that version's own tests against the proposed PostgreSQL schema, compares them with a run on the current schema, and blocks the merge only when it can show a reproducible failure tied to a specific change.

The workflow in GitLab

  1. A developer proposes a migration

    Shop v2 renames customers.email. v2's own tests pass. The gate reports Unsafe: v1 now fails with SQLSTATE 42703 on that column.

  2. GitLab Duo proposes a repair

    The developer mentions the custom Duo flow on the merge request. It reads the evidence from the gate's job log and opens a merge request on a skewcheck-repair/ branch. It cannot mark its own change as safe.

  3. The same gate judges the repair

    The engine and policy come from the target branch, not the repair branch. A defective repair is rejected; an expand/contract repair passes and v2 still works.

  4. A human merges

    The reviewer sees the original failure, the proposed change and the independent result side by side in the merge request.

Five verdicts, not a green tick

Safe

No supported incompatibility under the conditions tested. Not a universal guarantee.

Unsafe

The previous version fails in every candidate run, and a deterministic rule ties the SQLSTATE to a changed object.

Advisory

Something changed (an assertion, an unrelated error, a flaky result) but not enough to block.

No evidence

The experiment worked, but no test touched a risky change. Blocks by default.

Inconclusive

Missing baseline, broken migration, database or harness failure. Never reported as a pass.

Example scenarios

Each is a committed fixture with real engine output. Open one and run it again live on this server.

ScenarioVerdict
Additive change
Adds a nullable column, a new table and a plain index. Nothing the old version does can notice.
Safe
Column rename
v2 renames customers.email to email_address. v2 is fine; v1, still serving traffic during the rollout, is not.
Unsafe
Changed default
New orders default to "pending" instead of "new". The schema still accepts v1, but v1 now sees different data.
Advisory
Untested column drop
Drops customers.legacy_notes. No v1 test touches it, yet v1 admin code still does.
No evidence
Missing baseline
The pinned previous version cannot be found. Without it there is nothing to compare.
Inconclusive
Migration fails to apply
The proposed migration has a typo and does not apply. That is not a compatibility pass.
Inconclusive
Already-broken test
One v1 test already failed before this migration. It must not be blamed on the migration.
Safe
Defective repair
A "repair" for the rename that adds email_address as NOT NULL. v1 never writes it.
Unsafe
Expand/contract repair
Keeps email, adds email_address, syncs both with a trigger. The destructive step is deferred.
Safe
Type tightened to enum
orders.status becomes an enum without "shipped", a value v1 still writes.
Unsafe
New CHECK constraint
Totals must now be positive. v1 still creates fully discounted orders.
Unsafe
Table rename
orders is renamed to purchase_orders for v2.
Unsafe