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(), Knexraw(), SequelizequeryInterface.sequelize.query(), Prismamigration.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_locksandpg_classdeltas, 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_assuredblocks,safe_by_defaultmode, andstart_afterfor 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:migratelocally, in the ActiveRecord idiom they already speak. - pgfence as the SQL-layer CI gate. Catches anything that slipped through (raw
executeblocks, 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.