Prisma now documents pgfence for pre-deploy migration checks

Prisma's deployment docs now show pgfence as a pre-deploy migration safety check before prisma migrate deploy. Here is what that check catches and why it belongs in CI.

Prisma’s deployment docs now include pgfence in the production migration path.

In the section on pre-deploy migration safety checks, Prisma shows pgfence running before prisma migrate deploy in GitHub Actions.

That is the right place for migration safety. The dangerous part of a migration is often not whether the SQL is valid. It is whether valid SQL takes a lock that blocks reads, writes, or both while production traffic is still arriving.

The gap between valid and safe

Prisma Migrate gives teams a clean workflow for schema changes:

npx prisma migrate deploy

That command applies pending migrations. It does not claim to be a lock-risk analyzer, and it should not need to become one.

Postgres DDL has its own operational rules. A migration can be syntactically correct, generated by the normal workflow, reviewed by a human, and still take an ACCESS EXCLUSIVE lock on a busy table.

For example:

ALTER TABLE users
  ADD COLUMN last_seen_at timestamptz NOT NULL DEFAULT now();

The application intent is simple: add a timestamp. The operational behavior is sharper: a volatile default can force a table rewrite under a lock that blocks reads and writes.

That is the gap pgfence is built for.

What pgfence adds before deploy

pgfence reads Prisma’s generated SQL migration files and reports the migration risk before the deploy step runs:

npx @flvmnt/pgfence analyze prisma/migrations/**/migration.sql

It maps each DDL statement to:

  • the Postgres lock mode it takes
  • what that lock blocks
  • a risk level
  • policy violations like missing lock_timeout
  • a safe rewrite recipe when there is a known safer rollout

For a risky add-column migration, the safe path is usually an expand and contract sequence:

ALTER TABLE users ADD COLUMN IF NOT EXISTS last_seen_at timestamptz;

-- Backfill out of band in batches.

ALTER TABLE users
  ADD CONSTRAINT users_last_seen_at_not_null
  CHECK (last_seen_at IS NOT NULL) NOT VALID;

ALTER TABLE users VALIDATE CONSTRAINT users_last_seen_at_not_null;
ALTER TABLE users ALTER COLUMN last_seen_at SET NOT NULL;

The migration is still yours. pgfence just makes the lock behavior explicit before it reaches production.

A small CI step with a high ceiling

The useful workflow is straightforward:

- name: Check migration safety
  run: npx @flvmnt/pgfence analyze prisma/migrations/**/migration.sql

- name: Deploy database migrations
  run: npx prisma migrate deploy

That gives reviewers a dedicated safety signal before the migration is applied.

It also keeps the boundary clean:

  • Prisma owns schema migration generation and deployment.
  • pgfence owns Postgres lock visibility, risk reporting, and safe rewrite guidance.
  • CI owns the decision about whether a risky change should block.

That division matters because migration safety is not one tool replacing another. It is a sequence of checks that catch different failure modes.

Why this mention matters

pgfence is intentionally narrow. It does not try to be a general database platform. It answers one production question:

What will this Postgres migration lock, and what should we run instead?

Seeing pgfence show up in Prisma’s deployment docs is a strong signal that this question belongs in the default conversation for teams shipping Prisma migrations to Postgres.

If your team already uses Prisma and Postgres, add the check before prisma migrate deploy and run it against your next migration. If pgfence misses a dangerous pattern or flags something safe, open an issue with the SQL. That feedback is exactly how the rule set gets sharper.

Start here:

← All posts