🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

migrationpilot

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

migrationpilot

Know exactly what your PostgreSQL migration will do to production — before you merge.

Source
npmnpm
Version
1.1.0
Version published
Weekly downloads
219
-47.86%
Maintainers
1
Weekly downloads
 
Created
Source

MigrationPilot

npm version CI License: MIT

Know exactly what your PostgreSQL migration will do to production — before you merge.

MigrationPilot is a static analysis tool for PostgreSQL schema migrations. It parses your SQL with the actual PostgreSQL parser (libpg-query), classifies every lock acquired, flags dangerous patterns with 48 safety rules, scores overall risk, and suggests safe alternatives — all without touching your database. Works as a CLI, a GitHub Action, and a Node.js library.

Quick Start

CLI

npm install -g migrationpilot

# Analyze a migration file
migrationpilot analyze migrations/001_add_index.sql

# Check all migrations in a directory
migrationpilot check migrations/ --pattern "*.sql"

# Auto-fix what's fixable
migrationpilot analyze migrations/001.sql --fix

GitHub Action

# .github/workflows/migration-check.yml
name: Migration Safety Check
on: [pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: mickelsamuel/migrationpilot@v1
        with:
          migration-path: "migrations/*.sql"
          fail-on: critical

Pipe from any framework

# Django
python manage.py sqlmigrate myapp 0042 | migrationpilot analyze --stdin

# Prisma
npx prisma migrate diff --from-schema-datamodel prisma/schema.prisma --to-migrations migrations --script | migrationpilot analyze --stdin

# Knex
knex migrate:up --knexfile knexfile.js 2>&1 | migrationpilot analyze --stdin

CLI Commands

CommandDescription
analyze <file>Analyze a single SQL migration file
check <dir>Check all migration files in a directory
plan <file>Show execution plan with timeline visualization
initGenerate a .migrationpilotrc.yml config file
detectAuto-detect migration framework (14 supported)
watch <dir>Watch migration files and re-analyze on change
hookInstall/uninstall git pre-commit hook
list-rulesList all 48 safety rules with metadata

CLI Options

OptionCommandsDescriptionDefault
--pg-version <n>analyze, checkTarget PostgreSQL version (9-20)17
--format <fmt>analyze, checkOutput: text, json, sarif, markdowntext
--fail-on <level>analyze, checkExit code threshold: critical, warning, nevercritical
--fixanalyzeAuto-fix violations in-place (6 rules)
--dry-runanalyzePreview auto-fix changes without writing
--quietanalyze, checkOne-line-per-violation (gcc-style) output
--verboseanalyzePer-statement PASS/FAIL for all rules
--stdinanalyzeRead SQL from stdin instead of file
--exclude <rules>analyze, checkComma-separated rule IDs to skip
--database-url <url>analyze, checkPostgreSQL connection for production context (Pro)
--license-key <key>analyze, checkLicense key for Pro features
--pattern <glob>checkFile pattern for directory scanning*.sql
--no-colorallDisable colored output
--jsonlist-rulesOutput rules as JSON array

Environment variables: MIGRATIONPILOT_LICENSE_KEY, NO_COLOR, TERM=dumb.

All 48 Rules

Lock Safety (Critical)

RuleNameAuto-fixWhat it catches
MP001require-concurrent-indexYesCREATE INDEX without CONCURRENTLY blocks writes
MP002require-check-not-nullSET NOT NULL without CHECK pattern scans full table
MP003volatile-default-rewriteADD COLUMN DEFAULT now() rewrites table on PG < 11
MP004require-lock-timeoutYesDDL without SET lock_timeout blocks queue
MP005require-not-valid-fkADD CONSTRAINT FK without NOT VALID scans full table
MP006no-vacuum-fullVACUUM FULL rewrites table under ACCESS EXCLUSIVE
MP007no-column-type-changeALTER COLUMN TYPE rewrites table
MP008no-multi-ddl-transactionMultiple DDL in one transaction compound lock time
MP025ban-concurrent-in-transactionCONCURRENTLY ops inside a transaction = runtime ERROR
MP026ban-drop-tableDROP TABLE permanently removes table and data
MP027disallowed-unique-constraintUNIQUE constraint without USING INDEX scans full table
MP030require-not-valid-checkYesCHECK constraint without NOT VALID scans full table
MP031ban-exclusion-constraintEXCLUSION constraint builds GiST index under ACCESS EXCLUSIVE
MP032ban-clusterCLUSTER rewrites table under ACCESS EXCLUSIVE
MP034ban-drop-databaseDROP DATABASE in a migration file
MP035ban-drop-schemaDROP SCHEMA permanently removes schema + objects
MP036ban-truncate-cascadeTRUNCATE CASCADE silently truncates FK-referencing tables
MP046require-concurrent-detach-partitionDETACH PARTITION without CONCURRENTLY (PG 14+)
MP047ban-set-logged-unloggedSET LOGGED/UNLOGGED rewrites entire table

Warnings

RuleNameAuto-fixWhat it catches
MP009require-drop-index-concurrentlyYesDROP INDEX without CONCURRENTLY
MP010no-rename-columnRENAME COLUMN breaks app queries
MP011unbatched-backfillUPDATE without WHERE (full table scan)
MP012no-enum-add-in-transactionALTER TYPE ADD VALUE inside transaction
MP015no-add-column-serialSERIAL creates implicit sequence (use IDENTITY)
MP016require-fk-indexFK columns without index = slow cascading deletes
MP017no-drop-columnDROP COLUMN under ACCESS EXCLUSIVE
MP018no-force-set-not-nullSET NOT NULL without CHECK pre-validation
MP020require-statement-timeoutYesLong-running DDL without statement_timeout
MP021require-concurrent-reindexREINDEX without CONCURRENTLY (PG 12+)
MP022no-drop-cascadeDROP CASCADE silently drops dependents
MP023require-if-not-existsCREATE TABLE/INDEX without IF NOT EXISTS
MP024no-enum-value-removalDROP TYPE destroys enum + dependent columns
MP028no-rename-tableRENAME TABLE breaks queries, views, FKs
MP029ban-drop-not-nullDROP NOT NULL may break app assumptions
MP033require-concurrent-refresh-matviewYesREFRESH MATERIALIZED VIEW without CONCURRENTLY
MP037prefer-text-over-varcharVARCHAR(n) has no benefit over TEXT in PostgreSQL
MP038prefer-bigint-over-intINT PK/FK columns can overflow (use BIGINT)
MP039prefer-identity-over-serialSERIAL quirks — use GENERATED ALWAYS AS IDENTITY
MP040prefer-timestamptzTIMESTAMP without timezone causes timezone bugs
MP041ban-char-fieldCHAR(n) wastes space, causes comparison bugs
MP042require-index-nameUnnamed indexes are hard to reference
MP043ban-domain-constraintDomain constraints validate against ALL using columns
MP044no-data-loss-type-narrowingNarrowing column type (e.g., BIGINT → INT) can lose data
MP045require-primary-keyTables without PK break replication
MP048ban-alter-default-volatileVolatile SET DEFAULT on existing column is misleading

Production Context (Pro)

RuleNameWhat it catches
MP013high-traffic-table-ddlDDL on tables with 10K+ queries
MP014large-table-ddlLong-held locks on tables with 1M+ rows
MP019no-exclusive-lock-high-connectionsACCESS EXCLUSIVE with many active connections

Auto-fix: 6 rules can be automatically fixed with --fix: MP001, MP004, MP009, MP020, MP030, MP033.

Features

Auto-fix

migrationpilot analyze migration.sql --fix         # Fix in-place
migrationpilot analyze migration.sql --fix --dry-run  # Preview changes

Automatically fixes: missing CONCURRENTLY, lock_timeout, statement_timeout, NOT VALID on CHECK constraints, CONCURRENTLY on materialized view refresh.

Framework Detection

migrationpilot detect
# → Detected: Prisma (prisma/migrations/)

Detects 14 frameworks: Flyway, Liquibase, Alembic, Django, Knex, Prisma, TypeORM, Drizzle, Sequelize, goose, dbmate, Sqitch, Rails, Ecto.

Watch Mode

migrationpilot watch migrations/ --pattern "*.sql"

Re-analyzes on file changes with intelligent debouncing.

Pre-commit Hook

migrationpilot hook install   # Installs git hook (supports Husky)
migrationpilot hook uninstall

Execution Plan

migrationpilot plan migration.sql

Visual timeline showing lock type, duration estimate, blocking impact, and transaction boundaries for each statement.

Config File

# .migrationpilotrc.yml
extends: "migrationpilot:strict"   # Built-in preset
pgVersion: 16
failOn: warning
rules:
  MP037: false                     # Disable a rule
  MP004:
    severity: warning              # Downgrade severity
  MP013:
    threshold: 5000                # Custom threshold
ignore:
  - "migrations/seed_*.sql"

Three built-in presets: migrationpilot:recommended (default), migrationpilot:strict (all rules at critical, fail on warning), migrationpilot:ci.

Inline Disable

-- migrationpilot-disable MP001
CREATE INDEX idx_users_email ON users (email);

-- migrationpilot-disable-next-line MP004
ALTER TABLE users ADD COLUMN bio TEXT;

Severity Overrides

Override any rule's severity via config:

rules:
  MP009:
    severity: critical   # Upgrade from warning to critical
  MP007:
    severity: warning    # Downgrade from critical to warning

PG Version Awareness

Rules adapt their advice based on --pg-version:

  • PG 10+: Recommends GENERATED ALWAYS AS IDENTITY over SERIAL
  • PG 11+: Non-volatile ADD COLUMN DEFAULT is safe (no rewrite)
  • PG 12+: REINDEX CONCURRENTLY available
  • PG 14+: DETACH PARTITION CONCURRENTLY available
  • PG 18+: SET NOT NULL NOT VALID + VALIDATE NOT NULL pattern

Output Formats

FormatFlagUse case
Text--format text (default)Terminal with colors, tables, risk bars
JSON--format jsonScripting, CI pipelines (versioned $schema)
SARIF--format sarifGitHub Code Scanning, VS Code, IntelliJ
Markdown--format markdownDocs, wikis, Notion
Quiet--quietOne-line-per-violation (gcc-style)
Verbose--verbosePer-statement PASS/FAIL for all 48 rules

JSON Schema

JSON output includes a $schema URL and version field for reliable parsing:

{
  "$schema": "https://migrationpilot.dev/schemas/report-v1.json",
  "version": "1.1.0",
  "file": "migrations/001.sql",
  "riskLevel": "RED",
  "riskScore": 80,
  "violations": [...]
}

SARIF

# CLI
migrationpilot analyze migration.sql --format sarif > results.sarif

# GitHub Action (auto-generated)
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: ${{ steps.migration-check.outputs.sarif-file }}

Production Context (Pro)

With a Pro license + --database-url, MigrationPilot connects read-only to query system catalogs:

Data SourceWhat it provides
pg_classTable row counts, total size, index count
pg_stat_statementsAffected queries by call frequency
pg_stat_activityActive connections on target tables

This data feeds into risk scoring (table size 0-30 pts, query frequency 0-30 pts) and unlocks rules MP013, MP014, MP019.

Safety: Only reads pg_stat_* and pg_class. Never reads user data. Never runs DDL. Single read-only connection with timeouts.

Risk Scoring

FactorWeightFreePro
Lock Severity0-40YesYes
Table Size0-30Yes
Query Frequency0-30Yes
LevelScoreMeaning
GREEN0-24Safe to deploy
YELLOW25-49Review recommended
RED50-100Dangerous — use safe alternative

GitHub Action

Inputs

InputDescriptionRequiredDefault
migration-pathGlob pattern for SQL filesYes
github-tokenGitHub token for PR commentsNo${{ github.token }}
license-keyPro license keyNo
database-urlPostgreSQL connection (Pro)No
pg-versionTarget PostgreSQL versionNo17
fail-onFail threshold: critical, warning, neverNocritical

Outputs

OutputDescription
risk-levelOverall: RED, YELLOW, or GREEN
violationsTotal violation count
sarif-filePath to SARIF file for Code Scanning upload

With Production Context + Code Scanning (Pro)

- uses: mickelsamuel/migrationpilot@v1
  id: migration-check
  with:
    migration-path: "migrations/*.sql"
    license-key: ${{ secrets.MIGRATIONPILOT_LICENSE_KEY }}
    database-url: ${{ secrets.DATABASE_URL }}
    fail-on: critical

- uses: github/codeql-action/upload-sarif@v3
  if: always()
  with:
    sarif_file: ${{ steps.migration-check.outputs.sarif-file }}

PostgreSQL Lock Reference

DDL OperationLock TypeBlocks ReadsBlocks WritesLong-held
CREATE INDEXSHARENoYesYes
CREATE INDEX CONCURRENTLYSHARE UPDATE EXCLUSIVENoNoNo
DROP INDEXACCESS EXCLUSIVEYesYesNo
DROP INDEX CONCURRENTLYSHARE UPDATE EXCLUSIVENoNoNo
ADD COLUMN (no default)ACCESS EXCLUSIVEYesYesNo
ADD COLUMN DEFAULT now()ACCESS EXCLUSIVEYesYesYes*
ALTER COLUMN TYPEACCESS EXCLUSIVEYesYesYes
SET NOT NULLACCESS EXCLUSIVEYesYesYes
ADD CONSTRAINT FKACCESS EXCLUSIVEYesYesYes
ADD CONSTRAINT FK NOT VALIDACCESS EXCLUSIVEYesYesNo
VALIDATE CONSTRAINTSHARE UPDATE EXCLUSIVENoNoNo
RENAME COLUMN/TABLEACCESS EXCLUSIVEYesYesNo
DROP TABLEACCESS EXCLUSIVEYesYesNo
TRUNCATEACCESS EXCLUSIVEYesYesNo
CLUSTERACCESS EXCLUSIVEYesYesYes
VACUUM FULLACCESS EXCLUSIVEYesYesYes
VACUUMSHARE UPDATE EXCLUSIVENoNoNo
REINDEXACCESS EXCLUSIVEYesYesYes
REINDEX CONCURRENTLYSHARE UPDATE EXCLUSIVENoNoNo
REFRESH MATERIALIZED VIEWACCESS EXCLUSIVEYesYesYes
REFRESH MATERIALIZED VIEW CONCURRENTLYSHARE UPDATE EXCLUSIVENoNoNo
SET LOGGED/UNLOGGEDACCESS EXCLUSIVEYesYesYes
DETACH PARTITIONACCESS EXCLUSIVEYesYesNo
DETACH PARTITION CONCURRENTLYSHARE UPDATE EXCLUSIVENoNoNo

* On PG < 11, volatile defaults cause full table rewrite. On PG 11+, evaluated per-row at read time.

Comparison

MigrationPilotSquawkAtlas
Total rules4831~15
Free rules45310 (paywalled since v0.38)
Auto-fix6 rules00
Output formats6 (text, JSON, SARIF, markdown, quiet, verbose)32
Framework detection14 frameworks00
Watch modeYesNoNo
Pre-commit hooksYesNoNo
Execution planYesNoNo
Config file + presets3 presets00
PG-version-awareFull (9-20)PartialPartial
Programmatic APINode.jsNoGo
GitHub ActionYesNoYes
SARIF for Code ScanningYesNoNo
Inline disable commentsYesNoNo
Open sourceMITApache 2.0Proprietary

Pricing

FeatureFreePro ($29/mo)Enterprise
45 safety rules (MP001-MP048 excl. 013/014/019)YesYesYes
All output formats (text, JSON, SARIF, markdown)YesYesYes
GitHub Action PR commentsYesYesYes
Auto-fix (6 rules)YesYesYes
Config file, presets, inline disableYesYesYes
Production context (table sizes, query frequency)YesYes
Production rules (MP013, MP014, MP019)YesYes
Enhanced risk scoringYesYes
Priority supportYesYes
Team license managementYes
SSO / SAML + audit logYes

Get a license key at migrationpilot.dev/pricing.

Architecture

src/
├── parser/        # DDL parsing with libpg-query WASM (actual PG parser)
├── locks/         # Lock type classification (pure lookup table)
├── rules/         # 48 safety rules (MP001-MP048), engine, registry, helpers
├── production/    # Production context queries (Pro: pg_stat_*, pg_class)
├── scoring/       # Risk scoring (RED/YELLOW/GREEN, 0-100)
├── generator/     # Safe migration SQL generation
├── output/        # CLI, JSON, SARIF, markdown, PR comment, execution plan
├── analysis/      # Shared pipeline, transaction boundaries, migration ordering
├── fixer/         # Auto-fix engine (6 rules)
├── frameworks/    # Migration framework detection (14 frameworks)
├── watch/         # File watcher with debounce
├── hooks/         # Git pre-commit hook installer
├── config/        # Config loader (.migrationpilotrc.yml, presets)
├── license/       # HMAC-SHA256 license key validation
├── billing/       # Stripe checkout + webhook + email delivery
├── action/        # GitHub Action entry point
├── index.ts       # Programmatic API (17 exports)
└── cli.ts         # CLI entry point (8 commands)

Programmatic API

import { analyzeSQL, allRules, parseMigration, classifyLock } from 'migrationpilot';

const result = analyzeSQL(sql, allRules, { pgVersion: 16 });
console.log(result.violations);
console.log(result.overallRisk);

Full TypeScript types included. See API documentation.

Development

pnpm install
pnpm test          # 550+ tests across 31 files
pnpm dev analyze path/to/migration.sql
pnpm build         # CLI 835KB, Action 1.2MB, API 219KB
pnpm lint
pnpm typecheck

Contributing

See CONTRIBUTING.md for development setup and guidelines.

Security

See SECURITY.md for our security policy.

License

MIT

Keywords

postgresql

FAQs

Package last updated on 17 Feb 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts