pg-flux

Getting started

vs alternatives

Honest comparison vs Atlas, sqlc, Prisma, Drizzle, goose, golang-migrate, pg-schema-diff.

You probably already use one of the tools below. This page is about deciding whether pg-flux replaces it, complements it, or isn't worth the switch.

We try to be honest. Where pg-flux loses, we say so.

#TL;DR matrix

Tool Replaces it? Or works alongside?
Atlas Mostly yes, for PG-only projects Atlas wins for multi-DB
sqlc No — sqlc generates queries, pg-flux generates schema types Use both: pg-flux for schema + types, sqlc for typed queries
Prisma If you want SQL-first, yes Prisma wins for ORM-style apps
Drizzle Different category; you can use Drizzle Studio + pg-flux Drizzle gives you ORM; pg-flux gives you types + safe migrations
goose / golang-migrate Yes, completely These are file-based migration runners
pg-schema-diff Yes, for the diff portion pg-flux is the broader product
raw SQL + checked-in migrations Yes This is the default people start with

#vs Atlas

Atlas is the closest direct competitor. Both are declarative-schema migration tools. Where they diverge:

Dimension Atlas pg-flux
Languages supported PG, MySQL, MariaDB, SQLite, SQL Server, ClickHouse, Redshift PostgreSQL only
Schema definition Atlas HCL DSL, or SQL, or both SQL only
Migration generation Yes Yes
Drift detection Yes (Atlas Cloud) Yes (CLI: drift, verify)
PG 18 coverage Lagging (Atlas tracks slowly) First-class (NULLS NOT DISTINCT, NOT ENFORCED, virtual generated, etc.)
Type generation No Go + TypeScript, with comment hints, branded IDs, zod schemas
Hosted control plane Atlas Cloud (paid) None (self-hosted only)
Hazard model Lint rules + manual blocks Built-in hazard classification with --allow-hazards
Round-trip dump Limited First-class, integration-test-enforced
Schema dump Yes Yes, round-trip clean

When to choose Atlas: you manage multiple DB engines (PG + MySQL), or you want the HCL DSL, or you're on Atlas Cloud already.

When to choose pg-flux: PG-only, you want SQL-as-source-of-truth, you want the codegen layer, you want PG 18 features today.

Use both? Not practically. They'd fight over baseline state.

#vs sqlc

sqlc generates type-safe query code from .sql files. Different problem space.

Dimension sqlc pg-flux
Schema migrations No Yes
Query-to-code generation Yes No
Type generation for tables Yes Yes
Type generation for query results Yes (its main feature) No
Multi-language Go + Kotlin + Python Go + TypeScript
Manages the DB No Yes

You should use both. pg-flux handles schema + migration + table-row types. sqlc generates the typed query layer on top.

Text
schema/users.sql ──► pg-flux ──► users table + User struct

queries/users.sql ──► sqlc ─────────────────────┘

                          └──► GetUserByID(ctx, id) (User, error)

The handoff is clean because both consume the same SQL schema files. pg-flux owns "how does the schema get there"; sqlc owns "how does the application call it with types".

#vs Prisma

Prisma is full-stack ORM territory. Schema in Prisma DSL, migrations auto-generated, JS/TS-only client.

Dimension Prisma pg-flux
Schema definition schema.prisma (own DSL) SQL
Migration generation Yes Yes
ORM client Yes (Prisma Client) No (you write SQL or use sqlc/raw)
Multi-database PG, MySQL, SQLite, SQL Server, MongoDB PG only
PG-specific features Lagging (no NULLS NOT DISTINCT, no partition syntax, etc.) First-class
Generated types TypeScript only TypeScript + Go
Runtime Required (Prisma Client engine) None (just SQL output)

When to choose Prisma: you want a turnkey ORM with auto-generated client, you're TS-only, you don't need PG-specific features.

When to choose pg-flux: SQL-first team, you want PG superpowers (RLS, partitioning, GIST, range types, etc.), you mix Go and TS.

Use both? Hard. You'd give up Prisma's auto-migrations to use pg-flux's, which removes most of Prisma's value.

#vs Drizzle

Drizzle is a TS-first ORM with a SQL-like query builder. Schema is defined in TS, migrations are SQL.

