Best Postgres Migration Tools in 2026 (Compared)
The best Postgres migration tool is usually the one that matches how your team already writes code: Prisma Migrate, Drizzle Kit or Alembic if your schema lives in an ORM, dbmate or golang-migrate if you want plain SQL files with almost no tooling, Flyway or Liquibase for larger teams that need change management across many databases, Atlas for declarative "desired state" schemas, and pgroll when zero-downtime changes on busy tables are the main concern. Below is a comparison by style, license and trade-off, followed by the practices that matter more than the tool.
#Postgres migration tools at a glance
| Tool | Style | Migrations written as | License (as of November 2026) | Best for |
|---|---|---|---|---|
| Flyway | Versioned | SQL files (V1__name.sql), Java | Community: Apache 2.0; Enterprise: commercial | Teams standardizing across many databases |
| Liquibase | Versioned changelogs | XML, YAML, JSON or SQL | Community 5.x: FSL-1.1-ALv2; Secure: commercial | Enterprises with audit and rollback needs |
| Sqitch | Dependency-based | SQL deploy, revert and verify scripts | MIT | SQL-first teams who want explicit reverts |
| Atlas | Declarative and versioned | HCL or SQL desired state, generated diffs | Repository: Apache 2.0; Pro features paid | Schema-as-code with automatic planning |
| dbmate | Versioned | SQL with -- migrate:up / -- migrate:down | MIT | Small teams, any language |
| golang-migrate | Versioned | .up.sql / .down.sql files | MIT | Go services, CLI or library |
| Graphile Migrate | Roll-forward | SQL (current.sql, then committed) | MIT | Fast iteration on SQL-heavy apps |
| pgroll | Expand/contract | JSON or YAML operations | Apache 2.0 | Zero-downtime changes on live tables |
| Prisma Migrate | ORM-generated | Prisma schema, generated SQL | Apache 2.0 | TypeScript apps using Prisma |
| Drizzle Kit | ORM-generated | TypeScript schema, generated SQL | Apache 2.0 | TypeScript apps using Drizzle |
| Alembic | ORM-generated | Python scripts, autogenerate from SQLAlchemy | MIT | Python apps using SQLAlchemy |
#Four styles of migration tool
Understanding the style matters more than comparing feature lists.
Versioned SQL runners (dbmate, golang-migrate, Flyway in its simplest use) keep numbered files and a table recording which ran. You write every change by hand. They are predictable and easy to debug, because what runs is exactly what you wrote.
Change-management tools (Liquibase, Flyway's paid tier, Sqitch) add structure: changesets with authors and IDs, dependencies, verify steps, rollback scripts, environment targeting and reporting. Useful when many teams touch the same databases.
Declarative tools (Atlas, and the ORM tools in a sense) start from the schema you want and compute the migration from the difference. You stop writing alter table by hand, but you must review the generated plan, because a diff cannot know that a renamed column is a rename and not a drop plus an add.
Zero-downtime tools (pgroll) change how a migration runs: the old and new schema versions work at the same time while data is backfilled, so old and new app versions can run side by side during a deploy.
#The tools, briefly
#Flyway
Redgate's Flyway is one of the most widely used migration tools. You drop V2__add_orders.sql into a folder and flyway migrate applies what is new. The free Community edition covers versioned migrations; the Enterprise edition adds features such as undo script generation, drift detection and policy checks, with pricing on request (editions). Pick it if you want a well-known, boring tool that works the same across Postgres and other databases.
#Liquibase
Liquibase tracks changesets in changelog files that can be XML, YAML, JSON or SQL, and supports rollbacks, contexts and labels for targeting environments. Note the license change: starting with 5.0 (September 2025), Liquibase Community is under the Functional Source License (FSL-1.1-ALv2), with each release converting to Apache 2.0 two years after it ships; Liquibase says FSL does not meet the OSI open-source definition (announcement). For most internal use this changes little, but check it if you build a competing product or redistribute it.
#Sqitch
Sqitch does not number migrations. Each change has deploy, revert and verify scripts, and a plan file lists changes with their dependencies. It is SQL-native and makes reverts first-class. The learning curve is a little steeper than a numbered-file runner.
#Atlas
Atlas by Ariga lets you describe the desired schema in HCL or SQL and plans the migration for you, or work with versioned migration directories. The free Starter plan covers migration planning and execution; Pro (from $9 per developer per month, plus usage-based CI pipelines, as of November 2026) adds migration linting and safety checks, drift detection and more (pricing). Pick it if you like schema-as-code and want automated review in CI.
#dbmate and golang-migrate
Both are small, language-agnostic CLIs for plain SQL migrations. dbmate keeps up and down sections in one file and can create the database and dump the schema. golang-migrate uses separate .up.sql and .down.sql files and doubles as a Go library, so services can migrate on startup. Pick either when you want almost nothing between you and SQL.
#Graphile Migrate
Graphile Migrate is roll-forward only. You edit current.sql, it re-applies on every save during development, and you commit it into an immutable migration when done. It is opinionated and fast for SQL-heavy apps, and its authors argue that down migrations are rarely used in production anyway.
#pgroll
pgroll from Xata performs zero-downtime, reversible migrations by serving multiple schema versions at once, backfilling columns automatically and rolling back instantly if needed. It works with Postgres 14 and later. Pick it when your tables are large and busy and a locking alter table is not acceptable.
#Prisma Migrate, Drizzle Kit and Alembic
If your schema already lives in ORM code, use the ORM's tool:
# Prisma
npx prisma migrate dev --name add_orders # create and apply in development
npx prisma migrate deploy # apply in production
# Drizzle
npx drizzle-kit generate # SQL migration from your TS schema
npx drizzle-kit migrate # apply it
# Alembic (SQLAlchemy)
alembic revision --autogenerate -m "add orders"
alembic upgrade headAll three generate SQL you should read before applying. They are less suited to Postgres features the ORM does not model, such as Row Level Security policies, triggers or extensions; you add those as raw SQL migrations.
#How to choose
- Solo developer or small team, SQL-comfortable: dbmate or golang-migrate, or your platform's own CLI.
- TypeScript or Python app with an ORM: the ORM's tool, plus raw SQL migrations for policies and functions.
- Several teams, many environments, audit requirements: Flyway or Liquibase.
- You want to declare the end state and let a tool plan it: Atlas.
- Large, busy tables where locks hurt: pgroll, or careful hand-written expand/contract migrations.
Do not run two tools against the same schema. Pick one source of truth.
#Practices that matter more than the tool
Every tool will happily run a migration that locks a busy table for minutes. These habits prevent that:
-- Give up instead of queueing behind a long transaction
set lock_timeout = '5s';
-- Build indexes without blocking writes (cannot run inside a transaction block)
create index concurrently orders_customer_id_idx on public.orders (customer_id);
-- Add constraints in two steps: instant, then a non-blocking scan
alter table public.orders
add constraint orders_customer_fk foreign key (customer_id)
references public.customers (id) not valid;
alter table public.orders validate constraint orders_customer_fk;Also: keep migrations small and additive (add, backfill, switch, then drop in a later release), backfill large tables in batches, and never edit a migration that has already been applied. Test the whole chain on a fresh database in CI, and preview it against production-like data before it runs. A preview branch per pull request is the easiest way to do the latter.
#Migrations on StitchDB
Every tool above connects to a StitchDB project like any Postgres: Prisma, Drizzle, Kysely, Flyway, Liquibase and Alembic are listed in the compatibility docs. Use the connection string from Settings → Database with session mode (port 5432) for migrations, since transaction mode does not keep session state between transactions (connect). TLS is required.
If you do not have a tool yet, the StitchDB CLI includes one built around plain SQL files:
stitchdb migration new create_orders # stitchdb/migrations/<timestamp>_create_orders.sql
stitchdb migration up # apply to the local database
stitchdb db push --dry-run # list what would run on the project, with warnings
stitchdb db push # apply to the linked projectEach migration runs once, in order, in its own transaction. stitchdb db diff and stitchdb db pull capture changes made in Studio into migration files, and declarative schema files in stitchdb/schemas/ can generate migrations from a desired state (CLI migrations).
Before anything runs, db push, the SQL Editor and Database → Migrations check each statement against your tables' real sizes and warn when it would lock a busy table, with a safer version such as create index concurrently or not valid plus validate constraint (safe schema changes). On paid plans, preview branches give each pull request its own database built from your migrations, and merging applies them to production.
Trade-offs: the StitchDB CLI is specific to StitchDB projects, so if you need one tool across many database vendors, Flyway, Liquibase or Atlas is the better fit, and they work against StitchDB too.
#FAQ
#What is the most popular Postgres migration tool?
Flyway and Liquibase are the long-standing general-purpose tools, and in application code the ORM tools (Prisma Migrate, Drizzle Kit, Alembic) are the most common. Popularity matters less than fit with your stack.
#Do I need down migrations?
They are useful in development and for some rollbacks, but many teams roll forward only: fix a bad migration with a new one. Data-destroying changes cannot be truly reversed by a down script anyway; backups and point-in-time recovery cover those.
#Is Liquibase still open source?
Liquibase Community 5.0 and newer use the Functional Source License, which Liquibase itself says is not OSI open source; each release becomes Apache 2.0 two years after release. Versions before 5.0 remain under Apache 2.0.
#How do I avoid downtime during Postgres migrations?
Set a lock_timeout, build indexes concurrently, add constraints as not valid and validate later, backfill in batches, and split breaking changes into expand and contract steps. Tools like pgroll automate the expand/contract pattern.
#Can I use Prisma or Drizzle with StitchDB?
Yes. Connect with the project's connection string on port 5432 with sslmode=require and run their migration commands as usual.
Ship schema changes safely: create a free project and read safe schema changes.