Updated Nov 5, 20267 min read

Best Database Migration Tools in 2026: Flyway, Liquibase, Atlas, golang-migrate and More

A neutral comparison of schema migration tools for Postgres and other SQL databases, covering versioned vs declarative migrations, rollbacks, licensing and ORM-coupled tools like Prisma Migrate and Drizzle Kit.

A migration tool keeps the database schema in step with the code: it records which changes have run, applies new ones in order, and makes the same sequence repeatable on a laptop, in CI and in production. The tools differ in how you describe changes, as numbered SQL files, changelogs or a desired schema, and in what they do when a change fails.

This guide compares the widely used tools and their trade-offs. Encore, infrastructure from code covered in the first section, runs SQL migrations from each service's migrations directory as part of local development and every deploy, and its docs show how to generate those files with Atlas, Drizzle or Prisma.

Database migration tools at a glance

ToolStyleWritten inDown or undoLicenseBest fit
FlywayVersioned SQL or JavaJavaUndo scripts (U prefix)Apache 2.0 Community editionJVM teams, many engines
LiquibaseChangelogs (XML, YAML, JSON, SQL)JavaRollback per changesetFSL from 5.0Regulated teams that want change tracking
AtlasDeclarative or versioned, with lintingGoComputed down migrationsOpen coreSchema-as-code with review checks
golang-migrateVersioned up and down SQLGoDown filesMITPlain SQL from a CLI or Go library
gooseVersioned SQL or Go functionsGoDown sectionsMITGo apps that need code migrations
dbmateVersioned SQLGoDown sectionsMITAny language, single binary
Prisma MigrateGenerated from Prisma schemaTypeScriptDown scripts via migrate diffApache 2.0Prisma ORM users
Drizzle KitGenerated from TypeScript schemaTypeScriptNo down migrationsApache 2.0Drizzle ORM users

Where Encore fits

Encore

Encore is infrastructure from code for TypeScript and Go, with a platform that provisions and deploys into your own AWS or GCP account. It is not another migration tool to pick from the list. A database declared in code points to a migrations directory, and Encore applies the migrations wherever that database runs: locally in Docker with encore run, and on RDS or Cloud SQL during each deploy.

Application code passes through Encore and infrastructure guardrails to resources provisioned in your own AWS or GCP account.
Encore provisions the infrastructure your application needs in your own AWS or GCP account.
// accounts/db.go package accounts import "encore.dev/storage/sqldb" // Files in ./migrations are named 1_create_accounts.up.sql, 2_add_plan.up.sql, ... var db = sqldb.NewDatabase("accounts", sqldb.DatabaseConfig{ Migrations: "./migrations", })
Get started
brew install encoredev/tap/encore &&
encore app create
Copy

Run in your terminal to get started locally.

Encore runs migrations with golang-migrate and records them in a schema_migrations table, applying up files in order while down files are left for you to run by hand, as the database docs describe. If a migration fails, Encore rolls it back and, in the cloud, aborts the deploy so the old version keeps running against the old schema.

Generated migrations plug into the same flow: in TypeScript, setting migrations: { path: "migrations", source: "drizzle" } or source: "prisma" lets Drizzle or Prisma generate the files while Encore applies them, and in Go, Atlas with GORM writes golang-migrate-format files into the same directory.

For coding agents, a schema change is a new numbered file next to the service that owns the table, and encore run applies it locally right away, so the agent sees a failing migration before a reviewer does.

Flyway

Flyway

Flyway, from Redgate, runs versioned migrations named V1__create_users.sql, V2__add_index.sql and so on, with Java-based migrations when SQL is not enough. It supports a long list of databases and integrates with Maven, Gradle and Spring Boot, which is why it is the default in many JVM shops.

Flyway documents undo migrations, but Redgate's docs themselves recommend backwards-compatible changes and tested backups over relying on undo.

Liquibase

Liquibase

Liquibase describes changes as changesets in XML, YAML, JSON or SQL changelogs, each with an author and ID, and can generate rollback statements for many change types. Preconditions, contexts and labels let one changelog target several environments, which regulated teams value for audit trails.

