pgschema: a Terraform style workflow for PostgreSQL schema changes
Terraform-style, declarative Postgres schema migration. Agent friendly.
At a glance
- What is it?
- pgschema is a Go CLI that treats a PostgreSQL schema as desired state: you dump the live schema to SQL files, edit them, and pgschema plan diffs them against the database and generates the migration DDL, which pgschema apply then executes with concurrent change detection, transaction-adaptive execution and lock timeout control. It is Postgres only, needs no shadow database and requires no migration history table.
- Who is it for?
- pgschema suits a Postgres team that wants to version control its schema as plain SQL, wants a plan step before changes land, and needs Postgres specific objects such as row level security and partitioning tracked properly.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- pgplex/pgschema1,083 ★ · +15
| Repository | 2026-10-19 | 2026-11-07 |
|---|---|---|
| pgplex/pgschema | 1.1k | 1.1k |
15 Stars in the last 19 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The workflow: dump, edit, plan, apply
pgschema is a CLI tool that brings Terraform-style declarative schema migration to PostgreSQL, and the whole model fits in one line, pgschema dump, edit schema.sql, pgschema plan, pgschema apply. Dump extracts the current database schema as SQL files. Plan diffs your edited schema against the live database and generates the migration DDL. Apply executes with concurrent change detection, transaction-adaptive execution and lock timeout control. The key point is that the artifact you version control is a schema file, not a numbered migration. The repository description puts it as Terraform-style declarative schema migration, and the homepage is pgschema.com, with an introduction blog post that explains the design and a screencast showing it in action. The primary language is Go and the licence is Apache 2.0.
State-based rather than migration-file-based, and what that changes
The comparison with other tools is the sharpest part of the README. Tools like Flyway and Liquibase require you to write and number migration files manually, and pgschema works like Terraform, where you declare what the schema should look like and it figures out the SQL to get there. There is no migration history table and no manual sequencing. The consequence table makes the trade explicit. pgschema is state-based, Flyway and Liquibase are migration-file-based, and Atlas is state-based as well. So pgschema is not the only state-based option, and the differentiators are the Postgres depth, the absence of a shadow database and the absence of a history table. The history question is the one to think about hardest, because in a migration-file workflow the history table is also a record of what happened, and moving to a state-based model means that record is your git history instead.
Postgres only, and it goes deep on the objects generic tools skip
pgschema is Postgres only, which is presented as a feature rather than a limitation, since it means it handles Postgres-specific objects that generic tools skip: row level security policies, partitioned tables, partial indexes, constraint triggers, identity columns, domain types, default privileges and column-level grants. The supported objects table is long and detailed, spanning versions 14 to 18. Tables cover columns, identity and generated columns, RANGE, LIST and HASH partitioning, LIKE clauses and inline and table-level constraints. Constraints cover primary and foreign keys with ON DELETE and ON UPDATE, unique, check, NOT VALID and DEFERRABLE. Indexes cover regular, unique, partial and functional, all the methods from btree through brin, and CONCURRENTLY. Functions and procedures cover IN, OUT and INOUT parameters with defaults, SETOF and TABLE return types, SECURITY DEFINER and the volatility and strict attributes, while aggregates cover SFUNC, STYPE, FINALFUNC, INITCOND, COMBINEFUNC, the serial functions, moving aggregates, SORTOP, PARALLEL and ordered-set and hypothetical-set aggregates. Triggers cover BEFORE, AFTER and INSTEAD OF, the four events, ROW and STATEMENT level, WHEN conditions, constraint triggers and REFERENCING OLD and NEW TABLE. There is an explicit unsupported list for what is out of scope.
No shadow database, because validation uses an embedded Postgres
Most state-based tools spin up a temporary shadow database to validate migrations. pgschema uses an embedded Postgres instance internally and cleans up after itself, so no extra infrastructure is needed. The go.mod names the mechanism, the fergusstrange/embedded-postgres package at version 1.34.0. The .env.example shows the escape hatch, since if PGSCHEMA_PLAN_HOST is provided the plan command uses an external database to validate the desired state instead of spinning up an embedded PostgreSQL instance, which is useful in environments where embedded postgres has limitations. The external path needs its own host, port, database, user, password and SSL mode, all with the PGSCHEMA_PLAN_ prefix. The connection handling follows the standard libpq environment variables for the target database, with PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD, PGSSLMODE and PGAPPNAME, and the documentation notes these are used automatically when the corresponding CLI flags are not provided.
# PostgreSQL connection configuration, used when CLI flags are absent
PGHOST=localhost
PGPORT=5432
PGDATABASE=your_database_name
PGUSER=your_username
PGPASSWORD=your_password_here
PGAPPNAME=pgschemaInstallation by Nix, and the Windows exclusion
The installation section points at the pgschema.com installation page and then gives the Nix route, with a flake at the top of the repository, a default.nix, a flake.lock and a nix/ directory. You run nix build and nix run, and to pass arguments you use the double dash, so nix run . -- plan. There is a specific failure mode documented, that if the build fails with a vendorHash mismatch you update nix/pgschema.nix with the hash printed by Nix. The exclusion is the one to notice: Windows is not supported, and the documentation says to use WSL, the Windows Subsystem for Linux, or a Linux VM instead. A Dockerfile is also in the repository, built on golang:1.24-alpine with a static binary and a non-root user in the runtime stage, so a container route exists for the teams that would rather not use Nix.
nix build
nix run
nix run . -- planFree because Bytebase sponsors it, and that is the business model
The Why is it free section is direct. The answer is that there are no current plans to charge for pgschema, and that pgschema is sponsored by Bytebase, a commercial database governance platform, which covers the needs of teams that require controls beyond schema migration, such as data access control, data masking, audit logging and multi-database management across an organization. The comparison table draws the same line commercially, with pgschema listed as free and open source under Apache 2.0 with no feature gating, and Flyway, Liquibase and Atlas listed as having a free tier with advanced features paid. So the practical reading is that pgschema is the free tier of a broader governance product, and that the tool is the acquisition path rather than the business.
The repository layout and the release cadence
The top level of the repository shows a Go CLI with a specific shape. There is main.go at the root, a cmd/ directory for the command implementations, an internal/ directory, an ir/ directory which by the name is the intermediate representation between the schema and the generated DDL, a docs/ directory, a testdata/ directory, a testutil/ directory, and the .trellis/ and .claude/ directories alongside an AGENTS.md and a CLAUDE.md. There is a CODEOWNERS file, a Dockerfile, a flake.nix, a default.nix, a nix/ directory and a .env.example. The go.mod declares go 1.24.0 with a toolchain of go1.24.7, and the direct dependencies include pgx v5 for the Postgres driver, cobra for the CLI, embedded-postgres for validation, godotenv and lib/pq, testify, go-cmp and BurntSushi/toml. The releases are v1.13.1 on 2026-09-20, v1.13.2 and v1.13.3 both on 2026-10-15, and the last push was on 2026-10-15, so two patch versions shipped on the same day, which is the cadence of a project chasing down issues quickly.
Editorial conclusion
pgschema suits a Postgres team that wants to version control its schema as plain SQL, wants a plan step before changes land, and needs Postgres specific objects such as row level security and partitioning tracked properly. It is the wrong choice for a multi-database shop, since the tool is Postgres only, and a poor fit if your workflow is already built around numbered migration files that your team and tooling understand, because the state-based model changes where the history of a schema lives. Before adopting it, read the unsupported objects page, since the project keeps an explicit list of what it will not handle, and note that Windows is not supported, with WSL or a Linux VM required.
Frequently asked questions
What is pgschema?
It is a CLI tool that brings Terraform-style declarative schema migration to PostgreSQL. Instead of writing migration files by hand, you declare the desired schema state and pgschema generates the migration plan automatically, with dump to extract the schema, plan to diff it against the live database and apply to execute the DDL. The licence is Apache 2.0.
How does pgschema compare with Flyway, Liquibase and Atlas?
pgschema and Atlas are both state-based, while Flyway and Liquibase are migration-file-based. pgschema is Postgres only where the others are multi-database, it needs no shadow database where Atlas requires one by default, it needs no migration history table where Flyway requires one, and it is free and open source with no feature gating where the others have a free tier with paid advanced features.
Does pgschema need a shadow database to validate migrations?
No. It uses an embedded Postgres instance internally and cleans up after itself. If PGSCHEMA_PLAN_HOST is set, the plan command will instead use an external database to validate the desired state, which is useful where embedded postgres has limitations.
How do I install pgschema?
The installation page is at pgschema.com/installation, and the repository ships a Nix flake, so nix build and nix run work, with arguments passed after a double dash, for example nix run . -- plan. A vendorHash mismatch is fixed by updating nix/pgschema.nix with the hash Nix prints. Windows is not supported, so WSL or a Linux VM is required.
Why is pgschema free?
The README says there are no current plans to charge for it, and that pgschema is sponsored by Bytebase, a commercial database governance platform that covers needs beyond schema migration such as data access control, data masking, audit logging and multi-database management.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pgplex-pgschema)Star history chart for your README
[](https://hysenlabs.com/projects/pgplex-pgschema)Was this useful?