Skip to main content
Prisma Documentation Docs

Search documentation

Type to search this documentation.

On this pageOverview

Schema management in teams

When a team works on one schema, two people change it at the same time. In Prisma ORM, migrations form a graph rather than a numbered list, so parallel changes do not force anyone to rename files or rebuild history. This guide shows how that works day to day: what to commit, how to incorporate a teammate's migration, and how to resolve the case where two branches planned a migration from the same starting point and both merged.

Every command and every output below was run against a Git repository with three checkouts (two teammates and you), each with its own local PostgreSQL database.

  • Node.js 24 or later
  • A Prisma ORM project with a contract and at least one migration (the PostgreSQL quickstart gives you one)
  • A PostgreSQL database per developer, reachable as DATABASE_URL
  • Basic familiarity with Git branches and merges
  • The migration loop: contract emit, migration plan, db migrate

To delegate the pull-and-apply part of this guide to your coding agent, copy the prompt below and hand it over:

with
Bring my local database up to date with the migrations on this branch using Prisma ORM, following https://www.prisma.io/docs/guides/database/schema-changes.md.

1. Run `npx prisma migration status` and tell me what is pending. If it reports "Up to date", stop.

2. If it warns that there is no migration path from the database state to the contract, the graph has two branch tips. Run `npx prisma migration graph`, then plan one merge migration from each tip with `npx prisma migration plan --from <migration-dir> --name merge_<other-change>`, and show me both DDL previews before continuing.

3. Apply with `npx prisma db migrate --advance-ref db`, then run `npx prisma migration check` and `npx prisma db verify`.

4. If `migration plan` fails with MIGRATION.PLAN_ORIGIN_UNKNOWN, do not delete any migration directory. Find the contract state the database is on in the `npx prisma migration status` output, pass that hash with `--from`, and show me the error text. If you cannot tell which state the database is on, stop and ask me.

Each migration directory records the contract state it starts from and the state it ends at, to, as hashes in its migration.json. Those links are the migration history. The timestamp in the directory name is for humans; nothing depends on it. That is why two developers can plan migrations from the same state on separate branches and merge without renaming anything. The migration graph explains the model in full.

Three commands answer the questions a team asks most:

Question Command Needs a database?
What does the history look like? npx prisma migration graph No
Where is my database, and what is pending? npx prisma migration status Yes
Do the migration files on this branch hold together? npx prisma migration check No

Commit everything Prisma ORM needs to rebuild a database from scratch:

  • src/prisma/contract.prisma, the schema you author
  • src/prisma/contract.json and src/prisma/contract.d.ts, the emitted contract (generated, but committed; orm init marks them linguist-generated in .gitattributes)
  • migrations/app/, every migration directory: migration.ts, ops.json, and migration.json together
  • migrations/snapshots/, the contract snapshots migrations are typed against
  • migrations/app/refs/, named refs, including the db ref described next
  • prisma.config.ts

Do not commit .env. orm init already lists it in .gitignore.

migration plan is offline. It never asks the database which contract state it matches, so you have to tell it which state to plan from. It resolves the origin in this order: an explicit --from, otherwise the ref named db in migrations/app/refs/db.json, otherwise the empty database. Keep the db ref pointing at the state your local database matches by applying with --advance-ref db:

bunx prisma db migrate --advance-ref db
Bash
pnpm prisma db migrate --advance-ref db
Bash
yarn prisma db migrate --advance-ref db
Bash
npx prisma db migrate --advance-ref db

Do that every time you apply, and every plan chains from the right place without flags. Section 3 shows what happens when it cannot.

Do that every time you apply, and every plan chains from the right place without flags. Section 3 shows what happens when it cannot.

The project was created with npx prisma@latest orm init --yes --target postgres --authoring psl and has this contract:

title="src/prisma/contract.prisma"
// use prisma-8

model User {

  id        Int      @id @default(autoincrement())

  email     String   @unique

  username  String?

  name      String?

  posts     Post[]

  createdAt TimestamptzString @default(now())

  updatedAt temporal.updatedAtString()

}