Liquibase Community 5.0 moved from Apache 2.0 to the Functional Source License, which allows production use but restricts competing commercial offerings. Teams with an OSI-only policy should check this before adopting it.

Atlas

Atlas

Atlas treats the schema as code: you describe the desired schema in HCL, SQL or an ORM, and Atlas computes the migration, either applied directly or written as versioned files. Its migration linting flags destructive or locking changes in CI, which catches problems that a plain SQL runner would apply without complaint.

Atlas also offers migration linting that flags destructive or locking changes before they run. It also writes golang-migrate, goose, Flyway and Liquibase formats, so it can sit on top of another runner.

golang-migrate

golang-migrate pairs N_name.up.sql and N_name.down.sql files and runs them from a CLI or as a Go library, with drivers for Postgres, MySQL, SQLite, CockroachDB and more. It has no DSL to learn and is easy to embed in CI, though a failed migration marks the database dirty until you fix it and force the version, which is worth rehearsing before it happens in production.

goose

goose runs SQL migrations with -- +goose Up and -- +goose Down sections in one file, and also supports migrations written as Go functions for data backfills that need application logic. It can embed migrations in the binary with embed.FS.

It fits Go services that want to ship migrations inside the app. Like golang-migrate, it leaves zero-downtime patterns, such as adding a column before using it, to you.

dbmate

dbmate is a single binary that runs timestamped SQL files with -- migrate:up and -- migrate:down sections, independent of your application's language. It can wait for the database to become available and dump the resulting schema to a file for review.

It suits polyglot repositories and Docker-based setups where the migration step is a container that runs before the app.

Prisma Migrate

Prisma Migrate

Prisma Migrate generates SQL migration files from changes to schema.prisma, applies them with prisma migrate deploy, and keeps the generated client in step with the schema. You can edit the generated SQL before applying it.

It is tied to Prisma ORM and does not apply down migrations itself; you generate a down script with prisma migrate diff or reverse a change with a new migration.

Drizzle Kit

Drizzle Kit

Drizzle Kit compares your Drizzle schema in TypeScript with the previous snapshot and writes SQL migration files with drizzle-kit generate, or pushes the schema directly with drizzle-kit push for prototyping. The schema file doubles as the type source for queries.

Like Prisma Migrate, it fits teams already on the ORM, and it has no down migrations.

Good to know

Most migration incidents come from the change itself, not the tool: a column rename that breaks the running version, or an index build that locks a busy table. Expand-and-contract changes, CREATE INDEX CONCURRENTLY on Postgres, and running each migration against a copy of production data catch more problems than any rollback feature.

How to choose

Pick Flyway or Liquibase when the team is on the JVM or needs many database engines and audit-friendly change tracking. Pick Atlas when you want the schema described declaratively with CI linting, golang-migrate, goose or dbmate for plain SQL from a CLI, and Prisma Migrate or Drizzle Kit when you already use that ORM.

Pick Encore when you want migrations applied automatically on encore run and on each deploy to your own AWS or GCP account, with Atlas, Drizzle or Prisma generating the files if you prefer.

Frequently asked questions

What is the best database migration tool?

The right tool depends on the stack: Flyway and Liquibase suit JVM teams and many database engines, Atlas suits teams that want declarative schema-as-code with linting, golang-migrate, goose and dbmate suit plain SQL files run from a CLI, and Prisma Migrate or Drizzle Kit suit TypeScript teams already using that ORM.

Should I write down migrations?

Write them if you will actually run them, but do not rely on them as the main rollback plan. Down migrations cannot restore dropped data, and Flyway's own docs note that undo scripts assume the whole migration succeeded. Backwards-compatible changes plus backups are the safer default.

How do I run database migrations automatically on deploy?

With Encore, put numbered .up.sql files in the directory passed to new SQLDatabase or sqldb.NewDatabase. encore run applies them to the local Postgres, and each cloud deploy applies new migrations before the new version starts, aborting the deploy if one fails.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders