Overview
Prisma Migrate generates and applies SQL migration files derived from schema.prisma. Two commands do the work: migrate dev for local authoring and migrate deploy for CI and production. Each migration is a named SQL file stored in prisma/migrations/. Treat migration files as append-only once they have been applied to any environment. For the broader migration contract, see migrations.
Use migrate dev to author and migrate deploy to ship
The commands have different purposes and different risk profiles.
# Local development: generate the next migration, apply it, regenerate the client.
npx prisma migrate dev --name add_product_sku
# CI and production: apply pending migrations in order, no prompts, no client regen.
npx prisma migrate deploymigrate devuses a shadow database to calculate the diff between the current state andschema.prisma. It may prompt you to reset the local database if the history is inconsistent.migrate deployapplies any migration that is not yet recorded in the_prisma_migrationstable. It never creates new migrations. Run it before the new application binary takes traffic.- Never run
migrate devin production. It touches the shadow database and can reset state.
Understand the shadow database
migrate dev creates a temporary “shadow” database, replays all existing migrations on it, and compares that state to schema.prisma to compute the next migration’s SQL.
- Prisma needs
CREATE DATABASEandDROP DATABASEpermissions for the shadow database. Grant them on the migration user. - Hosted databases that disallow those permissions (PlanetScale, some Supabase configs) require you to set
shadowDatabaseUrlexplicitly indatasource db. - If the shadow database diverges (for example, you edited a migration file),
migrate devdetects the drift and warns you. Resolve it before authoring the next migration.
Baseline an existing database
When you add Prisma Migrate to a database that already has a schema, you must baseline it. Otherwise, migrate deploy will try to run the initial migration and fail on existing tables.
# 1. Create the migrations folder without running any SQL.
npx prisma migrate diff \
--from-empty \
--to-schema-datasource prisma/schema.prisma \
--script > prisma/migrations/0001_initial/migration.sql
# 2. Mark that migration as applied without executing it.
npx prisma migrate resolve --applied 0001_initial- After baselining, every subsequent
migrate devwill diff against the current DB state and produce correct incremental migrations. - Run the baseline step on every environment that already has the schema. A new environment (staging, fresh CI) can simply run
migrate deployand the baseline migration executes as normal SQL.
Detect and fix drift
Drift occurs when the database schema no longer matches what the migration history would produce. Common causes: a DBA ran ALTER TABLE by hand, a migration was partially applied, or someone edited a shipped migration file.
# Check for drift between the DB and the migration history.
npx prisma migrate diff \
--from-migrations prisma/migrations \
--to-schema-datasource prisma/schema.prisma \
--exit-code- A non-zero exit means the database is ahead of or behind the migration history.
- To fix drift in a development environment, reset:
npx prisma migrate reset. This drops and recreates the DB. - In production, write a corrective migration that brings the DB in line with what the history expects. Do not edit shipped migrations.
Squash migrations when the history becomes unwieldy
Long migration histories slow down CI shadow-database replay and migrate reset. Squash by merging old migrations into a single baseline.
- Export the current production schema with
pg_dump --schema-only. - Replace all existing migration folders with a single
0001_baseline/migration.sqlcontaining the dump. - Mark it applied in every environment with
prisma migrate resolve --applied 0001_baseline. - New migrations continue from
0002_....
- Squash only migrations that are applied everywhere. Never squash a migration that is pending in any environment.
- Squashing does not change the live schema. It only compresses the history Prisma uses for diffing.
Never edit a shipped migration
A migration is “shipped” as soon as any environment has applied it and recorded it in _prisma_migrations. Editing it after the fact breaks the shadow-database replay and may cause migrate deploy to error or skip rows.
- Write a follow-up migration for any correction.
- Use
-- prisma-migrate-disable-txat the top of a migration file when the SQL cannot run inside a transaction (for example,CREATE INDEX CONCURRENTLYon hot tables). - Commit the generated SQL file alongside the
schema.prismachange. Reviewers should read the SQL diff, not infer it from the schema diff. See prisma-schema for model conventions.