pg-flux

Getting started

Quick start

From zero to a working pg-flux setup — schema, migration, generated types — in five minutes.

Get from zero to a working pg-flux setup in five minutes. By the end of this guide you'll have a managed schema, a generated migration, and typed Go + TypeScript modules synced with your database.

#Install

macOS / Linux — one command, no Go required:

Shell
curl -sSfL https://raw.githubusercontent.com/nex-gen-tech/pg-flux/main/install.sh | sh

Windows — PowerShell one-liner (no admin required):

Text
$InstallDir = "$env:USERPROFILE\.local\bin"
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
$Release = (Invoke-RestMethod "https://api.github.com/repos/nex-gen-tech/pg-flux/releases/latest").tag_name
$Arch = if ($env:PROCESSOR_ARCHITECTURE -eq "ARM64") { "arm64" } else { "amd64" }
$Zip = "pg-flux-windows-$Arch.zip"
Invoke-WebRequest -Uri "https://github.com/nex-gen-tech/pg-flux/releases/latest/download/$Zip" -OutFile "$env:TEMP\$Zip"
Expand-Archive -Path "$env:TEMP\$Zip" -DestinationPath "$env:TEMP\pg-flux-extracted" -Force
Copy-Item "$env:TEMP\pg-flux-extracted\pg-flux.exe" -Destination "$InstallDir\pg-flux.exe" -Force
$UserPath = [Environment]::GetEnvironmentVariable("PATH", "User")
if ($UserPath -notlike "*$InstallDir*") { [Environment]::SetEnvironmentVariable("PATH", "$UserPath;$InstallDir", "User") }
pg-flux version

Alternative — if you have Go 1.22+ installed:

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

Verify:

Shell
pg-flux version
# pg-flux v0.1.6

You'll also need:

  • PostgreSQL 14 or newer running somewhere you can reach.
  • For codegen: Go 1.22+ (if generating Go types) and/or TypeScript (any modern version) in the target project.

#Scaffold a project

In a fresh directory:

Shell
pg-flux init

This creates:

Text
.pg-flux.yml          # tool-level config (DB URL, schema dir, migrations dir)
schema/               # your declarative SQL lives here
  schema.sql          # example seed file
migrations/           # generated migrations land here

Edit .pg-flux.yml to point at your database:

YAML
version: 1
db: postgres://postgres:postgres@localhost:5432/mydb?sslmode=disable
schema_dir: ./schema
migrations_dir: ./migrations
target_schemas: [public]

(Or set DATABASE_URL in the environment — the CLI flag --db always wins over both.)

#Write your schema declaratively

Replace schema/schema.sql with the schema you want — exactly the SQL you'd run by hand:

SQL
CREATE TYPE user_role AS ENUM ('admin', 'member', 'guest');

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

CREATE TABLE posts (
  id      bigint PRIMARY KEY,
  user_id bigint NOT NULL REFERENCES users(id),
  title   text NOT NULL,
  body    text NOT NULL DEFAULT ''
);

#Generate a migration

Shell
pg-flux migrate generate --label initial_schema

pg-flux inspects your live database, computes the minimum-DDL diff, and writes a migration file:

Text
Generated: migrations/20260520_103245_initial_schema.sql (8 statements)

The file embeds a baseline hash so apply can detect drift if anyone manually modifies the DB before you apply.

#Apply

Shell
pg-flux migrate apply
Text
apply 20260520_103245_initial_schema.sql ...
      ok
Applied 1 migration(s), 0 already up to date.

The migration runs inside an advisory-locked transaction. If you re-run it, pg-flux notices it's already applied and skips it.

#Generate types

For Go:

Shell
pg-flux gen --lang go --out ./internal/dbgen

For TypeScript (with the opinionated options most apps want):

Shell
pg-flux gen --lang ts --out ./src/db \
  --column-case=camel --bigint-as=number --date-as=string \
  --null-style=optional --enum-style=const-object \
  --branded-ids --insert-update-helpers --validators=zod

You'll get one file per object kind:

Text
internal/dbgen/
  tables.go         # struct per table
  enums.go          # typed constants + sql.Scanner/Valuer
  types.go          # composite types + domains
  views.go          # read-only view rows
  functions.go      # function param + result types

src/db/
  tables.ts         # interfaces + Insert/Update helpers
  enums.ts          # const-object + derived type
  brands.ts         # type UserId = number & { __brand: "UserId" }
  validators.ts     # parallel zod schemas
  index.ts          # barrel re-export

Want to scaffold a full codegen config?

Shell
pg-flux gen init

Writes .pg-flux-codegen.yml with every option documented inline.

#Iterate

Whenever you change schema/, run the same three commands:

Shell
pg-flux migrate generate --label add_column
pg-flux migrate apply
pg-flux gen

For CI, use the --check flags to fail builds on stale state:

Shell
pg-flux drift --strict       # exit 2 if live ≠ source
pg-flux verify --strict      # exit 4 if live has undeclared objects
pg-flux gen --check          # exit 3 if generated files are stale

#What next?