Quick Start

Analyze your first migration in under a minute, either with a local install or directly through npx.

Analyze a File

bash
# Without installing first
npx @flvmnt/pgfence analyze migrations/add-email-verified.sql

# Or after installing locally / globally
pgfence analyze migrations/add-email-verified.sql

Example Output

bash
migrations/add-email-verified.sql  [HIGH]
  Lock: ACCESS EXCLUSIVE | Blocks: reads+writes+DDL | Risk: HIGH | Rule: add-column-not-null-no-default

┌────┬──────────────────────────────────────────────┬────────────────────┬────────────────┬────────────┬──────────────────────────────────────────────┐
│ #  │ Statement                                    │ Lock Mode          │ Blocks         │ Risk       │ Message                                      │
├────┼──────────────────────────────────────────────┼────────────────────┼────────────────┼────────────┼──────────────────────────────────────────────┤
│ 1  │ ALTER TABLE users ADD COLUMN email_verified  │ ACCESS EXCLUSIVE   │ reads, writes, │ HIGH       │ ADD COLUMN "email_verified" with NOT NULL    │
│    │ BOOLEAN NOT NULL                             │                    │ DDL            │            │ but no DEFAULT...                            │
└────┴──────────────────────────────────────────────┴────────────────────┴────────────────┴────────────┴──────────────────────────────────────────────┘

  Policy Violations:
  ERROR Missing SET lock_timeout
    → Add SET lock_timeout = '2s'; at the start of the migration

  Safe Rewrite Recipes:

  add-column-not-null-no-default: Add nullable column, backfill, then add NOT NULL constraint
    ALTER TABLE users ADD COLUMN IF NOT EXISTS email_verified boolean;
    -- Backfill out-of-band in batches (repeat until 0 rows updated)...
    ALTER TABLE users ADD CONSTRAINT chk_nn CHECK (email_verified IS NOT NULL) NOT VALID;
    ALTER TABLE users VALIDATE CONSTRAINT chk_nn;
    ALTER TABLE users ALTER COLUMN email_verified SET NOT NULL;
    ALTER TABLE users DROP CONSTRAINT chk_nn;

=== Coverage ===
Postgres ruleset: PG14+ (configurable)
Analyzed: 1 statements  |  Unanalyzable: 0  |  Coverage: 100%

Analyze ORM Migrations

bash
# TypeORM
pgfence analyze --format typeorm src/migrations/*.ts

# Prisma
pgfence analyze --format prisma prisma/migrations/**/migration.sql

# Knex
pgfence analyze --format knex migrations/*.ts

# Kysely
pgfence analyze --format kysely migrations/*.ts

# Drizzle
pgfence analyze --format drizzle drizzle/*.sql

# Sequelize
pgfence analyze --format sequelize src/migrations/*.js

# Auto-detect format
pgfence analyze migrations/*

Apply Scoped Fixes

--fix only edits raw SQL files and only applies an explicit allowlist of mechanical changes: concurrent index syntax and missing timeout settings. It reports everything else without guessing.

bash
pgfence analyze --fix migrations/*.sql

Add --split to scaffold sibling migrations for supported ADD COLUMN NOT NULL, foreign key, and unique constraint recipes. The original migration is left unchanged, and generated backfill templates remain commented out until you supply a value and schedule them out of band.

bash
pgfence analyze --fix --split migrations/*.sql

CI Integration

yaml
- name: Check migration safety
  run: npx @flvmnt/pgfence analyze --ci --max-risk medium migrations/*.sql

If you want PR comments, SARIF uploads, or GitLab Code Quality artifacts, see CI/CD Integration.