Comparison

Eugene vs pgfence

An honest comparison of two Postgres migration safety tools: Eugene (Rust, trace-oriented, single static binary) and pgfence (TypeScript, multi-ORM, with safe rewrite guidance and an LSP server).

What Eugene does well

Eugene is a focused Postgres migration safety tool written in Rust by Robin Kaaveland. It ships as a single static binary, is MIT-licensed, and the latest release is v0.8.3 (March 2026). Its signature feature is trace mode: Eugene runs your migration inside a transaction against a real PostgreSQL instance, observes the actual locks taken via pg_locks, then rolls back. That live verification eliminates a category of guesswork that purely static tools have to live with.

Its current rule catalog is 15 hints: E1 through E11 plus E15 (errors) and W12 through W14 (warnings). Eugene's lint mode is concise and well-documented, with one page per hint explaining the lock-level reasoning.

Feature comparison

Feature Eugene pgfence
Language Rust (single static binary) TypeScript (Node.js native)
License MIT MIT
Latest release v0.8.3 (2026-03) v0.6.0 (2026-05)
SQL parser libpg_query (Rust bindings) libpg_query (Node.js bindings)
Rule surface 15 hints (E1-E11, E15, W12-W14) 36+ rules across DDL + policy categories
Input: raw SQL Yes Yes
Input: TypeORM / Prisma / Knex / Sequelize / Drizzle No (raw SQL only) Yes (built-in ORM extractors)
Trace mode (live lock observation) Yes (single tx, BEGIN/observe/ROLLBACK) Yes (Docker-based; observer polling for CONCURRENTLY)
Trace: catalog inspection Yes (relfilenode diffs) Yes (pg_class, pg_constraint, pg_index diffs)
Trace: ORM migrations No Yes (after ORM extraction)
Lock mode reporting Yes Yes (per statement, static + trace)
Safe rewrite recipes Brief suggestions per hint Step-by-step safe rewrites per rule (RULES.md)
DB-size-aware risk scoring No Yes (stats snapshot or direct connection)
LSP server / editor integration No Yes (LSP server + VS Code extension)
GitHub Action No official action Yes (composite action)
Output formats Terminal, JSON, Markdown Terminal, JSON, GitHub PR comment, SARIF
Coverage line in reports No Yes (analyzed vs. unanalyzable statements)
Policy checks Some (lock_timeout via W14) Yes (lock_timeout, statement_timeout, tx policy, app_name)
Memory footprint Low (native binary) Node.js process

The trace-mode framing online is outdated

You will see older blog posts and threads claim that Eugene is the only Postgres migration tool with trace mode. That was true through 2025, but pgfence has shipped trace mode since v0.4. Both tools now diff catalog snapshots and report actually-acquired locks. The execution models differ: Eugene runs the migration in a single transaction (clean, but cannot observe CREATE INDEX CONCURRENTLY, which fails inside a tx), while pgfence spins up a disposable Docker Postgres and uses an observer connection to capture transient locks from CONCURRENTLY statements. If most of your dangerous patterns are concurrent index work, that distinction matters.

Where pgfence is honestly stronger

  • ORM coverage: pgfence ships extractors for TypeORM, Prisma, Knex, Sequelize, and Drizzle. Eugene only reads raw SQL.
  • Editor integration: pgfence has a first-party LSP server with diagnostics, hover, and supported quick fixes. Eugene has no LSP.
  • Safe rewrite recipes: pgfence attaches a per-rule rewrite recipe (expand-backfill-contract sequences) directly in the output. Eugene gives shorter hint descriptions.
  • Larger rule surface: 36+ pgfence rules vs. 15 Eugene hints, with explicit policy checks for missing timeouts and CONCURRENTLY-in-transaction.
  • RULES.md catalog shipped in the package, browsable by editors and in-editor coding assistants.
  • Outputs: SARIF for GitHub Code Scanning, GitHub PR comment markdown, JSON, terminal.

Where Eugene is honestly stronger

  • Single static binary: no Node.js, no node_modules, no version-pinned runtime. Easier to drop into a Rust shop or a minimal CI image.
  • Memory footprint: a native Rust binary uses far less RAM than a Node.js process. Matters in tight CI containers.
  • Simplicity of trace mode: Eugene's single-transaction trace is conceptually simpler than pgfence's disposable Docker container plus observer connection. If you do not run CONCURRENTLY patterns, you may not need pgfence's extra machinery.
  • Hint catalog readability: Eugene's docs page per hint is clear and short; very pleasant to grep through.

When to choose Eugene

  • You write raw SQL migrations only, no ORM in the pipeline
  • Your stack is Rust or Go, and you do not want a Node.js dependency in CI
  • You want static analysis plus simple live trace, and no CONCURRENTLY patterns
  • You prefer a single binary you can vendor or check into tools/
  • You actively dislike the JS package-management surface area

When to choose pgfence

  • Your team uses TypeORM, Prisma, Knex, Sequelize, or Drizzle
  • You want trace mode that handles CONCURRENTLY statements
  • You want step-by-step safe rewrite guidance in the output
  • You need table-size-aware risk scoring
  • You want a VS Code extension or any LSP-aware editor to surface diagnostics inline
  • You want SARIF output for GitHub Code Scanning annotations
  • Your stack is Node.js/TypeScript and a JS-native tool fits the toolchain

See also