Expand/contract repair

Safe
No supported incompatibility was detected under the conditions tested. This is not a universal safety guarantee.

Keeps email, adds email_address, syncs both with a trigger. The destructive step is deferred.

Recorded example: genuine engine output generated Sat, 24 Oct 2026 18:30:04 GMT from the committed fixture. Run it again live below.

Baseline schema
Proposed schema
Previous versionshop-v1
2/2 test files passno database errors
2/2 test files passno database errors, identical in all 2 runs
Current versionH-valid-repair
Not needed: ordinary CI covers this
1/1 test files passno database errors

The outlined cell is the compatibility question. The verdict comes only from it, compared against the cell to its left.

Next step

Proceed with normal review. Keep the old application's tests meaningful; SAFE only covers what they exercise.

Starts a throwaway PostgreSQL and runs the full experiment, usually in under 15 seconds.

Schema changes

2 of 2 risk-bearing schema change(s) were exercised by the old application's tests in the control run.

ChangeRisk to old statementsExercised by previous version
Column customers.email_address added (text)inertNot required
Index customers_email_address_key added on customersbreakingYes, 2 statements in test/customers.test.js, test/orders.test.js
Trigger customers_sync_email added on customersbehavioralYes, 2 statements in test/customers.test.js, test/orders.test.js

Runs

Proposed migration: 002_rename_email.sql · PostgreSQL 16.15 (Debian 16.15-1.pgdg12+2) · gate does not block (exit 0)

RunMigrationsTest filesDatabase errorsStatements logged
control (old app × baseline schema)1/12/2 pass07
candidate #1 (old app × proposed schema)2/22/2 pass07
candidate #2 (old app × proposed schema)2/22/2 pass07
current app × proposed schema (context)2/21/1 pass02

Download this report: JSONMarkdownJUnit XML

What this result does not cover
  • Performance / lock-time analysis (out of scope).
  • Skewcheck only observes code paths that the old application's tests execute; untested paths are reported as coverage gaps, not as safe.
  • Coverage is identifier-level: a statement "touches" a changed object when it names the table (and column, or uses *). It is not a SQL parser.
  • Correlation between an error and a schema change uses a fixed set of deterministic rules (R1–R6). Anything else is reported as ADVISORY, never UNSAFE.
  • Performance, locking and migration runtime on production-sized data are not evaluated.
  • Test files of one run share a database and run sequentially; ordering effects are identical across runs but are not isolated.
  • Data-only migration effects are detected only when a test asserts on the affected data.