Open source · MIT · 14,218 stars on GitHub

Database migrations
that never drift.

Drift diffs your schema against your live database, then writes the migration for you — type-safe, reviewable SQL you can read before it runs. No more hand-edited up/down files, no more “works on my machine” drift between environments.

npm i -D drift-cli
  • Works with
  • PostgreSQL
  • MySQL
  • SQLite
  • PlanetScale
  • Neon
  • Turso

Quick start

Up and running in four commands

Point Drift at your database and let it write the first migration:

~/projects/orders-api — zsh
# install
npm i -D drift-cli

# scaffold drift.config.ts + connect your database
npx drift init

# diff your schema against the database and generate SQL
npx drift generate add_orders_table

# preview, then apply — every migration is plain reviewable SQL
npx drift status
npx drift push
You write the schema you want…
schema.ts
// schema.ts — describe the shape, not the diff
import { table, text, uuid, timestamp, int } from 'drift-cli';

export const orders = table('orders', {
  id:        uuid('id').primaryKey().default('gen_random_uuid()'),
  email:     text('email').notNull(),
  total:     int('total_cents').notNull(),
  status:    text('status').notNull().default('pending'),
  createdAt: timestamp('created_at').notNull().default('now()'),
});
…Drift writes the migration.
0007_add_orders_table.sql
-- migrations/0007_add_orders_table.sql  (generated by drift)
-- ↑ 1 table added · 0 columns dropped · safe to run

CREATE TABLE "orders" (
  "id"         uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  "email"      text NOT NULL,
  "total_cents" integer NOT NULL,
  "status"     text NOT NULL DEFAULT 'pending',
  "created_at" timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX "orders_email_idx" ON "orders" ("email");

Why Drift

A migration tool that gets out of your way

Drift owns one job — keeping your schema and your database in sync — and does it fast, safely, and in plain SQL you can read.

  • Fast

    A Rust diff engine reads your schema and introspects the database in one pass. Generating a migration on a 200-table schema takes under 40ms — fast enough to run on every save.

  • Type-safe

    Your schema is TypeScript, so column names, types and relations are checked at compile time. Rename a column and every query that referenced it lights up red in your editor.

  • Zero-config

    Run drift init and it detects your database from DATABASE_URL, picks the right dialect, and writes a one-file config. No adapters to wire up, no plugins to install.

  • Framework-agnostic

    Drift only owns your migrations — keep using Prisma, Drizzle, Kysely or raw SQL for queries. Postgres, MySQL, SQLite, and serverless drivers all speak the same commands.

  • Reviewable SQL

    Every migration is a plain .sql file you commit to git. Read it, edit it, comment on it in a PR. Nothing is hidden behind a binary format or an opaque migration table.

  • Safe rollbacks

    Each migration ships with a generated down step and a destructive-change guard. drift push --dry-run prints the exact plan; drift rollback reverts the last batch cleanly.

How it works

Three commands, every time

The whole workflow is connect, generate, apply. It looks the same on day one and on your thousandth migration — and identical on every machine that runs it.

  1. 01
    $ drift init

    Connect

    Drift reads DATABASE_URL, detects your dialect, and writes drift.config.ts plus an empty migrations folder. One command, no questions.

  2. 02
    $ drift generate

    Diff & generate

    Change your schema, then run generate. Drift compares the desired shape to the live database and emits a numbered, reviewable SQL migration with up and down steps.

  3. 03
    $ drift push

    Apply anywhere

    Run push in CI, on a teammate’s laptop, or against prod. Drift applies only the migrations that haven’t run yet and records them — every environment ends up identical.

Benchmarks

Built for the inner loop

Time to generate and apply a migration on a 50-table Postgres schema. Lower is better — measured on an M2 Air, median of 20 runs.

The bars compare tool overhead. The real win is the “~6 min” row: Drift removes the hand-written diff entirely.

We deleted 1,400 lines of hand-rolled migration scripts the week we adopted Drift. Generated SQL we can actually read in review, and prod and staging finally stopped drifting apart.
Priya Raman Staff Engineer, Northwind

Shipping migrations at