# See Your Migration History in Prisma Studio URL: https://www.prisma.io/blog/prisma-studio-migrations-view Published: 2026-07-17 Authors: Ankur Datta, Søren Bramer Schmidt Tags: announcement, orm Series: Prisma 8 Description: The Prisma Studio Migrations view shows every applied Prisma 8 migration as a timeline with a visual diff, the executed SQL, and a schema diff. The Migrations view is a new screen in Prisma Studio, the database GUI bundled with the Prisma CLI. It shows the migration history of a [Prisma 8](https://www.prisma.io/docs/orm) database as a timeline: one entry per applied migration, with a visual diff of what changed, the SQL that ran, and a schema diff. Studio reads that history from the database itself, not from your repo. So it works for any Prisma 8 Postgres database you can connect to, including one you have never migrated yourself. The full setup is documented in [Studio with Prisma 8](https://www.prisma.io/docs/studio/prisma-next). This is the tenth post in the Prisma 8 series. The migration model it builds on is the subject of [Rethinking Database Migrations](https://www.prisma.io/blog/rethinking-database-migrations), and the files it visualizes are the ones [TypeScript Migrations in Prisma 8](https://www.prisma.io/blog/typescript-migrations-in-prisma-next) walks through. ![The Prisma Studio Migrations view showing a timeline of six applied migrations and a visual diff canvas of the selected migration.](https://www.prisma.io/blog/prisma-studio-migrations-view/imgs/studio-migrations-timeline.png) ## What did that migration actually do? [#what-did-that-migration-actually-do] A migration named `add_roles_and_publishing` ran against staging three weeks ago. Now you need to know what it did. You can read the migration file, which tells you what was *supposed* to happen. You can diff two schema files and reconstruct the change in your head. You can open a SQL console and inspect the current table, which tells you where you ended up but not how you got there. Or you can ask the person who wrote it. None of these tell you what is actually applied to the database in front of you. A repo tells you what exists, not what ran. Staging may be three merges behind or one hotfix ahead. ## What the Migrations view shows [#what-the-migrations-view-shows] The record of what actually ran lives in the database. Prisma 8 writes it there on every apply, and Studio reads it back. The list runs newest-first, one entry per applied migration. A ⚠️ marker flags any migration carrying a destructive change, so a dropped column is visible before you click anything. Selecting a migration draws the schema at that moment: models the migration added in green, models whose table changed in amber, untouched neighbors dimmed for context. Amber means one specific thing: *this table's DDL changed*. A model that only gained a back-relation, where the foreign key lives on the other table, stays dimmed. The new relation edge is emphasized instead. If a card is amber, DDL ran against that table. ## A walkthrough you can run [#a-walkthrough-you-can-run] Here is the workflow, from an empty directory. The screenshots in this post come from a six-migration history built exactly this way; the two migrations below are its first two. ### Step 1: Create a project [#step-1-create-a-project] ```bash npm create prisma@latest ``` Answer the prompts (PostgreSQL, PSL, your package manager) or skip them: ```bash npm create prisma@latest -- my-app --yes --provider postgres --authoring psl --template minimal ``` This scaffolds a contract at `src/prisma/contract.prisma`. Then create a [Prisma Postgres](https://www.prisma.io/docs/postgres) database with `npx create-db@latest` and export the connection string it prints as `DATABASE_URL` (the CLI reads the environment variable, not `.env`). The database is temporary for 24 hours; `create-db` also prints a claim URL to keep it. ### Step 2: Model, plan, apply [#step-2-model-plan-apply] Prisma 8 calls your schema a [contract](https://www.prisma.io/docs/orm/contract-authoring/the-data-contract): ```prisma // use prisma-next model User { id Int @id @default(autoincrement()) email String @unique username String? name String? posts Post[] createdAt DateTime @default(now()) updatedAt temporal.updatedAt() } model Post { id Int @id @default(autoincrement()) title String content String? author User @relation(fields: [authorId], references: [id]) authorId Int createdAt DateTime @default(now()) updatedAt temporal.updatedAt() } ``` Compile it, [plan a migration](https://www.prisma.io/docs/orm/migrations/generating-a-migration), [apply it](https://www.prisma.io/docs/orm/migrations/applying-a-migration): ```bash npx prisma@latest contract emit npx prisma@latest migration plan --name init_users_posts npx prisma@latest migrate --advance-ref db ``` `--advance-ref db` moves a [ref](https://www.prisma.io/docs/orm/migrations/the-migration-graph#name-important-states-with-refs), a name pinned to a point in your migration history, onto what you just applied. Later plans start from there and produce a delta instead of recreating everything. ### Step 3: Change the model [#step-3-change-the-model] Add an enum, two fields, and a boolean: ```prisma enum Role { USER EDITOR ADMIN } model User { id Int @id @default(autoincrement()) email String @unique username String? name String? bio String? role Role @default(USER) posts Post[] createdAt DateTime @default(now()) updatedAt temporal.updatedAt() } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int createdAt DateTime @default(now()) updatedAt temporal.updatedAt() } ``` ```bash npx prisma@latest contract emit npx prisma@latest migration plan --name add_roles_and_publishing npx prisma@latest migrate --advance-ref db ``` Repeat for whatever your app needs; when a change needs a backfill, [Data Migrations in Prisma 8](https://www.prisma.io/blog/data-migrations-in-prisma-next) covers that. The history behind the screenshots here has six migrations: an initial pair of models, this enum-and-fields change, a `Category` model with a relation and two unique constraints, a destructive column drop, and two more field additions. ### Step 4: Add some data [#step-4-add-some-data] A history reads better next to real rows: ```bash npm run db:seed ``` ### Step 5: Open Studio [#step-5-open-studio] A Prisma 8 project has no `schema.prisma`, so Studio takes the connection string with `--url`. The connection string lives in `.env` rather than your shell, so load it first. Run Studio from a directory outside the project: the Prisma 7 CLI that ships Studio cannot read the Prisma 8 `prisma.config.ts` and fails if it finds one: ```bash set -a && . ./.env && set +a cd .. && npx prisma@7 studio --url "$DATABASE_URL" ``` Studio prints the local URL it serves on; open it, and **Migrations** is in the left navigation. ## Reading a migration [#reading-a-migration] Select `add_roles_and_publishing`. The canvas shows the `Role` enum as a new card, `User` amber with `bio` and `role` marked `+`, and `Post` amber with `published`. Open the **SQL** panel and you get exactly what ran, labelled with its operation class: ![The SQL panel showing the ALTER TABLE statements and check constraint executed by a migration, each labelled with its operation class.](https://www.prisma.io/blog/prisma-studio-migrations-view/imgs/studio-migrations-sql-panel.png) Note the last statement. Prisma 8 implements `Role` as a `text` column plus a `CHECK` constraint rather than a native Postgres enum type. The canvas shows you the modelling intent; the SQL panel shows you the implementation. The **Schema** panel renders the same change as a Prisma-schema diff, with long unchanged runs collapsed into folds: ![The Schema panel showing a color-coded diff of the Prisma schema before and after a migration, with collapsed unchanged sections.](https://www.prisma.io/blog/prisma-studio-migrations-view/imgs/studio-migrations-schema-diff.png) By default the canvas draws only the models a migration touched plus their direct neighbors. Toggle **All models** to see the whole schema as it stood at that point in history: ![The Migrations view with the All models toggle enabled, showing every model and enum in the schema at that migration.](https://www.prisma.io/blog/prisma-studio-migrations-view/imgs/studio-migrations-all-models.png) The selected migration is part of the URL. In Console that means a link drops a reviewer straight onto the change you're asking about. Locally it's a bookmark for yourself. Your tables are in the same session under **Tables**, so you can go from "what changed" to "what's in there" without leaving the app. [Getting Started with Studio](https://www.prisma.io/docs/studio/getting-started) covers editing, filtering, and exporting: ![The Prisma Studio table view showing rows in the post table, including the published column added by a migration.](https://www.prisma.io/blog/prisma-studio-migrations-view/imgs/studio-post-table-data.png) ## Where the history comes from [#where-the-history-comes-from] Studio never opens your `migrations/` directory and never calls the Prisma 8 CLI. It reads two tables that Prisma 8 maintains in your database: * **`prisma_contract.ledger`** holds one row per applied migration: the name, the apply time, the executed operations with their SQL, and the two contract hashes the migration moved between. * **`prisma_contract.contract`** stores each distinct contract once, keyed by its hash. Every ledger row names the contract it started from and the contract it produced. Studio looks both up by hash. There is nothing to reconstruct and nothing to guess. Writing only the destination contract on each apply is enough to cover both ends of every row. The first migration starts from the empty contract. Every origin after that was some earlier apply's destination, so it is already stored. The practical consequence: a migration applied from CI, from a teammate's laptop, or from a branch you never checked out shows up in your Studio with a full diff. The history belongs to the database. The hashes are the same ones that make Prisma 8 migrations [a graph rather than a numbered list](https://www.prisma.io/docs/orm/migrations/the-migration-graph). ## Where you can use it [#where-you-can-use-it] The Migrations view shipped in `@prisma/studio-core` 0.32.0, and Prisma CLI 7.9 and later bundle it. Run `npx prisma@7 studio --url "$DATABASE_URL"` from a directory outside your Prisma 8 project to try it locally. It is also in the embedded Studio in [Prisma Console](https://console.prisma.io), for any database with an applied Prisma 8 migration history. Open your database's Studio tab and select **Migrations**. No local setup, and the selected migration is part of the Console URL too. A few limits worth stating plainly: * **Prisma 8 on PostgreSQL.** The view needs the `prisma_contract.ledger` table. Prisma ORM projects using `prisma migrate` record their history differently and won't show it. * **Applied migrations only.** A migration you've planned but not applied isn't in the database, so it isn't in the view. * **An empty history hides the view.** No applied migrations, no **Migrations** item. * **Older databases lose the diffs.** If your database was migrated by a Prisma 8 that predates the contract store, you keep the list and the SQL panel, and the canvas asks you to update. ## Where this fits [#where-this-fits] You already model data as a contract and apply migrations to [Prisma Postgres](https://www.prisma.io/docs/postgres). The missing piece was reading back what those migrations did to a specific database. That record used to live only in files, describing intent. Now Studio shows what ran. This matters most where the repo can't help you. The database your app talks to in production was migrated by CI, not by you. Its history is in the ledger, and Studio reads the ledger. The same timeline is there whether you deploy on [Prisma Compute](https://www.prisma.io/docs/compute) or anywhere else, and the embedded Studio in Console shows it to everyone on your team without a local checkout. ## Frequently asked questions [#frequently-asked-questions] ### What is the Migrations view in Prisma Studio? The Migrations view is a screen in Prisma Studio that lists every applied migration of a Prisma 8 database, newest first, with a visual diff of the models it changed, the SQL it executed, and a Prisma-schema diff. It shipped in `@prisma/studio-core` 0.32.0 and reads the history from the database itself. ### Why doesn't the Migrations item appear in my Prisma Studio? The Migrations item appears only when the connected database has at least one applied Prisma 8 migration, recorded in the `prisma_contract.ledger` table. It stays hidden for databases with no applied migrations, for Prisma ORM projects using `prisma migrate`, and for Studio versions older than `@prisma/studio-core` 0.32.0. Prisma CLI 7.9 and later bundle a new enough Studio; run `npx prisma@7 studio`. ### Does the Migrations view work with Prisma ORM and prisma migrate? No. Projects managed with `prisma migrate` record their history in the `_prisma_migrations` table, which the view does not read. The Migrations view requires a Prisma 8 project on PostgreSQL, which records each apply in `prisma_contract.ledger`. ### Where does Prisma Studio read the migration history from? From the database, not from your repo. Prisma 8 writes one row per applied migration to `prisma_contract.ledger` and stores each schema snapshot in `prisma_contract.contract`, keyed by hash. Studio joins the two, so migrations applied from CI or another machine appear with a full diff. ## Try it [#try-it] ```bash npm create prisma@latest ``` Model something, apply two migrations, and open **Migrations**. Tell us what you'd want in the timeline next on [Discord](https://pris.ly/discord). **Star and watch [prisma/prisma](https://github.com/prisma/orm) on GitHub** to follow development.