model Post {

  id        Int      @id @default(autoincrement())

  title     String

  content   String?

  author    User     @relation(fields: [authorId], references: [id])

  authorId  Int

  createdAt TimestamptzString @default(now())

  updatedAt temporal.updatedAtString()

}

Its first migration was planned and applied on main with:

bunx prisma migration plan --name init

bunx prisma db migrate --advance-ref db
Bash
pnpm prisma migration plan --name init
pnpm prisma db migrate --advance-ref db
Bash
yarn prisma migration plan --name init
yarn prisma db migrate --advance-ref db
Bash
npx prisma migration plan --name init
npx prisma db migrate --advance-ref db
no-copy
✔ Applied 1 migration(s) (6 operation(s)) across 1 contract space(s)

App space
├─ Create schema "public"
├─ Create table "Post"
├─ Create table "User"
├─ Add unique constraint on "User" (email)
├─ Create index "Post_authorId_idx_e47547ed" on "Post"
├─ Add foreign key "Post_authorId_fkey" on "Post"
└─ marker 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e

✔ Advanced ref "db" → 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e
→ Check every space against the database: {bin} migration status

The {bin} in the hint is the CLI's placeholder for however you invoked it. Read it as npx prisma migration status. Every developer clones this repository, points DATABASE_URL in their .env at their own database, and runs npx prisma db migrate once to bring it to the same state.

✔ Applied 1 migration(s) (6 operation(s)) across 1 contract space(s)

App space

├─ Create schema "public"

├─ Create table "Post"

├─ Create table "User"

├─ Add unique constraint on "User" (email)

├─ Create index "Post_authorId_idx_e47547ed" on "Post"

├─ Add foreign key "Post_authorId_fkey" on "Post"

└─ marker 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e

✔ Advanced ref "db" → 91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e

→ Check every space against the database: {bin} migration status

The {bin} in the hint is the CLI's placeholder for however you invoked it. Read it as npx prisma migration status. Every developer clones this repository, points DATABASE_URL in their .env at their own database, and runs npx prisma db migrate once to bring it to the same state.

When a teammate merges a schema change, it arrives as three things: an edited contract.prisma, the re-emitted contract.json and contract.d.ts, and a new migration directory. Pull them, then ask Prisma which contract state your database matches:

git pull
title="bun"
bunx prisma migration status
pnpm
pnpm prisma migration status
yarn
yarn prisma migration status
npm
npx prisma migration status

If nothing changed, you see the whole history marked applied:

○   91e7f9f  @contract @db (db)

│↑  20260910T1543_init         ∅ → 91e7f9f  6 ops  ✓ applied

○   ∅

✔ Up to date

@db marks the contract state your database matches, @contract the emitted contract, and (db) the state the db ref names. When migrations are pending, the tree flags each one with ⧗ pending and a summary line tells you how many. Apply them and update the db ref in one step:

title="bun"
bunx prisma db migrate --advance-ref db
pnpm
pnpm prisma db migrate --advance-ref db
yarn
yarn prisma db migrate --advance-ref db
npm
npx prisma db migrate --advance-ref db

There is no generate step after applying: your typed client reads contract.json, which you just pulled.

The rest of this guide follows three developers changing the same contract. Ania adds a favoriteColor field, Javier adds a Tag model, and you add a bestPacmanScore field:

title="Before"
model User {

  id        Int      @id @default(autoincrement())

  email     String   @unique

  username  String?

  name      String?

  posts     Post[]

  createdAt TimestamptzString @default(now())

  updatedAt temporal.updatedAtString()

}
After
model User {  id              Int      @id @default(autoincrement())  email           String   @unique  username        String?  name            String?  favoriteColor   String? // Added by Ania  bestPacmanScore Int?    // Added by you  posts           Post[]  createdAt       TimestamptzString @default(now())  updatedAt       temporal.updatedAtString()}// Added by Javiermodel Tag {  tagName     String @id  tagCategory String}

Ania and Javier both branch from the same commit on main, where the db ref points at the init state.

On her branch, Ania adds the field:

title="src/prisma/contract.prisma"
model User {

  /* ... */

  favoriteColor String?

}

Then she emits, plans, and applies to her own database:

bunx prisma contract emit

bunx prisma migration plan --name add_favorite_color
Bash
pnpm prisma contract emit
pnpm prisma migration plan --name add_favorite_color
Bash
yarn prisma contract emit
yarn prisma migration plan --name add_favorite_color
Bash
npx prisma contract emit
npx prisma migration plan --name add_favorite_color
no-copy
✔ Planned 1 operation(s)

migrations/app/20260910T1546_add_favorite_color
└─ Add column "favoriteColor" to "User"

from:       91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e
to:         b29af3990b528c7a67809a2ac609305c59aa9c0af1ed0e4591cc0a727b38b1d1
app space:  migrations/app/20260910T1546_add_favorite_color

ℹ DDL preview

ALTER TABLE "public"."User" ADD COLUMN "favoriteColor" text;

The from: line is the init state, taken from the db ref. She applies and commits:

✔ Planned 1 operation(s)

migrations/app/20260910T1546_add_favorite_color

└─ Add column "favoriteColor" to "User"

from:       91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e

to:         b29af3990b528c7a67809a2ac609305c59aa9c0af1ed0e4591cc0a727b38b1d1

app space:  migrations/app/20260910T1546_add_favorite_color

ℹ DDL preview

ALTER TABLE "public"."User" ADD COLUMN "favoriteColor" text;

The from: line is the init state, taken from the db ref. She applies and commits:

bunx prisma db migrate --advance-ref db
Bash
pnpm prisma db migrate --advance-ref db
Bash
yarn prisma db migrate --advance-ref db
Bash
npx prisma db migrate --advance-ref db
no-copy
✔ Applied 1 migration(s) (1 operation(s)) across 1 contract space(s)

App space
├─ Add column "favoriteColor" to "User"
└─ marker b29af3990b528c7a67809a2ac609305c59aa9c0af1ed0e4591cc0a727b38b1d1

✔ Advanced ref "db" → b29af3990b528c7a67809a2ac609305c59aa9c0af1ed0e4591cc0a727b38b1d1
Bash
git add -A
git commit -m "Add User.favoriteColor"
✔ Applied 1 migration(s) (1 operation(s)) across 1 contract space(s)

App space

├─ Add column "favoriteColor" to "User"

└─ marker b29af3990b528c7a67809a2ac609305c59aa9c0af1ed0e4591cc0a727b38b1d1

✔ Advanced ref "db" → b29af3990b528c7a67809a2ac609305c59aa9c0af1ed0e4591cc0a727b38b1d1
git add -A

git commit -m "Add User.favoriteColor"

On his branch, from the same starting commit, Javier adds a model:

title="src/prisma/contract.prisma"
model Tag {

  tagName     String @id

  tagCategory String

}
bunx prisma contract emit

bunx prisma migration plan --name add_tag_model
Bash
pnpm prisma contract emit
pnpm prisma migration plan --name add_tag_model
Bash
yarn prisma contract emit
yarn prisma migration plan --name add_tag_model
Bash
npx prisma contract emit
npx prisma migration plan --name add_tag_model
no-copy
✔ Planned 1 operation(s)

migrations/app/20260910T1547_add_tag_model
└─ Create table "Tag"

from:       91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e
to:         18b24e59a8b291a37b50e0d82c7afb58b314a2b64920d530627c73bd6e2d9768
app space:  migrations/app/20260910T1547_add_tag_model

ℹ DDL preview

CREATE TABLE "public"."Tag" (
  "tagCategory" text NOT NULL,
  "tagName" text NOT NULL,
  PRIMARY KEY ("tagName")
);

His plan also starts from: the init state. He applies with db migrate --advance-ref db and commits. Both migrations now leave the same node and arrive at different ones. Neither developer knows about the other yet, and neither needs to.

✔ Planned 1 operation(s)

migrations/app/20260910T1547_add_tag_model

└─ Create table "Tag"

from:       91e7f9f035806fa2789a4d726ef7724cad434fd6b00014d47ebf12d6e6bb784e

to:         18b24e59a8b291a37b50e0d82c7afb58b314a2b64920d530627c73bd6e2d9768

app space:  migrations/app/20260910T1547_add_tag_model

ℹ DDL preview

CREATE TABLE "public"."Tag" (

  "tagCategory" text NOT NULL,

  "tagName" text NOT NULL,

  PRIMARY KEY ("tagName")

);

His plan also starts from: the init state. He applies with db migrate --advance-ref db and commits. Both migrations now leave the same node and arrive at different ones. Neither developer knows about the other yet, and neither needs to.

Ania's branch merges into main first, as a fast-forward. Javier's merge conflicts:

git merge javier/tag-model
Auto-merging migrations/app/refs/db.json

CONFLICT (content): Merge conflict in migrations/app/refs/db.json

Auto-merging src/prisma/contract.d.ts

CONFLICT (content): Merge conflict in src/prisma/contract.d.ts

Auto-merging src/prisma/contract.json

CONFLICT (content): Merge conflict in src/prisma/contract.json

Auto-merging src/prisma/contract.prisma

Automatic merge failed; fix conflicts and then commit the result.

Read the list carefully. contract.prisma, the file you author, merged cleanly: the two edits touch different parts of the schema. The three conflicts are all in files Prisma writes for you, and none of them needs hand editing:

  • contract.json and contract.d.ts are emitted from contract.prisma. Re-emit and they are regenerated from the merged source, conflict markers and all:
bunx prisma contract emit
Bash
pnpm prisma contract emit
Bash
yarn prisma contract emit
Bash
npx prisma contract emit
no-copy
✔ Emitted contract.json and contract.d.ts

storageHash:    1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b
  • migrations/app/refs/db.json records the contract state a local database last matched. Each branch pointed it at its own state, and neither is the state your database matches now. Take either side; you will set it correctly when you apply in section 3.5.
Bash
git checkout --ours migrations/app/refs/db.json

Do not commit yet. The graph is not finished.

✔ Emitted contract.json and contract.d.ts

storageHash:    1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b
  • migrations/app/refs/db.json records the contract state a local database last matched. Each branch pointed it at its own state, and neither is the state your database matches now. Take either side; you will set it correctly when you apply in section 3.5.
git checkout --ours migrations/app/refs/db.json

Do not commit yet. The graph is not finished.

Draw the graph:

bunx prisma migration graph
Bash
pnpm prisma migration graph
Bash
yarn prisma migration graph
Bash
npx prisma migration graph
no-copy
○     1e5059c  @contract

○     b29af39  (db)
│↑    20260910T1546_add_favorite_color  91e7f9f → b29af39  1 ops
│ ○   18b24e5
│ │↑  20260910T1547_add_tag_model       91e7f9f → 18b24e5  1 ops
│─╯
○     91e7f9f
│↑    20260910T1543_init                      ∅ → 91e7f9f  6 ops
○     ∅

1 space(s), 4 contract(s), 3 migration(s)

Read it bottom-up. From init (91e7f9f) two branches leave: Ania's ends at b29af39, Javier's at 18b24e5. The merged contract you just emitted, 1e5059c, sits at the top with no edge arriving at it. No database can reach it yet. migration status draws the same graph and marks where your database is, which is still on init (@db):

○     1e5059c  @contract

○     b29af39  (db)

│↑    20260910T1546_add_favorite_color  91e7f9f → b29af39  1 ops

│ ○   18b24e5

│ │↑  20260910T1547_add_tag_model       91e7f9f → 18b24e5  1 ops

│─╯

○     91e7f9f

│↑    20260910T1543_init                      ∅ → 91e7f9f  6 ops

○     ∅

1 space(s), 4 contract(s), 3 migration(s)

Read it bottom-up. From init (91e7f9f) two branches leave: Ania's ends at b29af39, Javier's at 18b24e5. The merged contract you just emitted, 1e5059c, sits at the top with no edge arriving at it. No database can reach it yet. migration status draws the same graph and marks where your database is, which is still on init (@db):

bunx prisma migration status
Bash
pnpm prisma migration status
Bash
yarn prisma migration status
Bash
npx prisma migration status
no-copy
○     1e5059c  @contract

○     b29af39  (db)
│↑    20260910T1546_add_favorite_color  91e7f9f → b29af39  1 ops
│ ○   18b24e5
│ │↑  20260910T1547_add_tag_model       91e7f9f → 18b24e5  1 ops
│─╯
○     91e7f9f  @db
│↑    20260910T1543_init                      ∅ → 91e7f9f  6 ops  ✓ applied
○     ∅

⚠ No migration path from the database state (91e7f9f03580) to the application's contract (1e5059c1976c). Run `{bin} migration plan --name <name>` to author one.

Do not follow that hint literally. Without --from, the planner takes the db ref as its origin, and after git checkout --ours that ref is Ania's tip, so migration plan --name merge_schema writes only the half of the merge her branch is missing. Javier's database would still have no path to the top. Had the ref still pointed at init, the planner would have started a third branch from the divergence point instead, with a warning that it forks the graph. Neither is the merge. Do not delete either branch's migration directory to get out of this: Ania's and Javier's databases have already applied those migrations. Name the origin yourself, once per tip.

○     1e5059c  @contract

○     b29af39  (db)

│↑    20260910T1546_add_favorite_color  91e7f9f → b29af39  1 ops

│ ○   18b24e5

│ │↑  20260910T1547_add_tag_model       91e7f9f → 18b24e5  1 ops

│─╯

○     91e7f9f  @db

│↑    20260910T1543_init                      ∅ → 91e7f9f  6 ops  ✓ applied

○     ∅

⚠ No migration path from the database state (91e7f9f03580) to the application's contract (1e5059c1976c). Run `{bin} migration plan --name <name>` to author one.

Do not follow that hint literally. Without --from, the planner takes the db ref as its origin, and after git checkout --ours that ref is Ania's tip, so migration plan --name merge_schema writes only the half of the merge her branch is missing. Javier's database would still have no path to the top. Had the ref still pointed at init, the planner would have started a third branch from the divergence point instead, with a warning that it forks the graph. Neither is the merge. Do not delete either branch's migration directory to get out of this: Ania's and Javier's databases have already applied those migrations. Name the origin yourself, once per tip.

Plan one merge migration from each tip. Each one carries the change its branch is missing, and both arrive at the merged contract:

bunx prisma migration plan --from 20260910T1546_add_favorite_color --name merge_add_tag_model
Bash
pnpm prisma migration plan --from 20260910T1546_add_favorite_color --name merge_add_tag_model
Bash
yarn prisma migration plan --from 20260910T1546_add_favorite_color --name merge_add_tag_model
Bash
npx prisma migration plan --from 20260910T1546_add_favorite_color --name merge_add_tag_model
no-copy
✔ Planned 1 operation(s)

migrations/app/20260910T1550_merge_add_tag_model
└─ Create table "Tag"

from:       b29af3990b528c7a67809a2ac609305c59aa9c0af1ed0e4591cc0a727b38b1d1
to:         1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b
✔ Planned 1 operation(s)

migrations/app/20260910T1550_merge_add_tag_model

└─ Create table "Tag"

from:       b29af3990b528c7a67809a2ac609305c59aa9c0af1ed0e4591cc0a727b38b1d1

to:         1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b
bunx prisma migration plan --from 20260910T1547_add_tag_model --name merge_add_favorite_color
Bash
pnpm prisma migration plan --from 20260910T1547_add_tag_model --name merge_add_favorite_color
Bash
yarn prisma migration plan --from 20260910T1547_add_tag_model --name merge_add_favorite_color
Bash
npx prisma migration plan --from 20260910T1547_add_tag_model --name merge_add_favorite_color
no-copy
✔ Planned 1 operation(s)

migrations/app/20260910T1550_merge_add_favorite_color
└─ Add column "favoriteColor" to "User"

from:       18b24e59a8b291a37b50e0d82c7afb58b314a2b64920d530627c73bd6e2d9768
to:         1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

--from accepts a migration directory name, as here, or a contract hash from the graph. The planner diffs the two contract snapshots and writes exactly the operations that are missing on that side. Review both DDL previews the way you would review any migration. The graph is now a diamond, and every database on either branch has a path to the top:

✔ Planned 1 operation(s)

migrations/app/20260910T1550_merge_add_favorite_color

└─ Add column "favoriteColor" to "User"

from:       18b24e59a8b291a37b50e0d82c7afb58b314a2b64920d530627c73bd6e2d9768

to:         1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

--from accepts a migration directory name, as here, or a contract hash from the graph. The planner diffs the two contract snapshots and writes exactly the operations that are missing on that side. Review both DDL previews the way you would review any migration. The graph is now a diamond, and every database on either branch has a path to the top:

bunx prisma migration graph
Bash
pnpm prisma migration graph
Bash
yarn prisma migration graph
Bash
npx prisma migration graph
no-copy
○     1e5059c  @contract
│─╮
│↑│   20260910T1550_merge_add_tag_model       b29af39 → 1e5059c  1 ops
│ │↑  20260910T1550_merge_add_favorite_color  18b24e5 → 1e5059c  1 ops
○ │   b29af39  (db)
│↑│   20260910T1546_add_favorite_color        91e7f9f → b29af39  1 ops
│ ○   18b24e5
│ │↑  20260910T1547_add_tag_model             91e7f9f → 18b24e5  1 ops
│─╯
○     91e7f9f
│↑    20260910T1543_init                            ∅ → 91e7f9f  6 ops
○     ∅

1 space(s), 5 contract(s), 5 migration(s)

Your own database is still on init, so two migrations are pending for it. Apply them and let --advance-ref db set the db ref to where the database actually ends up, which also settles the db.json conflict from section 3.3:

○     1e5059c  @contract

│─╮

│↑│   20260910T1550_merge_add_tag_model       b29af39 → 1e5059c  1 ops

│ │↑  20260910T1550_merge_add_favorite_color  18b24e5 → 1e5059c  1 ops

○ │   b29af39  (db)

│↑│   20260910T1546_add_favorite_color        91e7f9f → b29af39  1 ops

│ ○   18b24e5

│ │↑  20260910T1547_add_tag_model             91e7f9f → 18b24e5  1 ops

│─╯

○     91e7f9f

│↑    20260910T1543_init                            ∅ → 91e7f9f  6 ops

○     ∅

1 space(s), 5 contract(s), 5 migration(s)

Your own database is still on init, so two migrations are pending for it. Apply them and let --advance-ref db set the db ref to where the database actually ends up, which also settles the db.json conflict from section 3.3:

bunx prisma db migrate --advance-ref db
Bash
pnpm prisma db migrate --advance-ref db
Bash
yarn prisma db migrate --advance-ref db
Bash
npx prisma db migrate --advance-ref db
no-copy
✔ Applied 2 migration(s) (2 operation(s)) across 1 contract space(s)

App space
├─ Add column "favoriteColor" to "User"
├─ Create table "Tag"
└─ marker 1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

✔ Advanced ref "db" → 1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

The runner walked init → add_favorite_color → merge_add_tag_model. It could equally have walked the other side; both paths end at the same contract. Now commit the merge, the re-emitted contract, both merge migrations, and the db ref together:

Bash
git add -A
git commit -m "Merge javier/tag-model and plan merge migrations"
✔ Applied 2 migration(s) (2 operation(s)) across 1 contract space(s)

App space

├─ Add column "favoriteColor" to "User"

├─ Create table "Tag"

└─ marker 1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

✔ Advanced ref "db" → 1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

The runner walked init → add_favorite_color → merge_add_tag_model. It could equally have walked the other side; both paths end at the same contract. Now commit the merge, the re-emitted contract, both merge migrations, and the db ref together:

git add -A

git commit -m "Merge javier/tag-model and plan merge migrations"

Ania pulls main. Her database matches b29af39, so only the migration that adds Javier's table is pending for her:

bunx prisma migration status
Bash
pnpm prisma migration status
Bash
yarn prisma migration status
Bash
npx prisma migration status
no-copy
○     1e5059c  @contract (db)
│─╮
│↑│   20260910T1550_merge_add_tag_model       b29af39 → 1e5059c  1 ops  ⧗ pending
│ │↑  20260910T1550_merge_add_favorite_color  18b24e5 → 1e5059c  1 ops
○ │   b29af39  @db
│↑│   20260910T1546_add_favorite_color        91e7f9f → b29af39  1 ops  ✓ applied
│ ○   18b24e5
│ │↑  20260910T1547_add_tag_model             91e7f9f → 18b24e5  1 ops
│─╯
○     91e7f9f
│↑    20260910T1543_init                            ∅ → 91e7f9f  6 ops  ✓ applied
○     ∅

⚠ 1 pending: run `{bin} db migrate --to 1e5059c1976c`
○     1e5059c  @contract (db)

│─╮

│↑│   20260910T1550_merge_add_tag_model       b29af39 → 1e5059c  1 ops  ⧗ pending

│ │↑  20260910T1550_merge_add_favorite_color  18b24e5 → 1e5059c  1 ops

○ │   b29af39  @db

│↑│   20260910T1546_add_favorite_color        91e7f9f → b29af39  1 ops  ✓ applied

│ ○   18b24e5

│ │↑  20260910T1547_add_tag_model             91e7f9f → 18b24e5  1 ops

│─╯

○     91e7f9f

│↑    20260910T1543_init                            ∅ → 91e7f9f  6 ops  ✓ applied

○     ∅

⚠ 1 pending: run `{bin} db migrate --to 1e5059c1976c`
bunx prisma db migrate --advance-ref db
Bash
pnpm prisma db migrate --advance-ref db
Bash
yarn prisma db migrate --advance-ref db
Bash
npx prisma db migrate --advance-ref db
no-copy
✔ Applied 1 migration(s) (1 operation(s)) across 1 contract space(s)

App space
├─ Create table "Tag"
└─ marker 1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

Javier does the same, and for him the pending migration is merge_add_favorite_color, which adds Ania's column. Nobody re-created anything, and the database's own ledger shows the route each one took:

✔ Applied 1 migration(s) (1 operation(s)) across 1 contract space(s)

App space

├─ Create table "Tag"

└─ marker 1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

Javier does the same, and for him the pending migration is merge_add_favorite_color, which adds Ania's column. Nobody re-created anything, and the database's own ledger shows the route each one took:

bunx prisma migration log
Bash
pnpm prisma migration log
Bash
yarn prisma migration log
Bash
npx prisma migration log
no-copy
Applied at                  Migration                          Change             Ops
2026-09-10 17:45:41 +02:00  20260910T1543_init                 ∅ → 91e7f9f        6 ops
2026-09-10 17:46:17 +02:00  20260910T1546_add_favorite_color   91e7f9f → b29af39  1 ops
2026-09-10 17:52:47 +02:00  20260910T1550_merge_add_tag_model  b29af39 → 1e5059c  1 ops
Applied at                  Migration                          Change             Ops

2026-09-10 17:45:41 +02:00  20260910T1543_init                 ∅ → 91e7f9f        6 ops

2026-09-10 17:46:17 +02:00  20260910T1546_add_favorite_color   91e7f9f → b29af39  1 ops

2026-09-10 17:52:47 +02:00  20260910T1550_merge_add_tag_model  b29af39 → 1e5059c  1 ops

With main merged and your database on the merged state, add your own field. Always pull and apply before you plan, so your plan chains from the state everyone shares:

git pull
title="bun"
bunx prisma migration status
pnpm
pnpm prisma migration status
yarn
yarn prisma migration status
npm
npx prisma migration status
title="src/prisma/contract.prisma"
model User {

  /* ... */

  favoriteColor   String?

  bestPacmanScore Int?

}
bunx prisma contract emit

bunx prisma migration plan --name add_best_pacman_score
Bash
pnpm prisma contract emit
pnpm prisma migration plan --name add_best_pacman_score
Bash
yarn prisma contract emit
yarn prisma migration plan --name add_best_pacman_score
Bash
npx prisma contract emit
npx prisma migration plan --name add_best_pacman_score
no-copy
✔ Planned 1 operation(s)

migrations/app/20260910T1554_add_best_pacman_score
└─ Add column "bestPacmanScore" to "User"

from:       1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b
to:         4961e5b3ceb00cb24a60245343f288095c5a00fc2344d02db1b68509a8b91440
app space:  migrations/app/20260910T1554_add_best_pacman_score

ℹ DDL preview

ALTER TABLE "public"."User" ADD COLUMN "bestPacmanScore" int4;

No --from was needed: the db ref points at the merged state because the last apply advanced it. Check the from: line anyway. If it does not name the state you expect, stop and read Common gotchas.

✔ Planned 1 operation(s)

migrations/app/20260910T1554_add_best_pacman_score

└─ Add column "bestPacmanScore" to "User"

from:       1e5059c1976c2439863eae8ac13211916ca411614c917394c413346f0d00f60b

to:         4961e5b3ceb00cb24a60245343f288095c5a00fc2344d02db1b68509a8b91440

app space:  migrations/app/20260910T1554_add_best_pacman_score

ℹ DDL preview

ALTER TABLE "public"."User" ADD COLUMN "bestPacmanScore" int4;

No --from was needed: the db ref points at the merged state because the last apply advanced it. Check the from: line anyway. If it does not name the state you expect, stop and read Common gotchas.

bunx prisma db migrate --advance-ref db

bunx prisma migration check
Bash
pnpm prisma db migrate --advance-ref db
pnpm prisma migration check
Bash
yarn prisma db migrate --advance-ref db
yarn prisma migration check
Bash
npx prisma db migrate --advance-ref db
npx prisma migration check
no-copy
✔ Applied 1 migration(s) (1 operation(s)) across 1 contract space(s)

App space
├─ Add column "bestPacmanScore" to "User"
└─ marker 4961e5b3ceb00cb24a60245343f288095c5a00fc2344d02db1b68509a8b91440

✔ Advanced ref "db" → 4961e5b3ceb00cb24a60245343f288095c5a00fc2344d02db1b68509a8b91440
no-copy
✔ All checks passed

migration check is offline and verifies every migration's hash and the graph's integrity. Run it after you edit a migration by hand, so an ops.json or migration.json that no longer matches its hash shows up before you commit. A pipeline does not need it, because db migrate refuses such a migration too.

migration check reads only the files, so it cannot tell you whether a database matches them. db verify does. Run npx prisma db verify --db "$DATABASE_URL" after db migrate, and it fails if the database's marker or its tables differ from the contract you emitted. A pipeline that migrates a shared database runs db migrate alone; it refuses a database whose marker is outside your history with MIGRATION.MARKER_MISMATCH before it runs anything. Migrate a shared database from a workflow shows the job.

✔ Applied 1 migration(s) (1 operation(s)) across 1 contract space(s)

App space

├─ Add column "bestPacmanScore" to "User"

└─ marker 4961e5b3ceb00cb24a60245343f288095c5a00fc2344d02db1b68509a8b91440

✔ Advanced ref "db" → 4961e5b3ceb00cb24a60245343f288095c5a00fc2344d02db1b68509a8b91440
✔ All checks passed

migration check is offline and verifies every migration's hash and the graph's integrity. Run it after you edit a migration by hand, so an ops.json or migration.json that no longer matches its hash shows up before you commit. A pipeline does not need it, because db migrate refuses such a migration too.

migration check reads only the files, so it cannot tell you whether a database matches them. db verify does. Run npx prisma db verify --db "$DATABASE_URL" after db migrate, and it fails if the database's marker or its tables differ from the contract you emitted. A pipeline that migrates a shared database runs db migrate alone; it refuses a database whose marker is outside your history with MIGRATION.MARKER_MISMATCH before it runs anything. Migrate a shared database from a workflow shows the job.

Commit the same set of files your teammates did:

git add src/prisma/contract.prisma src/prisma/contract.json src/prisma/contract.d.ts migrations

git commit -m "Add User.bestPacmanScore"

The final graph on main is a diamond with one more step on top, and your application code can use all three changes right away:

title="script.ts"
const user = await db.orm.public.User.create({

  email: "pacman@prisma.io",

  favoriteColor: "yellow",

  bestPacmanScore: 3333360,

});

const tag = await db.orm.public.Tag.create({ tagName: "arcade", tagCategory: "games" });

Run npx prisma@latest init once to install the Prisma ORM skills for your coding agent and keep them matching your installed packages. Prompts that map to this guide:

  • "Using the prisma-8 skill, check whether my database is behind the migrations on this branch and apply what is pending."
  • "Two branches both added migrations from the same state. Draw the migration graph and plan the merge migrations from each tip."
  • "Run migration check and explain any integrity failure before I open this pull request."
Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu