LabHub

Blog

DB Migration Tools 2026 — Atlas / Flyway / Liquibase / Bytebase / pgroll / Squawk / gh-ost Deep Dive

한국어English日本語

Prologue — "One migration line, 5 minutes of downtime"

A 2026 team postmortem.

23:14, routine deploy. ALTER TABLE orders ADD COLUMN status_v2 VARCHAR(32) NOT NULL DEFAULT 'pending'. 23:14:08, primary acquires lock. 23:14:09, all queries start queueing. 23:14:42, backend exhausts connection pool, 5xx begins. 23:19:31, migration ends. 23:19:34, queue drains, normal. 5 minutes 22 seconds of downtime. The table had 400 million rows.

This is still a common 2026 scene. There is no shortage of tools — Flyway, Liquibase, Atlas, Bytebase, pgroll, Squawk, gh-ost, pt-osc, Reshape, dbmate, golang-migrate, Diesel, Alembic, Prisma Migrate, Drizzle Kit. But if the tool does not tell you which migrations are safe, the 5-minute outage repeats.

This post maps the 2026 DB migration landscape. Who is good at what, who is not, and what your team should pick.


Chapter 1 · The 2026 DB Migration Map — Declarative vs Imperative vs Online

The big picture first. Every migration tool sits on one of three axes.

Axis 1: declarative vs imperative

Declarative does for DB schemas what Terraform did for infrastructure. Pro: the schema reads in one place as code. Con: there is no guarantee the generated ALTER is safe (rename can be decomposed into drop+add).

Axis 2: online vs offline

For small tables (under a few hundred thousand rows), offline is simple. For large tables (hundreds of millions of rows, high traffic), online is mandatory.

Axis 3: forward-only vs reversible

A 2026 senior consensus: forward-only plus a sequence of short, safe changes is more realistic than reversible. Down migrations are meaningful only up to "drop the empty column we just added".

One-page summary

ToolModelOnline?Language / targetRecommended for
Atlasdeclarativedirect no, integrations yesmulti-DBdeclarative schema plus CI
Flyway 11imperativenoJava-friendlyenterprise standard
Liquibase 4.30imperative plus metanoJava, XML/YAMLlarge org, multi-DB
Sqitchimperative plus DAGnoDB neutraldependency-explicit
Bytebase 3both plus workflowintegration yesmulti-DBDB DevOps, review
Squawklintern/aPostgresCI gate
pgrolldeclarative plus expand/contractyesPostgreszero-downtime Postgres
gh-ostonline changeyesMySQLlarge-scale MySQL
pt-osconline changeyesMySQLclassic MySQL
Reshapeonline changeyesPostgresRust, zero-downtime
dbmateimperativenomulti-DB, Go CLIlightweight CLI
golang-migrateimperativenoGo, multi-DBGo default
Dieselimperative plus ORMnoRustRust-friendly
Alembicimperative plus autogennoPython, SQLAlchemyPython default
Prisma MigratebothnoTypeScriptNode-friendly
Drizzle Kitdeclarative plus imperativenoTypeScriptTS, lightweight

That is the 2026 map. Now into each cell.


Chapter 2 · Expand-Contract Pattern + Common Foot-Guns

Before picking a tool, learn the pattern. Even with a great tool, a bad pattern still locks tables.

Expand-Contract (Parallel Change)

The core pattern for zero-downtime migrations. Split into three steps.

  1. Expand: add only, so the old and new schema coexist. No drops.
  2. Migrate: code writes and reads against the new schema. A backfill copies old data into the new shape.
  3. Contract: once all code is confirmed to use the new schema only, drop the old.

Example — rename a column (email to email_address).

pgroll, Reshape, gh-ost automate this pattern as their default model. Other tools require humans to split into three migrations.

Common foot-guns

1) Adding NOT NULL on a big table

In Postgres 11+, ALTER TABLE ... ADD COLUMN x INT NOT NULL DEFAULT 0 only flips metadata (fast). But ALTER TABLE ... ALTER COLUMN x SET NOT NULL scans the whole table while holding ACCESS EXCLUSIVE. At 400M rows, that is minutes of lock.

2) Column rename

3) Type change (INT to BIGINT)

4) Adding an index

5) Changing default value (Postgres before 11 / some types)

6) Adding a foreign key

7) Large DELETE / UPDATE

The takeaway: a migration tool is just "something that runs scripts in order"; it does not guarantee safety. Safety comes from the pattern, a linter like Squawk, and review.


Chapter 3 · Atlas (Ariga) — The Declarative Standard

Atlas (atlasgo.io) started in 2022 and grew its share quickly in 2024-2025. It does for DB schemas what HashiCorp Terraform did for infrastructure.

Model

You write the desired schema in schema.hcl (or SQL / JSON). Atlas diffs it against the live DB and generates ALTER statements.

schema "public" {}

table "users" {
  schema = schema.public
  column "id" {
    type = bigint
    null = false
  }
  column "email" {
    type = varchar(255)
    null = false
  }
  primary_key { columns = [column.id] }
  index "idx_users_email" {
    columns = [column.email]
    unique  = true
  }
}

The CLI has two modes.

Strengths

Weaknesses

Where to use

In 2026 Atlas is the de facto standard of the declarative camp.


Chapter 4 · Flyway 11 — The Java Classic

Flyway has existed since 2010 and is the standard in the JBoss / Spring Boot ecosystem. Redgate acquired it in 2024, and 11.x is focused on module cleanup and new database adapters.

Model

V{version}__{description}.sql naming convention. Plain imperative.

db/migration/
  V1__create_users.sql
  V2__add_email_index.sql
  V3__add_orders.sql
  R__create_view_active_users.sql   # Repeatable
  U2__rollback_email_index.sql       # Undo (Teams)

A flyway_schema_history table in the DB tracks which Vs have run. flyway migrate applies only the unapplied ones in order.

Strengths

Weaknesses

Where to use

In 2026 Flyway remains the default in the JVM camp. But fewer new projects use Flyway alone — combinations with Atlas / Squawk are common.


Chapter 5 · Liquibase 4.30 — XML / YAML Friendly

Liquibase is the Flyway rival. From 2006, 4.30 (2025-2026) focuses on changelog formats, DB support, and UX.

Model

List changeSets in a changelog. The format can be XML, YAML, JSON, or SQL.

databaseChangeLog:
  - changeSet:
      id: 1
      author: alice
      changes:
        - createTable:
            tableName: users
            columns:
              - column:
                  name: id
                  type: BIGINT
                  autoIncrement: true
                  constraints: { primaryKey: true, nullable: false }
              - column:
                  name: email
                  type: VARCHAR(255)
                  constraints: { nullable: false, unique: true }
      rollback:
        - dropTable: { tableName: users }

Strengths

Weaknesses

Flyway vs Liquibase in one line

In 2026 they are roughly tied, but new projects clearly trend toward Atlas.


Chapter 6 · Sqitch — The Old-School Dependency Camp

Sqitch (sqitch.org) was built by David Wheeler in 2012 as a "Git-style migration tool". It tracks migrations by a dependency graph, not by version numbers.

Model

Each change has a name. sqitch add appchanges creates three files.

deploy/appchanges.sql    -- apply SQL
revert/appchanges.sql    -- rollback SQL
verify/appchanges.sql    -- verification SELECT

Dependencies live in sqitch.plan.

add_users 2026-05-16T12:00:00Z alice
add_orders [add_users] 2026-05-16T13:00:00Z alice  -- depends on add_users

sqitch deploy applies in dependency-satisfying order. sqitch verify runs the verify SQL to confirm it actually landed.

Strengths

Weaknesses

Where to use

In 2026 Sqitch is a niche but loyal tool. Some PostgreSQL core contributors still prefer it.


Chapter 7 · Bytebase 3 — DB DevOps + Review

Bytebase (bytebase.com) started in 2021 and jumped to 3.x in 2025. Concept: "GitLab / GitHub for DBs".

Model

Web UI plus GitOps. You raise a migration SQL as a PR, and Bytebase:

  1. Auto-lints (SQL Review, a Squawk-style ruleset).
  2. Approval workflow (DBA reviews).
  3. Per-stage auto-deploy (dev → staging → prod).
  4. Schema drift detection (alerts if a change Bytebase did not know about lands in prod).
  5. Data masking, access control (who can see which columns).

Strengths

Weaknesses

Where to use

In 2026 Bytebase is the de facto leader of DB DevOps. Serverless DBs like PlanetScale and Neon have nice native UIs, but Bytebase wins on on-prem / multi-cloud.


Chapter 8 · Squawk — A Postgres Migration Linter

Squawk (squawkhq.com) is a small OSS tool by Steve Dignam from 2020. It reads migration SQL and flags risky patterns. Not a migration tool — a linter.

Model

squawk migration.sql

When it finds something risky, you get an error or warning.

migration.sql:1:1: warning: adding-not-nullable-field
  ALTER TABLE "user" ADD COLUMN "email" TEXT NOT NULL
  Adding a NOT NULL field requires a table rewrite ...
  Use ADD COLUMN ... DEFAULT NULL, backfill, then ALTER ... SET NOT NULL.

Detection rules (Postgres-centric, 30+)

Strengths

Weaknesses

Where to use

A 2026 senior consensus: if you run Postgres, Squawk is the default. It goes into CI regardless of which migration tool you chose.


Chapter 9 · pgroll (Xata) — Zero-Downtime Postgres Migrations

pgroll (github.com/xataio/pgroll) was open-sourced by Xata in 2023-2024. The ambition: the tool itself automates expand-contract.

Model

Define migrations in JSON. pgroll automatically creates views + triggers so the old and new schema are exposed at the same time.

{
  "name": "rename_email_column",
  "operations": [
    {
      "rename_column": {
        "table": "users",
        "column": "email",
        "to": "email_address"
      }
    }
  ]
}

pgroll start to begin → two versions coexist (exposed via views) → pgroll complete to drop the old column. You can pgroll rollback mid-way.

How it works

  1. pgroll start adds the new column/table/index and creates views.
  2. The old view = old schema, the new view = new schema. Code chooses which view via SET search_path.
  3. Triggers sync data both ways (writes to the old column also update the new, and vice versa).
  4. A backfill runs in the background to copy old data into the new column.
  5. Once all traffic is on the new view, pgroll complete drops the old column.

Strengths

Weaknesses

Where to use

In 2026 pgroll is the best bet for zero-downtime Postgres migrations. Maturity is still behind gh-ost (MySQL) though.


Chapter 10 · gh-ost / pt-online-schema-change / Reshape — Online Schema Change

Large tables plus live traffic = online schema change. Three tools.

gh-ost (GitHub, MySQL)

GitHub built and open-sourced this in 2016. Trigger-free, binlog-based.

How it works:

  1. Create a shadow table with the new schema.
  2. Copy rows from the old table to the shadow in chunks.
  3. Read the binlog and apply in-flight changes (INSERT / UPDATE / DELETE) to the shadow.
  4. Cut over: a short lock swaps old and shadow atomically.
gh-ost \
  --user="root" --password="..." \
  --host=primary.db \
  --database="app" --table="orders" \
  --alter="ADD COLUMN status_v2 VARCHAR(32) NOT NULL DEFAULT 'pending'" \
  --execute

pt-online-schema-change (Percona, MySQL)

Part of Percona Toolkit. Trigger-based.

How it works:

  1. Create the shadow table and install INSERT / UPDATE / DELETE triggers on the old.
  2. Copy old to shadow in chunks.
  3. Cut over: two RENAME TABLEs to swap.

Reshape (Postgres, Rust)

Built by Fabian Lindfors in 2022. Postgres expand-contract.

How it works: similar to pgroll. Define migrations in TOML, not SQL, then views + triggers expose old and new in parallel.

[[actions]]
type = "add_column"
table = "users"
column = "email_address"
data_type = "text"
nullable = true

Three-way comparison

gh-ostpt-oscReshapepgroll
DBMySQLMySQLPostgresPostgres
Triggersnoyesyesyes
Binlogyesnonono
Activity (2026)mediumlowlowhigh
Recommendedlarge MySQLgh-ost edge cases(avoid)Postgres

The 2026 consensus: MySQL: gh-ost default, pt-osc fallback. Postgres: pgroll as the rising standard.


Chapter 11 · dbmate / golang-migrate / Diesel / Alembic — Language Camps

Each language ecosystem has its default.

dbmate (Go, multi-DB)

amacneil/dbmate. A single-file Go binary with a clean CLI.

dbmate new add_users
# creates db/migrations/20260516120000_add_users.sql

Each file has up / down sections.

-- migrate:up
CREATE TABLE users (id BIGINT PRIMARY KEY, email TEXT NOT NULL);

-- migrate:down
DROP TABLE users;

golang-migrate (Go, multi-DB)

golang-migrate/migrate. CLI plus Go library.

migrations/
  000001_create_users.up.sql
  000001_create_users.down.sql

dbmate vs golang-migrate — in 2024-2025 many teams switched to dbmate. For new Go projects dbmate is the lighter default (or Atlas).

Diesel migrations (Rust)

Part of the Diesel ORM. diesel migration generate add_users produces up.sql / down.sql.

Alembic (Python, SQLAlchemy)

The migration tool for SQLAlchemy. Migrations are Python code.

def upgrade():
    op.add_column('users', sa.Column('email', sa.String(255), nullable=False))

def downgrade():
    op.drop_column('users', 'email')

In 2026, Django still uses Django migrations, while FastAPI / SQLAlchemy still defaults to Alembic.


Chapter 12 · Prisma Migrate / Drizzle Kit — The TypeScript Camp

Node / TypeScript is fragmented. Two leaders.

Prisma Migrate

Part of the Prisma ORM. Write models in schema.prisma, then prisma migrate dev generates and applies migrations.

model User {
  id    BigInt  @id @default(autoincrement())
  email String  @unique
}

Drizzle Kit

Part of the Drizzle ORM. Schema defined in TypeScript code, then drizzle-kit generate produces a SQL diff.

export const users = pgTable("users", {
  id: bigserial("id").primaryKey(),
  email: varchar("email", { length: 255 }).notNull().unique(),
});

The 2026 TS consensus:


Chapter 13 · Who Picks What — A Decision Tree

SituationRecommendation
Single app, Postgres, low trafficdbmate or golang-migrate plus Squawk
Single app, MySQL, low trafficFlyway or dbmate
Java / Spring BootFlyway (or Liquibase) plus Squawk
Node / TypeScript, full-stackPrisma plus Atlas at scale
Node / TypeScript, edgeDrizzle Kit plus Squawk
Python / DjangoDjango migrations
Python / FastAPIAlembic
RustDiesel or SQLx plus dbmate
Go, new projectAtlas (declarative) or dbmate (simple)
Microservices 50+Bytebase plus each service's tool
Large Postgres, zero downtime requiredpgroll plus Squawk plus Atlas
Large MySQL, zero downtime requiredgh-ost plus Flyway plus a Squawk-MySQL alternative
DBA team present, review workflowBytebase-centric
Cross-DB (Postgres + MySQL + Oracle)Liquibase or Bytebase
1000+ accumulated migrationsSqitch (dependency graph)

Common antipatterns


Chapter 14 · Korea / Japan Cases — Toss / Kakao / Mercari

Toss

At Toss SLASH 2023, Toss disclosed broad use of gh-ost on MySQL. The payments domain is 24/7, so any lock is revenue loss. They tune chunk size and throttle per domain with gh-ost.

In 2025-2026 some new Postgres services at Toss are reportedly evaluating pgroll. Squawk is a mandatory CI step on every new migration PR.

Kakao

Kakao's messenger / pay / bank each take a different DB strategy. Kakao Bank runs on Oracle, so Liquibase plus a custom workflow. Some new services in Kakao Pay use Flyway plus gh-ost (MySQL). Kakao Messenger runs on a proprietary distributed storage, so general migration tools do not apply.

In 2024 some Kakao teams reportedly adopted Atlas to unify their Go backends, as discussed at internal conferences.

Mercari (Japan)

Mercari runs 100+ microservices. Each service picks its own tool, but lint (Squawk plus internal rules) is the shared CI step. Many services use Spanner, so the Spanner CLI plus a homegrown migration framework dominates there.

The Mercari Engineering blog frequently writes about "Schema migration as code" — an internal implementation of a declarative model similar to Atlas / Bytebase.

LY Corporation (LINE + Yahoo Japan)

After the 2023 merger, LINE's core backend DB migrations are standardizing on Flyway. Some new Go services use Atlas. An internal sql-lint tool acts as a Squawk-MySQL substitute with custom rules.

Common patterns:

That is the 2026 flow at Korean / Japanese big tech.


Conclusion — Many tools, few patterns

The whole post in one page:

  1. Tools are plentiful. Atlas, Flyway, Liquibase, Sqitch, Bytebase, pgroll, Squawk, gh-ost, pt-osc, Reshape, dbmate, golang-migrate, Diesel, Alembic, Prisma, Drizzle. No need for another.
  2. Start your selection with language and team fit. Java → Flyway, Python → Alembic, Go → Atlas / dbmate, TS → Prisma / Drizzle.
  3. If you need zero-downtime, pattern decides the tool. Expand-contract → pgroll (Postgres) / gh-ost (MySQL).
  4. Squawk (or equivalent linter) is default. As long as you run Postgres, put it in CI.
  5. A working positive down migration is mostly a fantasy. Forward-only plus a sequence of short, safe changes is more realistic than reversible.
  6. The migration tool does not guarantee safety. Pattern + lint + review do.

Finally: the 5-minute outage in the prologue was not the tool's fault. The cause was running ALTER COLUMN ... SET NOT NULL on a 400M-row table inside a single transaction. Keep the tool, change the pattern to expand-contract, and 5 minutes becomes 0 seconds.


References

Comments

No comments yet.

Sign in to leave a comment