Comparison

strong_migrations vs pgfence

An honest comparison of the original Rails migration safety gem and a TypeScript multi-ORM static analyzer. Strong Rails coverage on one side, broader SQL surface on the other.

What strong_migrations is

strong_migrations is the original Postgres migration safety gem. Created by Andrew Kane, it has shaped how a generation of teams reason about safe DDL. Latest release is v2.8.0 (2026-05-14), shipping ~21 checks for Rails / ActiveRecord with growing MySQL and MariaDB coverage.

It runs inside Rails. When rails db:migrate executes, strong_migrations intercepts ActiveRecord DSL calls and raises a Ruby exception with a long, hand-crafted error message that doubles as documentation: it explains the lock, why it is dangerous, and the exact 3-step safe rewrite to apply instead. That error-message-as-docs pattern remains best-in-class. Its foreign-key-without-index detection has been a benchmark for the category since 2018.

Feature comparison

Feature strong_migrations pgfence
Language Ruby TypeScript (Node.js native)
Analysis approach Runtime interception of ActiveRecord DSL Static SQL analysis (pre-merge)
ORM coverage Rails / ActiveRecord only TypeORM, Prisma, Knex, Sequelize, Drizzle, raw SQL
Multi-engine Postgres, MySQL, MariaDB (partial) Postgres only
Rule count ~21 checks 36+ rules, growing rule catalog
Lock-mode reporting Implicit in error messages Explicit per statement (8 PG lock modes)
FK-without-index detection Yes (ships today, gold standard) Roadmap (v0.7)
Safe rewrite recipes Yes (baked into error messages) Yes (step-by-step recipes in output, RULES.md)
Output / behaviour Raises in dev, blocks db:migrate Terminal, JSON, GitHub PR comment, SARIF
CI integration Community gem-runner Actions First-party GitHub Action
Editor / LSP None VS Code extension (diagnostics, hover, quick fixes)
Trace mode (real PG locks) No Yes (Docker-based)
DB-size-aware risk scoring No Yes (stats snapshot)
Policy checks (lock_timeout, etc.) lock_timeout, statement_timeout, and PG17 transaction_timeout Yes (lock_timeout, statement_timeout, idle_in_tx, tx policy)
Coverage line No Yes (every report)
License MIT MIT

Where pgfence is honestly stronger

  • Language-agnostic SQL. pgfence reads the SQL itself, so it catches dangerous statements written through TypeORM queryRunner.query(), Knex raw(), Sequelize queryInterface.sequelize.query(), Prisma migration.sql, Drizzle generated SQL, and plain .sql files. strong_migrations only sees ActiveRecord DSL calls.
  • Five ORM extractors versus one. If your stack is not Rails, strong_migrations is not an option.
  • LSP / editor integration. Lock-mode hover cards, diagnostics, and quick fixes inside VS Code. strong_migrations has no editor surface.
  • Trace mode. pgfence can spin a disposable Postgres in Docker, run the migration, observe pg_locks and pg_class deltas, and report what actually happened. strong_migrations relies on pattern recognition.
  • RULES.md: a curated, in-editor-assistant rule catalog that machine-readable agents and humans can both consume.
  • Larger lock-mode surface: CLUSTER, REPLICA IDENTITY FULL, RLS toggles, ATTACH PARTITION quirks, REFRESH MATVIEW CONCURRENTLY, ALTER TYPE ADD VALUE: all explicit in pgfence; not covered by strong_migrations.

Where strong_migrations is honestly stronger

  • Native Rails integration is unmatched. safety_assured blocks, safe_by_default mode, and start_after for legacy migrations exist nowhere else.
  • FK-without-index detection ships today. pgfence's equivalent is in the v0.7 roadmap.
  • MySQL and MariaDB coverage: algorithm: :copy, shared/exclusive locking, callable defaults. pgfence is Postgres-only.
  • Error-message-as-documentation. Each strong_migrations error reads like a mini blog post. It is the canonical reference even teams that do not use Rails quote in code review.
  • Eight years of Ruby community trust. Battle-tested at large Rails shops.

When to choose strong_migrations

  • Pure Rails / ActiveRecord shop.
  • MySQL or MariaDB is your primary engine.
  • You want dev-time interception inside db:migrate, not a separate analyzer running in CI.
  • You value the error-message-as-documentation pattern as primary developer education.

Run both: defense in depth

strong_migrations and pgfence are not strictly competitors. The strongest setup for a Rails shop running anything ambitious is to run both:

  • strong_migrations as the Rails dev-time gate. Catches issues the moment a developer runs db:migrate locally, in the ActiveRecord idiom they already speak.
  • pgfence as the SQL-layer CI gate. Catches anything that slipped through (raw execute blocks, CLUSTER, REPLICA IDENTITY FULL, RLS toggles, partition attaches) and gives explicit lock modes plus a coverage line so the team knows what was and was not analyzed.

For Node.js teams using Knex, Prisma, TypeORM, Sequelize, or Drizzle, strong_migrations is not on the table. pgfence is built for that gap.

See also

  • Squawk vs pgfence: the Rust SQL linter with a growing IDE surface.
  • Eugene vs pgfence: the Rust trace-oriented tool.
  • pgrubic: a newer Python-based Postgres linter with a large rule surface, worth watching.
  • Atlas: schema-as-code / migration orchestration, a different category but adjacent.