Drizzle Kit · PostgreSQL 13+ · GitHub Actions

Test Drizzle migrations against production before you merge

drizzle-kit generate diffs your schema against its last snapshot, not against production. DbProof runs drizzle-kit migrate on a copy of production's schema, with its row statistics, on every pull request, and says what would fail or lock in production.

How it works with Drizzle Kit

Your own drizzle-kit migrate, against production's shape

Connect a repository and DbProof finds the folder with meta/_journal.json, the nearest package.json and your package manager, and opens a pull request with the workflow.

Restore production's shape

The check starts a throwaway Postgres on production's major version in your runner and restores the latest snapshot of production's schema and migration history.

Apply one migration at a time

Drizzle Kit has no target option, so DbProof cuts the journal after each migration in turn and runs drizzle-kit migrate, then puts the journal back as it was.

Weigh it against production

DbProof compares the result with production's statistics and reports on the pull request as a check and a comment, with the file, the line and a suggested fix.

The check sets DATABASE_URL to its throwaway database, so the step that runs it is your own command:

- uses: dbproof/check-action@v1
  with:
    project: your-org/your-api
    migrations-dir: drizzle
    # The check sets DATABASE_URL to its throwaway database.
    migrate-command: npx drizzle-kit migrate
Findings

What the check reports

Each finding names the migration file and line, says what production would do, and suggests a fix. Errors fail the check; warnings don’t.

error

A .notNull() over nulls

The generated SET NOT NULL meets nulls production's statistics show, and fails mid-deploy.

error

Migration fails to apply

A hotfix already added the column in production. The migration passes in CI on an empty database and fails on deploy.

warning

An index that blocks writes

Drizzle Kit runs migrations in a transaction, where Postgres can't build an index concurrently. DbProof flags the lock on large tables and says how to build it outside drizzle-kit migrate.

warning

A type change that rewrites a table

integer to bigint rewrites every row while holding the table's lock. DbProof flags it on tables over 1M rows.

warning

A reference without an index

.references() creates the foreign key but no index on it, so every delete from the parent scans the child table.

warning

A dropped column

The code still deployed may read it, and breaks the moment the migration runs.

error

An applied migration edited

Someone changed a migration production already ran, so the repository no longer matches production's history.

drift

Production changed outside migrations

DbProof opens a pull request with the migration and its journal entry, and reminds you to add the change to your Drizzle schema and regenerate.

What leaves production

Structure and statistics, never rows

A capture step in your deploy job reads production with the connection string your migrations already use, and uploads a snapshot.

What capture reads

  • The catalog: tables, columns, indexes, constraints, views and functions
  • Planner estimates: row counts, and each column's share of nulls, distinct values and width
  • drizzle.__drizzle_migrations: each applied migration's hash and timestamp

What it never reads

  • Rows from any of your tables
  • Sample values: no most-common values, no histograms
  • Your connection string: it stays in your GitHub secrets
FAQ

Drizzle questions

Does it work with drizzle-kit push?

No. DbProof tests the migrations drizzle-kit generate writes, and push changes the database without writing any.

My drizzle.config.ts reads a variable other than DATABASE_URL.

Set that variable from $DBPROOF_CHECK_DSN in the workflow's migrate-command, e.g. PG_URL="$DBPROOF_CHECK_DSN" npx drizzle-kit migrate.

Monorepos, pnpm or Yarn?

DbProof uses the package.json nearest the migrations folder, and installs with npm, pnpm or Yarn depending on the lockfile it finds.

Does DbProof connect to my database?

No. Capture runs in your deploy job, and checks run against a throwaway Postgres in your runner. DbProof only receives the snapshot.

Find out what your next Drizzle migration does to production

Connect a repository in a few minutes. Free during the beta.