Configuration

pgfence reads configuration from .pgfence.toml or .pgfence.json in the current working directory. CLI flags override the file when both are present.

Config File

pgfence does not walk ancestor directories looking for config. It reads the config file from the directory you run it in.

toml
# .pgfence.toml
format = "auto"
output = "cli"
min-pg-version = 14
max-risk = "high"
require-lock-timeout = true
require-statement-timeout = true
max-lock-timeout = 5000
max-statement-timeout = 600000
disable-rules = ["rename-column"]
plugins = ["./rules/team-rules.mjs"]

The same config can be expressed in JSON:

json
{
  "format": "auto",
  "output": "cli",
  "min-pg-version": 14,
  "max-risk": "high",
  "require-lock-timeout": true,
  "require-statement-timeout": true,
  "max-lock-timeout": 5000,
  "max-statement-timeout": 600000,
  "disable-rules": ["rename-column"],
  "plugins": ["./rules/team-rules.mjs"]
}

Options

OptionDefaultDescription
formatautoMigration format: sql, typeorm, prisma, knex, drizzle, sequelize, or auto
outputcliReporter output: cli, json, github, sarif, or gitlab
db-urlDatabase URL for size-aware scoring
stats-filePath to a JSON stats snapshot as an alternative to db-url
min-pg-version14Minimum PostgreSQL version to assume for version-sensitive checks
max-riskhighRisk threshold for --ci
require-lock-timeouttrueRequire SET lock_timeout in every migration
require-statement-timeouttrueRequire SET statement_timeout in every migration
max-lock-timeoutWarn when lock_timeout exceeds this many milliseconds
max-statement-timeoutWarn when statement_timeout exceeds this many milliseconds
disable-rulesSuppress specific rule IDs
enable-rulesWhitelist only these rule IDs
snapshotSchema snapshot JSON for definitive type-change analysis
pluginsPlugin file paths, resolved from the current working directory

PostgreSQL Version

pgfence is tested against PostgreSQL 14 through 17. The default minimum is PG 14. Set --min-pg-version or the config-file equivalent to override if needed:

bash
pgfence analyze --min-pg-version 12 migrations/*.sql

Version-sensitive behavior:

PatternPG 11+PG 12+PG 14+
ADD COLUMN ... DEFAULT <constant>Metadata-only (LOW)Metadata-only (LOW)Metadata-only (LOW)
ALTER TYPE ... ADD VALUEACCESS EXCLUSIVE (MEDIUM)EXCLUSIVE, instant (LOW)EXCLUSIVE, instant (LOW)
RENAME COLUMNACCESS EXCLUSIVEACCESS EXCLUSIVEInstant (LOW)
DETACH PARTITION CONCURRENTLYNot availableNot availableSHARE UPDATE EXCLUSIVE (LOW)
REINDEX CONCURRENTLYNot availableAvailableAvailable

Inline Ignore

Add an inline comment immediately before a statement to suppress checks for it. The directive applies only to the single statement that follows.

Suppress all checks

sql
-- pgfence-ignore
DROP TABLE old_sessions;

Use this to explicitly acknowledge a statement that pgfence cannot fully analyze, such as dynamic SQL, or when you have reviewed the risk and accepted it.

Suppress specific rule

sql
-- pgfence-ignore: drop-table
DROP TABLE old_logs;

-- pgfence-ignore: add-column-not-null-no-default
ALTER TABLE audit_log ADD COLUMN meta JSONB NOT NULL DEFAULT '{}';

Suppress multiple rules

sql
-- pgfence-ignore: drop-table, prefer-robust-drop-table
DROP TABLE old_queue;

Syntax reference

SyntaxEffect
-- pgfence-ignoreSuppress all checks for the next statement
-- pgfence-ignore: <ruleId>Suppress one specific rule
-- pgfence-ignore: <ruleId>, <ruleId>Suppress multiple rules (comma-separated)
-- pgfence: ignore <ruleId>Legacy syntax, still supported
Use --output json to see the ruleId for any check you want to suppress.