1---
2title: Migrations
3description: How Prisma.Contract and Prisma.Migrate run Prisma's contract emission, migration planning, and graph-ordered apply inside alchemy deploy.
4---
5
6Prisma ORM v8 replaces `prisma migrate dev`/`deploy` with a
7contract-first migration system: `prisma migration plan` writes
8**migration packages** and `prisma db migrate` applies them in graph
9order. Alchemy runs both as resources in the deploy graph —
10`Prisma.Contract` plans, `Prisma.Migrate` applies:
11
12```typescript
13import * as Prisma from "alchemy/Prisma";
14
15const contract = yield* Prisma.Contract("contract");
16
17yield* Prisma.Migrate("migrate", {
18 url: databaseUrl,
19 contract,
20});
21```
22
23Here `databaseUrl` is a deploy-time database URL (plain or redacted), not the
24runtime connection Effect passed to the query client. Register
25`Prisma.providers()` alongside your database providers.
26
27Both [PSL-first and TypeScript-first contracts](/sql/prisma/contracts) use this
28migration flow. Choose and configure your source in the Contracts guide before
29planning changes.
30
31## What a deploy actually does
32
33`Prisma.Contract` checks the emitted contract's storage hash against the
34on-disk migration graph. Plan-time drift checks emit into a temporary directory,
35without changing your workspace. When reconciliation is needed, it:
36
371. Runs `prisma contract emit` — regenerating `contract.json`
38 (runtime IR) and `contract.d.ts` (types) from your contract source.
392. Compares the emitted contract's hash against the graph head.
403. If the graph doesn't cover the contract, runs
41 `prisma migration plan` with an explicit `--from` at the
42 current head, writing a new package under `migrations/app/`.
43
44`Prisma.Migrate` then observes the database's **contract marker** (a
45`prisma_contract.marker` row Prisma maintains) and applies only
46the pending part of the graph — a fresh database is bootstrapped from
47empty, an up-to-date one is a no-op, and re-running after a crash
48converges. A deploy can plan and apply a new package in the same run; it does
49not pause for review unless the plan needs a human decision. For reviewed
50changes, [plan and commit locally](#generate-review-and-commit-before-application)
51before deploying.
52
53## Migration packages, not SQL files
54
55A planned migration is a directory, not a `.sql` file:
56
57```
58migrations/
59├── app/
60│ └── 20260812T1014_migration-03524e20/
61│ ├── migration.json # from/to contract hashes + package hash
62│ ├── migration.ts # the operations, as reviewable TypeScript
63│ └── ops.json # rendered operations (content-addressed)
64└── snapshots/
65 └── 03524e20.../ # content-addressed contract snapshots
66```
67
68Commit the source contract, `migrations/` (including snapshots), emitted
69`contract.json` and `contract.d.ts`, and any generated Effect modules used by
70your application. Other environments consume these checked-in artifacts.
71TypeScript-first applications can import the authored contract directly; the
72deploy only plans a new package when the graph does not cover the contract.
73
74## Placeholders need your decision
75
76Some changes cannot be planned mechanically — making a column required
77needs a backfill for existing rows. Prisma renders those as
78`placeholder(...)` closures in the package's `migration.ts`, and
79alchemy **fails the deploy** rather than guessing (the SQL runs
80against your real database later in the same deploy):
81
821. Edit `migrations/app/<dir>/migration.ts` and replace each
83 `placeholder(...)` with a typed query plan.
842. Self-emit the package: `node migrations/app/<dir>/migration.ts`.
853. Commit and re-deploy — the contract sees no drift and
86 `Prisma.Migrate` applies the finished package.
87
88Or abandon the change: delete the package directory and revert the
89contract source.
90
91## Generate, review, and commit before application
92
93Run the same CLI locally on each contract change so deployment consumes a
94reviewed migration graph:
95
96```sh
97pnpm exec prisma contract emit
98pnpm exec prisma migration plan --name add-posts
99git add prisma.config.ts src/prisma migrations
100git diff --cached
101git commit -m "Add Prisma migration"
102```
103
104Resolve any placeholders and self-emit their packages before staging. If the
105application uses generated Effect outputs, run `pnpm exec alchemy prisma generate`
106before staging too; native `prisma contract emit` does not generate them. Review
107the source contract, operations, emitted artifacts, and snapshots together.
108
109The next deploy detects no drift when the committed graph covers the contract,
110and `Prisma.Migrate` applies it. Alternatively, keep application in your CLI
111workflow with `pnpm exec prisma db migrate --db "$DATABASE_URL"`. Add `--show`
112to preview the pending migration path before application.
113
114## The contract marker
115
116Prisma records the applied contract hash in the database itself
117(`prisma_contract.marker`). `Prisma.Migrate`'s diff compares the
118marker against the contract's hash, so databases changed out-of-band —
119a marker reset, a branch recreated from another parent — are detected
120and re-converged on the next deploy. The runtime client also verifies
121the marker on first use by default, so an application deployed against a
122stale database surfaces the drift instead of returning wrong answers.
123
124## Destroy never unwinds the database
125
126Removing `Prisma.Contract` from the stack does not delete migration
127packages or emitted artifacts (they are checked in), and destroying
128`Prisma.Migrate` never drops tables or reverts migrations. Deleting the database
129resource itself follows that provider's lifecycle. Rolling back a schema is
130itself a migration: plan to an earlier contract with
131`prisma migration plan --to <ref>`.
132
133## Scope: Postgres 17+, RC caveats
134
135Prisma v8 currently ships one production-track target: **PostgreSQL
13617+** (`@prisma/orm-postgres`). There is no MySQL and no D1 in the v8
137line, so unlike [Drizzle](/sql/drizzle/migrations) there are no other
138dialects to choose between — for those databases, use Drizzle or the
139raw [Effect SQL clients](/sql/effect-sql/postgres). Alchemy pins the
140exact RC version in its catalog; expect the RC line to keep moving
141until 8.0.0 final.
142
143## Where next
144
145- [Postgres](/sql/prisma/postgres) — the runtime query API.
146- [Cloudflare integration](/cloudflare/data/prisma) — the full contract, database, and Worker setup.
147- [SQL databases](/sql/databases) — database choices and canonical deployment guides.
148- [Effect SQL: Migrations](/sql/effect-sql/migrations) — the plain
149 `.sql` migration contract used by Drizzle and the raw clients.
150- [Prisma Postgres](/prisma) — provision the database with the Prisma
151 platform provider.