Prisma Migrate

Prisma Fundamentals

Chapter 4 · Prisma Migrate

Your schema describes what the database should look like. Prisma Migrate gets it there: it compares the schema with the database, writes the SQL needed to close the gap, and keeps a history of every change so that other developers, test servers and production can all be brought to exactly the same state.

What a Migration Is

A migration is a file of SQL that changes the database structure — creating a table, adding a column, adding an index. Prisma stores each one in its own folder, in the order they were made:

prisma/ ├── schema.prisma └── migrations/ ├── 20260927093000_init/ │ └── migration.sql ├── 20260927101500_blog_schema/ │ └── migration.sql └── migration_lock.toml # records which database type the migrations are for

Prisma also keeps a table in your database, _prisma_migrations, listing which migrations have been applied there. Comparing that table with the folders tells it what still needs to run.

Commit your migrations
The migrations folder is part of your project's source code. Commit it, along with the schema, so that everyone applies the same changes in the same order. Never edit a migration that has already been applied somewhere else.

migrate dev: The Development Workflow

# 1. Edit schema.prisma, e.g. add a field to Post: # excerpt String? # 2. Create and apply a migration npx prisma migrate dev --name add-post-excerpt # 3. Regenerate the client (Prisma 7 no longer does this for you) npx prisma generate

migrate dev does several things in one command:

  1. Replays your existing migrations in a temporary shadow database, to check that the history still works and that your real database hasn't been changed behind Prisma's back (drift).
  2. Compares the result with your schema, and writes a new migration for any differences.
  3. Applies any unapplied migrations to your development database.
Prisma 7: generate and seed are now separate
In earlier versions migrate dev also regenerated the client and ran your seed script. Prisma 7 removed both, so you run npx prisma generate yourself, and npx prisma db seed when you want seed data (Prisma Intermediate/Advanced, Chapter 4). Some pages in Prisma's own documentation still describe the old behaviour, so trust the Prisma 7 upgrade guide if they disagree.

The shadow database

The shadow database is created and deleted automatically each time. With SQLite this needs no setup. With PostgreSQL or MySQL, the database user needs permission to create databases. If it can't have that (common on hosted databases), create an empty database yourself and point Prisma at it in the config file:

import "dotenv/config"; import { defineConfig, env } from "prisma/config"; export default defineConfig({ schema: "prisma/schema.prisma", migrations: { path: "prisma/migrations" }, datasource: { url: env("DATABASE_URL"), shadowDatabaseUrl: env("SHADOW_DATABASE_URL"), }, });

When a Change Would Lose Data

Some schema changes can't be applied to existing rows safely. Adding a required column with no default to a table that already has rows, for example, would leave those rows without a value. Dropping a column deletes its data. In these cases migrate dev warns you, and may offer to reset the development database.

ChangeWhy it's riskySafer approach
Add a required columnExisting rows have no valueGive it a @default, or add it as optional first
Remove a column or tableIts data is deletedMake sure nothing needs the data first; back it up
Rename a fieldPrisma sees "drop the old, add a new" and would lose the dataEdit the migration SQL to rename instead (below)
Add @uniqueFails if duplicates already existClean up duplicates first

Editing a Migration Before It Runs: --create-only

Prisma can't tell a rename from a delete-and-add. When you rename content to body, the generated SQL drops content and adds an empty body. To keep the data, create the migration without applying it, fix the SQL, then apply it:

# 1. Create the migration file, but don't run it npx prisma migrate dev --create-only --name rename-content-to-body # 2. Edit prisma/migrations/<timestamp>_rename-content-to-body/migration.sql, # replacing the generated DROP/ADD lines with: ALTER TABLE "Post" RENAME COLUMN "content" TO "body"; # 3. Apply it npx prisma migrate dev
Or avoid the rename in the database
If only your code needs the new name, use @map (Chapter 3): rename the field in the schema to body and add @map("content"). The column keeps its old name and no migration is needed.

Other Migrate Commands

CommandWhat it doesWhere to use it
migrate devCreates and applies migrations; checks for driftDevelopment only
migrate resetDeletes the database, recreates it, and reapplies every migrationDevelopment only — it destroys data
migrate deployApplies pending migrations and nothing else: no new migrations, no drift checks, no resets, no shadow databaseProduction, staging and CI
migrate statusShows which migrations have and haven't been appliedAnywhere
db pushMakes the database match the schema directly, with no migration filesQuick prototyping only
Never run migrate dev or reset on production
Both are designed for disposable development databases and can delete data. Production only ever gets migrate deploy, which applies the reviewed, committed migrations and refuses to do anything else. Prisma Intermediate/Advanced, Chapter 8, covers production migrations in detail.
db push vs. migrate
db push is handy while you're sketching a schema and don't care about history. But it leaves no record of what changed, so it can't be replayed on another machine. Switch to migrations as soon as anyone else, or any real data, depends on the database.

Hands-On Exercises

Exercise 1

Add an optional excerpt field to Post and create a migration for it. Then run npx prisma migrate status and explain its output. What would happen if you forgot to run prisma generate afterwards?

📄 View solution
Exercise 2

Create a post with some content. Rename the content field to body in a way that keeps the post's text, and prove the data survived.

📄 View solution
Exercise 3

A teammate suggests running npx prisma migrate dev on the production server "to be safe." Explain what could go wrong, and what should happen instead.

📄 View solution

Chapter 4 Quick Reference

  • A migration is a SQL file in prisma/migrations/; the _prisma_migrations table records which have run; commit the folder
  • migrate dev --name x checks for drift in a shadow database, creates a migration from schema changes, and applies it
  • In Prisma 7, run prisma generate (and prisma db seed) yourself afterwards
  • Set shadowDatabaseUrl in the config file when the database user can't create databases
  • Watch for data-losing changes: required columns, drops, renames, new unique constraints
  • --create-only lets you edit the SQL (for example to rename a column) before applying it
  • migrate reset and migrate dev are for development only; production uses migrate deploy
  • migrate status shows what's applied; db push is for throwaway prototyping