Dimension Drizzle pg-flux
Schema definition TypeScript files SQL files
Migration generation Drizzle Kit Yes
Drift detection Limited Yes
ORM Yes (drizzle-orm) No
Multi-database PG, MySQL, SQLite PG only

When to choose Drizzle: you want TS-as-source-of-truth, you want the ORM, you like the SQL-like query syntax.

When to choose pg-flux: you want SQL-as-source-of-truth (the actual SQL syntax, not a JS DSL), you mix Go + TS clients.

Use both? Possible: use pg-flux for the schema + migration + Go types, use Drizzle as the TS client against the same DB. But you'd be defining the schema twice, which defeats the point.

#vs goose / golang-migrate

These are imperative migration runners. You write 001_up.sql / 001_down.sql pairs. They apply them in order.

Dimension goose / golang-migrate pg-flux
Migration source Hand-written up/down pairs Generated from declarative SQL
Declarative schema No Yes
Drift detection No Yes
Hazard model No Yes
Codegen No Yes
Maturity Older, broader install base Newer, more focused

When to choose goose/golang-migrate: you genuinely want imperative migrations and don't trust generators. You have a tiny schema. You're maintaining a legacy codebase.

When to choose pg-flux: anything else.

Migrating from goose to pg-flux: see Recipes / adoption. Short version: pg-flux dump your live DB, mark all existing migrations as baselined, switch tools.

#vs pg-schema-diff

pg-schema-diff (from Stripe) does exactly what its name says — diffs two PG schemas. Excellent at the diff itself.

Dimension pg-schema-diff pg-flux
Diff quality Excellent Comparable; we test against the same matrix
Migration lifecycle No Yes (generate / apply / status / repair / baseline)
Drift / verify No Yes
Codegen No Yes
Dump No Yes
Hazard model Stripe's lints Built-in, opt-in via flag

When to choose pg-schema-diff: you just need a diff library to embed in your own tool.

When to choose pg-flux: you want the whole product.

These are complementary in spirit: if pg-schema-diff didn't exist, pg-flux's differ would be smaller. We share inspiration.

#vs rolling your own

The default in most projects: a migrations/ folder with hand-written .sql files, applied by psql -f in CI.

This works until it doesn't. The failure modes:

  • No drift detection. Someone runs SQL in prod, nobody knows.
  • No hazard guards. DROP COLUMN runs and nobody notices.
  • No type generation. Your Go and TS drift further from the DB every week.
  • No PG version awareness. PG 18 features you wrote work locally but fail in prod (running PG 14).
  • No round-trip. Re-creating the dev DB from scratch is hours of manual work.

pg-flux is what you'd build if you tried to write all of that yourself, except we already did.

#When pg-flux is the wrong choice

We try to be straight about this. Don't use pg-flux if:

  • You manage MySQL / SQLite / SQL Server. We don't support them. Use Atlas.
  • You want a turnkey ORM. We don't generate query code; we generate row types. Pair with sqlc.
  • You can't trust generated SQL. Some teams have a policy of human-written-only migrations. pg-flux can still emit the SQL for you to review and commit, but you'll lose the auto-apply guarantees.
  • Your schema is genuinely tiny (under 10 tables, no changes for months). The setup cost isn't justified.
  • You need migration code (not just SQL) — i.e., per-migration Go functions that do conditional logic. pg-flux migrations are pure SQL. Use a different tool.

For everything else PG-shaped, pg-flux is built for you.

#Decision tree

Text
Do you use PostgreSQL?
├── No  → Atlas (cross-DB), or your engine's native tool
└── Yes

    ├── Do you want declarative SQL as source of truth?
    │   ├── No  → Prisma (TS DSL) / Drizzle (TS code) / Atlas (HCL)
    │   └── Yes
    │       │
    │       ├── Do you also need typed queries (not just typed rows)?
    │       │   ├── Yes → pg-flux + sqlc
    │       │   └── No  → pg-flux alone
    │       │
    │       └── Do you use PG-specific features (RLS, partitions, GIST, range types)?
    │           ├── Yes → pg-flux (others lag here)
    │           └── No  → Either works; pg-flux is still our pick for PG-only shops

If you ended up at "pg-flux," head to quick start.