Column rename
✕
Unsafe
The previous application version reproducibly fails against the proposed schema, and the failure is linked to a specific schema change.
v2 renames customers.email to email_address. v2 is fine; v1, still serving traffic during the rollout, is not.
Recorded example : genuine engine output generated Sat, 24 Oct 2026 18:29:55 GMT from the committed fixture. Run it again live below.
Baseline schema
Proposed schema
Previous versionshop-v1
2/2 test files pass no database errors
0/2 test files pass SQLSTATE 42703, identical in all 2 runs
Current versionB-breaking-rename
Not needed: ordinary CI covers this
1/1 test files pass no database errors
The outlined cell is the compatibility question. The verdict comes only from it, compared against the cell to its left.
Why test/customers.test.js: SQLSTATE 42703 (undefined_column) linked to column_removed:customers.email by R1 undefined_column ↔ removed/renamed column. test/orders.test.js: SQLSTATE 42703 (undefined_column) linked to column_removed:customers.email by R1 undefined_column ↔ removed/renamed column.
Next step Make the migration backward compatible (expand/contract: keep the old shape until the old version is retired), then re-run the gate.
Run this scenario live Starts a throwaway PostgreSQL and runs the full experiment, usually in under 15 seconds.
Evidence Regression test/customers.test.js
Observed test/customers.test.js passes on the baseline schema and fails in all 2 candidate runs.
Database error SQLSTATE 42703 undefined_column — column "email" of relation "customers" does not existINSERT INTO customers (name, email) VALUES ($1, $2) RETURNING id
Interpretation The statement references column "email", which the proposed schema no longer has on customers.
Rule R1 undefined_column ↔ removed/renamed column (strong correlation)
Linked change column_removed:customers.email
Regression test/orders.test.js
Observed test/orders.test.js passes on the baseline schema and fails in all 2 candidate runs.
Database error SQLSTATE 42703 undefined_column — column "email" of relation "customers" does not existINSERT INTO customers (name, email) VALUES ($1, $2) RETURNING id
Interpretation The statement references column "email", which the proposed schema no longer has on customers.
Rule R1 undefined_column ↔ removed/renamed column (strong correlation)
Linked change column_removed:customers.email
Schema changes 3 of 3 risk-bearing schema change(s) were exercised by the old application's tests in the control run.
Change Risk to old statements Exercised by previous version Column customers.email (text) removedPossibly renamed to "email_address" (same type; heuristic). breaking Yes, 3 statements in test/customers.test.js, test/orders.test.js Column customers.email_address added (text NOT NULL); possibly a rename of "email"NOT NULL without a default: inserts from the old application will omit it. breaking Yes, 2 statements in test/customers.test.js, test/orders.test.js Constraint customers_email_key on customers changed: UNIQUE (email) → UNIQUE (email_address) breaking Yes, 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 blocks the pipeline (exit 1)
Run Migrations Test files Database errors Statements logged control (old app × baseline schema) 1/1 2/2 pass 0 7 candidate #1 (old app × proposed schema) 2/2 0/2 pass 2 (42703) 0 candidate #2 (old app × proposed schema) 2/2 0/2 pass 2 (42703) 0 current app × proposed schema (context) 2/2 1/1 pass 0 2
Download this report: JSON Markdown JUnit 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.