Configuration

March 3, 2026 · View on GitHub

pg-safe-migrate can be configured via:

  1. CLI flags (highest priority)
  2. Config file (pgsm.config.json or .pgsmrc.json)
  3. Environment variables
  4. Defaults (lowest priority)

Config File

Create pgsm.config.json in your project root:

{
  "databaseUrl": "${DATABASE_URL}",
  "migrationsDir": "./migrations",
  "schema": "public",
  "tableName": "_pg_safe_migrate",
  "transactionPolicy": "auto",
  "requireDown": false,
  "allowRules": [],
  "statementTimeout": "30s",
  "lockTimeout": "10s"
}

Options Reference

OptionCLI FlagEnv VarDefaultDescription
databaseUrl-d, --databaseDATABASE_URLPostgreSQL connection string
migrationsDir--dirPGSM_MIGRATIONS_DIR./migrationsPath to migration files
schema--schemapublicSchema for the history table
tableName--table_pg_safe_migrateHistory table name
transactionPolicy--transactionautoTransaction wrapping policy
lockId--lock-id(derived)Advisory lock ID
requireDown--require-downfalseRequire down migrations
allowRules--allow-unsafe[]Globally allowed lint rules
statementTimeout(none)SQL statement_timeout
lockTimeout(none)SQL lock_timeout

Transaction Policy

PolicyBehavior
autoAuto-detect: use transactions unless migration contains CONCURRENTLY, VACUUM, etc.
alwaysAlways wrap in transaction. Fails if non-transactional statements detected.
neverNever wrap in transaction. Statements execute sequentially.

Recommendation: Use auto (default). It handles most cases correctly.

History Table

The history table stores applied migration records:

ColumnTypeDescription
idTEXT PRIMARY KEYMigration filename (sans extension)
checksumTEXT NOT NULLSHA-256 of file content
applied_atTIMESTAMPTZWhen it was applied
execution_msINTEGERHow long it took
directionTEXTup (or down for rollbacks)
tool_versionTEXTVersion of pg-safe-migrate used
notesJSONB NULLOptional metadata

Programmatic Usage

import { createMigrator } from "pg-safe-migrate-core";

const migrator = createMigrator({
  databaseUrl: process.env.DATABASE_URL,
  migrationsDir: "./migrations",
});

// Check for issues
const { ok, issues, drift } = await migrator.check();

// Apply pending
const steps = await migrator.run();

// Get status
const status = await migrator.status();

Tips

  • Use environment variable interpolation (${DATABASE_URL}) in config files to avoid hardcoding credentials.
  • Set requireDown: true in team environments to enforce reversible migrations.