pg-flux
v0.1 · PostgreSQL 14 – 18

Your Postgres schema and your app types,finally in the same place.

Write your schema as plain SQL. pg-flux generates the migration, applies it safely, and emits Go + TypeScript types that match — every time. No DSL. No second source of truth. No more 3 a.m. "wait, what type IS the email column."

Go 1.25+ MIT licensed Zero-config defaults
~/app · pg-flux · zsh
$ pg-flux init✓ scaffold .pg-flux.yml, schema/, migrations/$ pg-flux migrate generate --label add_usersGenerated: migrations/20260520_add_users.sql (4 statements)$ pg-flux migrate applyapply 20260520_add_users.sql … ok$ pg-flux gen --lang go,ts --validators=zod[go] wrote 5 files · [ts] wrote 8 files

What's in the box

Every piece that used to be a separate tool.

One CLI handles the lifecycle: schema in SQL, diffed against live, applied safely, types generated, drift caught. Stop bolting tools together.

Declarative schema

Write SQL once. pg-flux figures out the migration. No HCL, no DSL, no JSON config of your tables — just SQL, the way PostgreSQL meant it.

Refuses to break prod

Mass-drops blocked. Type rewrites blocked. Drift between generate and apply caught by a baseline-hash check. You have to opt in to anything risky.

Adopts against existing DBs

One command extracts your live schema into source files, round-trip clean. The dump → migrate generate loop produces zero pending statements. Verified in CI.

Generates the types

Go structs and TypeScript interfaces for every catalog object with a row shape. Branded IDs, zod validators, ORM tags — opt in to what you need, ignore the rest.

PostgreSQL 14 through 18

Virtual generated columns, NULLS NOT DISTINCT, NOT ENFORCED, security_invoker views — all version-gated and emitted only when the target server supports them.

Built for CI

Three exit codes: drift detected, generated code stale, undeclared live objects. Wire a pipeline that fails on any of them and you'll catch issues before they reach production.

How it works

The everyday workflow.

Four commands. Edit, generate, apply, regenerate. Each step is observable and idempotent.

  1. 1

    Write SQL in schema/

    CREATE TABLE users (
      id    bigint PRIMARY KEY,
      email text NOT NULL,
      role  user_role NOT NULL DEFAULT 'member'
    );
  2. 2

    Generate a migration

    $ pg-flux migrate generate --label add_role
    Generated: migrations/20260520_add_role.sql (3 statements)
  3. 3

    Apply safely

    $ pg-flux migrate apply
    apply 20260520_add_role.sql ... ok
  4. 4

    Regenerate types

    $ pg-flux gen
    [go] wrote 2 files (4 already up to date)
    [ts] wrote 4 files (6 already up to date)

How it compares

One tool. No second source of truth.

Most teams bolt together a migration tool, a dump utility, and a codegen. pg-flux replaces all three with one model.

Capabilitypg-fluxTypical alternative
Declarative source✓ NativeUsually no (sql up/down pairs)
Bidirectional dump✓ Round-trip cleanpg_dump (noisy, not round-trip)
Drift detection✓ 3 layersManual
Go + TS codegen✓ Built-inSeparate tool (sqlc, prisma)
PG 18 features✓ Version-gatedOften lagging
CI gatesdrift, verify, gen --checkCustom scripts

Install and try it in two commands.

Go install, then point at any local Postgres.

$ go install github.com/nex-gen-tech/pg-flux/cmd/pg-flux@latest$ pg-flux init