# The migration graph (/docs/orm/migrations/the-migration-graph) > For the complete Prisma documentation index, see [llms.txt](https://www.prisma.io/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL. You and a teammate each changed your Prisma contract on separate branches. The migration graph is how Prisma ORM applies both changes to every database after the branches merge. Location: ORM > Migrations > The migration graph Say you are Alice, and on your branch you add a `phone` field to your contract, the `contract.prisma` file that replaced `schema.prisma`. Bob adds an `avatar` field on his branch, and both branches merge the same afternoon. Your laptop, Bob's laptop, staging, and production each hold a different version of the database, and each one needs the merged version without losing work or repeating a change. Prisma ORM 7 keeps migrations as timestamped SQL directories and applies them in name order, so where a migration sits in the history is decided by its name. In Prisma ORM 8, each migration records the contract versions it starts and ends at instead, so migrations are linked to each other rather than ordered by time, and those links are the migration graph. ## When this matters [#when-this-matters] Most of the time you can build a whole app without thinking about the graph at all, because a single line of migrations needs no explaining. It is worth understanding when you are in one of these situations: * Two people, or two AI agents, change the contract on separate branches and merge. * You roll a database back to an earlier version of your contract and then forward again. * A database is several contract states out of date, after a fresh clone or on a long-lived staging database. ## The short version [#the-short-version] Each migration records the contract state it starts from and the state it ends at, so a migration is a link between two named versions of your contract rather than a step in a numbered queue. That is why branching, merging, and rolling back are all the same act: you plan one more migration with `npx prisma migration plan` and tell it which state to start from. > [!NOTE] > You probably need only these five commands > > Every time you change the contract, run `npx prisma contract emit`, which replaces `prisma generate`. Then plan a migration with `npx prisma migration plan --name `, and in development apply it with `npx prisma db migrate --advance-ref db`. `npx prisma migration graph` draws the whole history, and `npx prisma migration status` tells you which contract state a database matches and what `db migrate` would run next. > > Keep `--advance-ref db` on that command in development, so that your next `migration plan` starts from what you just applied instead of planning it again, as [The db ref](https://www.prisma.io/docs/orm/migrations/generating-a-migration#the-db-ref-skipping---from) explains. ## Terms [#terms-used-on-this-page] | Term | Meaning | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Contract** | Your `contract.prisma` file, compiled to `contract.json`. | | **Contract state** | One version of your contract, named by its hash. | | **Hash** | An identifier computed from the database layout your contract describes, not from the text of `contract.prisma`. The graph shows its first seven characters, like `4437973`. | | **Node** | A contract state, drawn as a `○` row in `migration graph` output. | | **Edge** | A migration, drawn as a `↑`, `↓`, or `⟲` row. Applying it changes the database from one node's state to the other's. | | **Marker** | The record in the database of which contract state it matches. Reading it does not check the tables. | | **Ledger** | The database's own list of every migration applied to it, and when each ran. | | **Ref** | A name for a contract state, like `prod`, stored as a file in `migrations/app/refs/`. | | **Contract reference** | The text a command accepts to name a contract state, such as a hash prefix or a ref name. [Contract references each command accepts](#contract-reference-forms) lists the forms. | | **`^`** | A migration directory name followed by `^`. It names the contract state before that migration, while the directory name alone names the state after it. | | **Contract space** | A separate migration history with its own directory in `migrations/`. Your app's is `migrations/app/`. Each [Prisma ORM extension package](https://www.prisma.io/docs/orm/extensions/using-extensions) that ships migrations, such as pgvector support, has its own, and one `db migrate` run applies all of them, as [Extension spaces](https://www.prisma.io/docs/orm/migrations/applying-a-migration#extension-spaces) shows. | ## How it works [#how-it-works] A migration on disk is a directory in `migrations/app/`, and what makes it part of a graph rather than an item in a list is that it names both ends of its own change. Its `ops.json` lists the operations, the steps it runs, such as adding a column, and [What a migration contains](https://www.prisma.io/docs/orm/migrations/how-migrations-work#what-a-migration-contains) lists the rest of its files. Its `migration.json` records the hash it starts `from` and the hash it ends at, `to`, so a migration that ends where another one starts is joined to it. To change what a migration does, edit its `migration.ts` and recompile with `node migrations/app//migration.ts`, as [Editing a migration](https://www.prisma.io/docs/orm/migrations/editing-a-migration) shows. A database with no **marker** counts as empty, so `db migrate` starts it from the first migration. If the database already has tables but no marker, Prisma ORM still counts it as empty, which is not what you want, so read [Baselines](#baselines) before you run anything against it. ## A worked example [#a-worked-example] Here is the situation from the top of the page, after Bob's branch merged first. [Name important states with refs](#name-important-states-with-refs) explains `@contract` and `(prod)`: #### bun ```bash bunx prisma migration graph ``` #### pnpm ```bash pnpm prisma migration graph ``` #### yarn ```bash yarn prisma migration graph ``` #### npm ```bash npx prisma migration graph ``` ```text │ migrations: migrations ○ e377d00 @contract │↑ 20260922T0627_alice_merge 1a76a3c → e377d00 1 ops ○ │ 5e1f082 │↑│ 20260922T0627_alice_add_phone 4437973 → 5e1f082 1 ops │ ○ 1a76a3c (prod) │ │↑ 20260922T0627_bob_add_avatar 4437973 → 1a76a3c 1 ops │─╯ ○ 4437973 │↑ 20260922T0626_init ∅ → 4437973 3 ops ○ ∅ 1 space(s), 5 contract(s), 4 migration(s) ``` Read it from the bottom up, because the earliest state is the bottom row and every row above it is a later one. Each `↑` row shows a migration's directory name, its start and end hashes, and its operation count. The lines on the left are drawn in columns, one column for each branch of the history. Where a row belongs to one branch, the other branch's column shows a `│`, so you can follow that column up the page. The `│─╯` row shows where the two columns split: Bob's migration, in the right-hand column, and Alice's, in the left-hand column, both start from `4437973`. To print a key to the symbols in the rows, run `npx prisma migration graph --legend`. The key explains `○`, the arrows, `∅`, the `@contract` and `@db` labels, and ref labels such as `(prod)`. It also explains `✓`, which means applied, and `⧗`, which means pending, and you see those two in `migration status` output. From an empty database (`∅`), `init` produces contract state `4437973`. Alice's migration starts there and produces `5e1f082`, and Bob's starts from the same state and produces `1a76a3c`, which is why the drawing splits in two. Bob merged first, so `main` now points the `prod` ref at `1a76a3c`, and production will be migrated there. Alice's branch still holds a migration that starts from `4437973`, which is no longer the head. After Alice rebases onto `main`, her `contract.prisma` holds both fields, `phone` and `avatar`, and production is at `1a76a3c`, where `prod` points. So the migration production needs is one from `prod` to that merged contract. If git reports a conflict in `contract.prisma`, `contract.json`, or `contract.d.ts`, she resolves it in `contract.prisma` and runs `npx prisma contract emit`, which rewrites the other two. She accepts `main`'s `refs/prod.json` as it is, and if `refs/db.json` conflicts too, she can take either side, because the `db update` in the last step below points it at the merged state. Then she plans one migration from `prod`: #### bun ```bash bunx prisma migration plan --name alice_merge --from prod ``` #### pnpm ```bash pnpm prisma migration plan --name alice_merge --from prod ``` #### yarn ```bash yarn prisma migration plan --name alice_merge --from prod ``` #### npm ```bash npx prisma migration plan --name alice_merge --from prod ``` That is `alice_merge` in the drawing, from `1a76a3c` to the merged contract `e377d00`, and it adds `phone` to a database that already has `avatar`. `migration plan` always ends at whatever is in `contract.json`, which now holds the merged contract. If her old `migration.ts` had operations she wrote by hand, such as a `dataTransform`, she copies them into the new file and recompiles it, because the planner derives the schema changes from the contract but cannot carry over what she wrote. Her old migration, `alice_add_phone`, can stay on disk or be deleted. Either way it never runs, because `db migrate` follows the path from the database's marker to its target, and `5e1f082` is not on the path from `prod` to `@contract`, so it cannot run out of order. Her own development database is the one database that is at `5e1f082`, and the quickest way to bring it to the merged contract is `npx prisma db update`, which changes a development database directly and points the `db` ref at the new state, so her next plan starts from the right place. ## What happens when you run db migrate [#what-happens-when-you-run-db-migrate] `npx prisma db migrate` works out for itself which migrations your database still needs. It starts from the state in the marker and runs the migrations on the path to its target, which is `contract.json` unless `--to` names a contract state instead. If an operation fails, the run stops there, and [When something goes wrong](https://www.prisma.io/docs/orm/migrations/applying-a-migration#when-something-goes-wrong) explains how to re-run while [Recovery](https://www.prisma.io/docs/orm/migrations/rollbacks-and-recovery#recovery-when-a-migration-fails-partway) explains what to do next. Once your history has branches, more than one path can lead to the target, so `db migrate` has to pick one. It takes the path with the fewest migrations, and on a tie the migration with the earlier `createdAt` in its `migration.json`. That is also why a migration whose end state leads nowhere is never run: a database at `4437973` runs `bob_add_avatar` and then `alice_merge`, and never `alice_add_phone`, because no path through it reaches the target. The choice does not change where you end up, because both paths end at the same contract state, and `db migrate` checks the tables against that state before it updates the marker. To see the path it picked before anything runs, use `npx prisma db migrate --show`. When no chain of migrations leads from the marker to the target, the run fails with an error whose `code` is `MIGRATION.PATH_UNREACHABLE`, and that usually means one of two things. Either `--to` names a state you did not intend, which is worth checking first, or the migration you need has not been planned yet. In the second case, plan it from the hash the marker holds with `npx prisma migration plan --from --name `, and to find that hash run `npx prisma migration status`, which prints it next to its `@db` label. ## Inspecting the graph [#inspecting-the-graph] | Question you have | Command | Needs a database? | | ----------------------------------------------------------------------------------------- | ----------------------------- | ----------------- | | What does the whole graph look like? | `npx prisma migration graph` | No | | Which migration directories exist on disk? | `npx prisma migration list` | No | | Was an `ops.json` or `migration.json` edited by hand, or does a ref name a missing state? | `npx prisma migration check` | No | | Which contract state does my database match, and what would `db migrate` run next? | `npx prisma migration status` | Yes | | What has actually been applied, and when? | `npx prisma migration log` | Yes | `migration log` reads the **ledger**, so it tells you what actually ran rather than what should have run, and a rollback appears there as one more applied migration instead of erasing anything. Run `migration check` before you commit a migration you edited, and after you move a ref. It catches an `ops.json` or `migration.json` that was changed by hand, and a ref naming a state that does not exist, and it needs no database connection. A deploy pipeline does not need it: `db migrate --to ` refuses a hand-edited migration file on its own. See [Reviewing what you planned](https://www.prisma.io/docs/orm/migrations/generating-a-migration#reviewing-what-you-planned) for its exit codes. ## Name important states with refs [#name-important-states-with-refs] Hashes are hard to remember and hard to talk about, so Prisma ORM lets you give the states that matter a name of your own. A **ref** is that name: you create one and point it at a state with `npx prisma migration ref set`, and then you pass the name instead of a hash, for example to `db migrate --to`. The name `prod` below is only an example: #### bun ```bash bunx prisma migration ref set prod 1a76a3c bunx prisma migration ref list bunx prisma db migrate --to prod ``` #### pnpm ```bash pnpm prisma migration ref set prod 1a76a3c pnpm prisma migration ref list pnpm prisma db migrate --to prod ``` #### yarn ```bash yarn prisma migration ref set prod 1a76a3c yarn prisma migration ref list yarn prisma db migrate --to prod ``` #### npm ```bash npx prisma migration ref set prod 1a76a3c npx prisma migration ref list npx prisma db migrate --to prod ``` A ref named for an environment, such as `prod` or `staging`, names the contract state your deploy pipeline will migrate that environment to. It is a promise the repository makes, not a record of what is deployed; the marker in the database records that. Point it at the new state when a change merges to `main`, and have the pipeline run `db migrate --to prod` so it never applies more than the repository has promised. `ref set` points a ref at a contract state, and [the table below](#contract-reference-forms) lists the forms it accepts. One of them is `^`, a migration directory name followed by `^`. It names the contract state before that migration, while the directory name alone names the state after it. Once the ref exists, `db migrate --to prod` applies migrations until the database matches the state `prod` names, and the database it changes is the one `prisma.config.ts` connects to, unless you pass a connection string with `--db`. Some states you only need to refer to once, so Prisma ORM reserves a few tokens that start with `@`. Each names a contract state without creating a ref: * `@contract`: the contract in `contract.json`. * `@db`: the contract state in the marker of the database you are connected to. The `db` ref is a file, so it can name a different state. * `@empty`: the empty database, before any migration. ### Contract references each command accepts [#contract-reference-forms] Not every command accepts every form. This table lists what each one accepts: | Command and option | Accepts | | --------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `migration plan --from` | a hash, a hash prefix, a ref name, a migration directory name, `^`, or `@empty` | | `migration plan --to` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | | `migration new --from` | a hash, or a prefix of one, that an existing migration ends at | | `migration ref set ` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | | `migration status --from`, `--to` | a hash, a hash prefix, a ref name, a migration directory name, `^`, `@contract`, `@db`, or `@empty` | | `db migrate --to`, and `--from` with `--show` | a hash, a hash prefix, a ref name, a migration directory name, `^`, `@contract`, `@db`, or `@empty` | | `db update --to` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | | `db sign [contract]`, `--contract` | a hash, a hash prefix, a ref name, a migration directory name, or `^` | A hash prefix is the first 6 or more characters of a hash, and it must match exactly one contract state. None of these options accepts a file path. The table lists only what you can pass. To read what an option does, open the command's page in the [CLI reference](https://www.prisma.io/docs/cli), such as [`migration status`](https://www.prisma.io/docs/cli/migration-status). For example, to see the path from the contract you have now to the state `prod` names, without changing anything, run `npx prisma db migrate --show --from @contract --to prod`. ## What the graph gives you [#what-the-graph-gives-you] ### Parallel work without ordering conflicts [#parallel-work-without-ordering-conflicts] Two branches can plan migrations at the same time without either one knowing about the other, because nothing about a migration depends on when it was planned. Cleaning up afterwards is one `migration plan --from prod`, as [A worked example](#a-worked-example) shows. ### History you can trust [#history-you-can-trust] A migration only ever runs against a database that matches the state it starts `from`. Before any operation runs, `db migrate` checks that the marker is a state in your migration history and stops if it is not. That check reads only the marker, not the tables. `db migrate` checks the tables only after it has run operations, and never when it has nothing to run. To check the tables yourself, run [`npx prisma db verify --schema-only`](https://www.prisma.io/docs/cli/db-verify), which compares the tables with your contract and skips the marker check. That marker check is also what you run into after using `npx prisma db update`, which, like Prisma ORM 7's `db push`, changes a database to match the contract without writing a migration. Because the contract it applied is one that no migration ends at, your next `db migrate` run stops at the check. [Drift](https://www.prisma.io/docs/orm/migrations/rollbacks-and-recovery#drift-when-the-database-isnt-where-migrations-left-it) explains what to do next. ### Rollback as one more migration [#rollback-as-a-normal-move] Undoing a change is not a special mode you switch into, because a migration can go backwards, from a later contract state to an earlier one, and you plan and apply it like any other migration. [Rollbacks and recovery](https://www.prisma.io/docs/orm/migrations/rollbacks-and-recovery) shows the commands, including reverting your contract before you apply the rollback. ### More than one shape of history [#more-than-one-shape-of-history] Straight lines, branches, and branches that join again all use the same commands, so there is nothing new to learn the first time your history stops being a straight line. ## Baselines [#baselines] The word "baseline" turns up in several different places, and which one you are looking at depends on where you saw it: * **A kind of migration.** A first migration from an empty database to a contract state, such as `init` above. * **A label in command output.** `(baseline)` in `migration plan` output means the migration starts from an empty database. * **A Prisma ORM 7 task.** What Prisma ORM 7 called baselining, marking an existing database as already migrated, is `npx prisma db sign` in Prisma ORM 8. Reach for [`npx prisma db sign`](https://www.prisma.io/docs/cli/db-sign) when a database has no marker and its tables already match your contract. It checks the tables, writes the marker, and points the `db` ref at the signed contract. Signing alone is not enough to start migrating, though, because `db migrate` refuses a signed database until a migration in your history ends at the signed state. Your next `migration plan` writes that one for you, because the `db` ref now names the signed state; [The automatic baseline](https://www.prisma.io/docs/orm/migrations/generating-a-migration#the-automatic-baseline) explains what it writes. For a database Prisma ORM 7 migrated, follow [Transfer migration ownership](https://www.prisma.io/docs/guides/upgrade-prisma-orm/postgresql#4-transfer-migration-ownership) instead. ## Database-specific details [#database-specific-details] Nothing above changes with your database, because the graph and the commands are the same on every database that [Prisma ORM 8 supports](https://www.prisma.io/docs/orm/supported-databases). What does differ is where the marker and ledger are stored, and how much of a failed `db migrate` run is left behind, which [When something goes wrong](https://www.prisma.io/docs/orm/migrations/applying-a-migration#when-something-goes-wrong) covers. * **PostgreSQL**: the marker is the `prisma_contract.marker` table and the ledger is the `prisma_contract.ledger` table. * **MongoDB**: the marker and ledger are documents in a `_prisma_migrations` collection, which is new in Prisma ORM 8 because Prisma ORM 7 had no migrations on MongoDB. ## Adding a migration you write yourself [#adding-a-migration-you-write-yourself] `npx prisma migration new` writes an empty migration for a change you write yourself, such as a data update. The migration always ends at the contract state in your current `contract.json`. Without `--from`, it starts where `migration plan` would: at the `db` ref, or at an empty database when there are no migrations and no `db` ref yet. When there are migrations but no `db` ref, it stops and asks for `--from`. [`migration new`](https://www.prisma.io/docs/cli/migration-new) lists every case. Unlike the `--from` of `migration plan`, the `--from` of `migration new` takes only a contract hash that an existing migration ends at, which is the `to` hash in that migration's `migration.json`. You can shorten the hash to its first characters, such as the 7 that `migration graph` shows, as long as they match only one migration's `to` hash. It does not take a ref name, a migration directory name, or an `@` name such as `@db`. [Contract references each command accepts](#contract-reference-forms) compares it with the other commands. So to start from `e377d00` in the drawing above, run `npx prisma migration new --name backfill --from e377d00`. Because `e377d00` is also the `@contract` state, that migration starts and ends at the same state, which is what a data-only migration does. ## Release-candidate limitations [#release-candidate-limitations] The graph itself, the way `db migrate` chooses which migrations to run, refs, the marker, and the ledger all work today. These are not built yet: * **No squash.** You cannot yet collapse a long chain of migrations into one. * **No split.** You cannot yet break one large migration into smaller ones after the fact. ## Common tasks [#common-tasks] | Task | Command | | ------------------------------------------------------- | ------------------------------------------------------------------ | | Create a migration after you change the contract | `npx prisma migration plan --name ` | | Plan the migration production needs after a merge | `npx prisma migration plan --name --from prod` | | Apply migrations to your development database | `npx prisma db migrate --advance-ref db` | | See the whole graph | `npx prisma migration graph` | | See which contract state a database matches | `npx prisma migration status` | | Apply migrations until a database matches a named state | `npx prisma db migrate --to prod` | | Name a contract state `prod` | `npx prisma migration ref set prod ` | | List the refs you have named | `npx prisma migration ref list` | | Plan a rollback of the migration in `` | `npx prisma migration plan --from --to ^ --name ` | | Apply a rollback migration you planned | `npx prisma db migrate --to ` | | Check migration files and refs offline | `npx prisma migration check` | ## Prompt your coding agent [#prompt-your-coding-agent] Projects created with `npm create prisma@latest` include the [Prisma ORM skills](https://www.prisma.io/docs/ai/tools/skills#available-skills-for-prisma-8) for your coding agent. In an existing project, run `npx prisma skills sync`. Ask your agent to: * "Draw the migration graph for this project and explain the branches." * "Which contract state is the `prod` ref pointing at, and does the database match it?" * "Two feature branches both added migrations. Draw the graph and plan the one migration production needs from the `prod` ref." ## See also [#see-also] * [How migrations work](https://www.prisma.io/docs/orm/migrations/how-migrations-work): what a migration contains, and how you plan, review, and apply one * [Applying a migration](https://www.prisma.io/docs/orm/migrations/applying-a-migration): running `db migrate` in development and production * [Studio with Prisma ORM](https://www.prisma.io/docs/studio/prisma-next): browse the same ledger visually in Prisma Studio, one entry per migration * [Rollbacks and recovery](https://www.prisma.io/docs/orm/migrations/rollbacks-and-recovery): planning and applying a migration back to an earlier state ## Related pages - [`Applying a migration`](https://www.prisma.io/docs/orm/migrations/applying-a-migration): The db migrate command applies the migrations you planned, until your database matches your contract, with a preview, checks on every operation, and safe re-runs. - [`Editing a migration`](https://www.prisma.io/docs/orm/migrations/editing-a-migration): A migration is TypeScript you own. Fill in backfills, reorder steps, or write raw SQL, then recompile it with one command. - [`Generating a migration`](https://www.prisma.io/docs/orm/migrations/generating-a-migration): Turn a change to your contract into a migration you can review, with the migration plan command. - [`How migrations work`](https://www.prisma.io/docs/orm/migrations/how-migrations-work): Change your contract, plan a migration, review it, apply it. Operations can check the database before and after they run. - [`Rollbacks and recovery`](https://www.prisma.io/docs/orm/migrations/rollbacks-and-recovery): Rolling back is one more migration that makes the database match an earlier contract state. Recovery is fixing a failed migration and running it again.