Prisma v8.0.0-rc.20prerelease Released Oct 22, 2026
โš ๏ธ Breaking Change Impact Score: 7/10

Prisma v8.0.0-rc.20 โ€” Release Notes & Engineering Impact

Source available โ€” automated, not human-reviewed

Component: prisma ยท Channel: prerelease. Automated analysis, not a compatibility certification. How this works.

Analysis updated: 2026-10-31.

Breaking-change evidence from the source

  • The upgrade recipes for this hop: the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). Each breaking change below names the change ids to look for in them.
  • Breaking changes - **A piped ORM command prints data lines, not JSON, unless you pass `--json`.** The ORM toolchain now requires `@prisma/cli-engine` 0.9.0, up from 0.7.0, the engine the `prisma` CLI ships since 8.0.0-rc.25. This engine picks the output format from flags only. When stdout is a pipe, a file, `$(โ€ฆ)`, a CI log or an agent, a command used to print JSON. It now prints the human output on stderr and plain data lines on stdout. Add `--json` to every script, CI step or program that reads JSON from `prisma contract โ€ฆ`, `prisma db โ€ฆ`, `prisma migration โ€ฆ` or `prisma orm init`. A project
Read the original context โ†—
Source flags breaking changes โ€” review applicability
๐Ÿ“„ .MD
โšก Executive Summary (TL;DR)

Prisma v8.0.0-rc.20. Source highlight: ORM commands run on `@prisma/cli-engine` 0.9.0, so a piped command prints tab-separated data lines and JSON needs `--json`. A type alias in PSL can set `@default`, `@onCreate` and `@onUpdate`, and the contract stores each column's real type instead of the alias name. Postgres migrations can rename,

Who Does This Impact? (Role-Based Analysis)

๐Ÿ’ป Software Engineers & Devs

Check the source notes against the package and APIs you use before upgrading.

๐Ÿ“Š Product & Engineering Leads

Use the documented changes to assess relevance to your product; release frequency alone is not a quality measure.

โš™๏ธ DevOps & Security

Verify the target version, runtime requirements and rollback procedure in the official documentation.

โš ๏ธ Breaking Changes & Deprecations (2)

  • The upgrade recipes for this hop: the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). Each breaking change below names the change ids to look for in them.
  • Breaking changes - **A piped ORM command prints data lines, not JSON, unless you pass `--json`.** The ORM toolchain now requires `@prisma/cli-engine` 0.9.0, up from 0.7.0, the engine the `prisma` CLI ships since 8.0.0-rc.25. This engine picks the output format from flags only. When stdout is a pipe, a file, `$(โ€ฆ)`, a CI log or an agent, a command used to print JSON. It now prints the human output on stderr and plain data lines on stdout. Add `--json` to every script, CI step or program that reads JSON from `prisma contract โ€ฆ`, `prisma db โ€ฆ`, `prisma migration โ€ฆ` or `prisma orm init`. A project

โœจ New Features & Capabilities (6)

  • **A piped ORM command prints data lines, not JSON, unless you pass `--json`.** The ORM toolchain now requires `@prisma/cli-engine` 0.9.0, up from 0.7.0, the engine the `prisma` CLI ships since 8.0.0-rc.25. This engine picks the output format from flags only. When stdout is a pipe, a file, `$(โ€ฆ)`, a CI log or an agent, a command used to print JSON. It now prints the human output on stderr and plain data lines on stdout. Add `--json` to every script, CI step or program that reads JSON from `prisma
  • **Supabase runs every role operation through `forRole(binding)`, and its `pg` option takes a pool only.** `SupabaseRuntime` no longer has `queryWithRole`, `executeWithRole`, `preparedQueryWithRole` or `preparedExecuteWithRole`. Call `runtime.forRole(binding)` once and use its `query`, `execute` and `connection` members. The `pg` option of `supabase()` takes a `pg.Pool`; a `pg.Client` fails with `SUPABASE.CONFIG_INVALID`. `db.close()` does not end a pool you pass in. `RoleBoundDb`, `ServiceRoleDb
  • A type alias in PSL can set `@default`, `@onCreate` and `@onUpdate`, and each field typed by it gets them, such as `types { UpdatedAt = TimestampString(3) @onCreate(now()) @onUpdate(now()) }`. Postgres, SQLite and MongoDB provide `temporal.CreatedAt` and `temporal.UpdatedAt`, and Postgres also has `String` and `JsDate` variants. MongoDB schemas can now use aliases. The TypeScript builder has a `type.*` helper for every type PSL can write, such as `type.VarChar(64)`. (#30819)
  • Postgres migrations can rename and move namespaces. `--rename billing:finance` renames the schema, and `--rename public.Invoice:billing.Invoice` moves a table into another schema with its rows, constraints, indexes and policies. `migration.ts` gains `this.renameSchema`, `this.setTableSchema` and `this.dropSchema`. (#30823)
  • `prisma migration plan` can change a relation's `onDelete` or `onUpdate`, and can change or remove a primary key, on Postgres. It drops the foreign key or primary key and adds it back, dropping and restoring every foreign key that points at an old primary key. It used to refuse both changes with `MIGRATION.PLANNING_FAILED`. (#30774)
  • Prisma 7's `prisma migrate dev`, `deploy`, `status`, `diff`, `reset` and `resolve` exit with `CLI.COMMAND_MOVED` and name the Prisma 8 command to use. (#30774)

๐Ÿ”ง Bug Fixes & Patches (3)

  • A Supabase client's internal runtime for Supabase's own tables is now closed by `db.close()`, so its queries after close reject with "Runtime is closed" instead of a driver error you could not act on. (#30828)
  • In the TypeScript builder, passing `undefined` to skip a preset argument no longer loses the arguments after it, so `field.temporal.timestamptz(undefined, 'now')` types correctly. (#30830)
  • `db migrate` no longer says a failed apply changed nothing on MongoDB when operations before the failure stayed applied. (#30814)
๐Ÿ“„ View Raw Release Notes (Original Developer Log)
# v8.0.0-rc.20 ORM commands run on `@prisma/cli-engine` 0.9.0, so a piped command prints tab-separated data lines and JSON needs `--json`. A type alias in PSL can set `@default`, `@onCreate` and `@onUpdate`, and the contract stores each column's real type instead of the alias name. Postgres migrations can rename, move and remove namespaces, and can change a relation's actions or a primary key. A failed migration check now names the object it expected. The upgrade recipes for this hop: the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). Each breaking change below names the change ids to look for in them. ## Breaking changes - **A piped ORM command prints data lines, not JSON, unless you pass `--json`.** The ORM toolchain now requires `@prisma/cli-engine` 0.9.0, up from 0.7.0, the engine the `prisma` CLI ships since 8.0.0-rc.25. This engine picks the output format from flags only. When stdout is a pipe, a file, `$(โ€ฆ)`, a CI log or an agent, a command used to print JSON. It now prints the human output on stderr and plain data lines on stdout. Add `--json` to every script, CI step or program that reads JSON from `prisma contract โ€ฆ`, `prisma db โ€ฆ`, `prisma migration โ€ฆ` or `prisma orm init`. A project that depends on `@prisma/cli-engine` itself moves to `0.9.0`. Data lines are a stable interface: fields are tab-separated in a documented order, and new fields are only added at the end. For example, `migration list` prints space, name, from, to and operation count, one line per migration. `db init`, `db update`, `db verify`, `db schema` and `migration ref delete` print nothing on stdout; read their exit code, or pass `--json`. See `piped-output-needs-json` and `engine-pin-moves-to-0-9-0` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). ([#30835](https://github.com/prisma/orm/pull/30835)) Before: ```sh prisma migration status | jq '.envelope.result' ``` After: ```sh prisma migration status --json | jq '.envelope.result' prisma migration list | cut -f2 # or read the data lines: one migration name per line ``` - **The contract stores a column's type, not the type alias it was written with.** A column typed by a `types {}` alias now stores the alias's codec and parameters itself, and the contract no longer has the alias in `storage.types`. Every contract that uses an alias gets a new storage hash. A stored contract whose columns still name an alias in `typeRef` no longer loads. Run the app recipe's script, which rewrites stored contracts and migration snapshots, then run `prisma contract emit`, then `prisma db sign` against every database. The database does not change. In the TypeScript builder, the `types` key is removed and `field.namedType(...)` takes only an enum: write an alias as a constant `field.column(type.VarChar(64))`. The Supabase extension's contract changes hash for the same reason, so sign a Supabase database too. See `stored-contracts-expand-type-aliases`, `ts-types-key-removed` and `supabase-contract-expanded` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). Extension authors run the same script from the package root and re-emit the bundled contract. A contract space that registers a database type writes it under `databaseTypes` instead of `types`. `ColumnTypeDescriptor.typeRef`, `StorageColumn.typeRef` and `ExecutionContext.types` are removed. See `stored-contracts-expand-type-aliases`, `types-key-is-database-types` and `column-type-ref-removed` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). ([#30819](https://github.com/prisma/orm/pull/30819)) Before: ```ts const types = { Embedding1536: type.pgvector.Vector(1536) } as const; const Post = model('Post', { fields: { embedding: field.namedType(types.Embedding1536).optional() }, }); return { types, models: { Post } }; ``` After: ```ts const Embedding1536 = field.column(type.pgvector.Vector(1536)); const Post = model('Post', { fields: { embedding: Embedding1536.optional() }, }); return { models: { Post } }; ``` - **A SQL builder insert must include every column the database requires.** In `db.sql.<namespace>.<table>.insert(rows)`, leaving out a column that is not nullable and has no default is now a type error that names the column. Such an insert used to compile and then fail in the database. A value typed `T | undefined` for such a column is an error too; check it before the insert. In ORM `create` and `upsert`, a field that is not nullable, has no default and generates a value only on update, such as one with `@onUpdate(...)` and no `@onCreate(...)`, is now required. See `sql-builder-insert-required-columns` and `orm-create-on-update-only-field` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/), and `sql-builder-insert-required-columns` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). ([#30830](https://github.com/prisma/orm/pull/30830)) Before: ```ts // User.displayName is `String` with no default; this compiled, then failed in the database db.sql.public.user.insert([{ email: '[email protected]', kind: 'admin' }]); ``` After: ```ts db.sql.public.user.insert([{ email: '[email protected]', kind: 'admin', displayName: 'Admin' }]); ``` - **MongoDB enum members and discriminator values are written in the syntax of their data type.** A MongoDB PSL enum member is read as a value of its codec's data type, as on SQL, so a quoted member is text. A quoted member on a type that does not take text is refused with `PSL_VALUE_TYPE_INCOMPATIBLE`: write numbers, `NaN` and the infinities unquoted, and dates and binary values with their tags. An Int32 or Int64 member written with a fraction, such as `1.0`, is refused; write `1`. A `@@discriminator` field must be required and hold one value, on SQL and MongoDB alike. When an enum types a discriminator, each `@@base` value must be one of its members. A value the receiving type refuses now reports `PSL_VALUE_REFUSED`. A Decimal128 value with leading zeros in `contract.json`, such as `"007.5"`, is refused when the contract loads; re-emit the contract. See `mongo-quoted-enum-members`, `mongo-integer-enum-members-with-a-fraction`, `discriminator-optional-or-list`, `discriminator-base-value-not-a-member`, `psl-value-refused-code` and `decimal128-spelling` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). Extension authors: `AuthoringEntityContext` takes `dataTypes` in place of `dataTypeLookup`, the `readWrittenValueForCodec` hook is removed, and an enum block needs `writtenValues`. See `entity-context-data-types` and `enum-block-members-written-values` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). ([#30832](https://github.com/prisma/orm/pull/30832)) Before: ```prisma enum Ratio { @@type("mongo/double@1") Unknown = "NaN" Half = 0.5 } ``` After: ```prisma enum Ratio { @@type("mongo/double@1") Unknown = NaN Half = 0.5 } ``` - **Supabase runs every role operation through `forRole(binding)`, and its `pg` option takes a pool only.** `SupabaseRuntime` no longer has `queryWithRole`, `executeWithRole`, `preparedQueryWithRole` or `preparedExecuteWithRole`. Call `runtime.forRole(binding)` once and use its `query`, `execute` and `connection` members. The `pg` option of `supabase()` takes a `pg.Pool`; a `pg.Client` fails with `SUPABASE.CONFIG_INVALID`. `db.close()` does not end a pool you pass in. `RoleBoundDb`, `ServiceRoleDb` and the transaction context gain `enums` and `nativeEnums`, so test doubles of them must add those members. After `db.close()`, a query on any role-bound client rejects with `DRIVER.NOT_CONNECTED` "Runtime is closed", and `close()` waits for open role transactions. See `supabase-for-role-replaces-with-role-methods`, `supabase-role-types-gain-members`, `supabase-pg-takes-a-pool` and `supabase-close-waits-for-work` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). Extension authors: `SqlRuntimeBase.acquireRawConnection()` now follows the close rule of `connection()`, and a runtime that shares its driver is built with `ownsDriver: false`. See `supabase-for-role-replaces-with-role-methods`, `supabase-role-types-gain-members`, `supabase-pg-takes-a-pool` and `raw-connection-obeys-close` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). ([#30828](https://github.com/prisma/orm/pull/30828)) Before: ```ts const rows = await runtime.queryWithRole(plan, { role: 'anon' }).toArray(); const db = await supabase({ contract, pg: new Client({ connectionString }), jwtSecret }); ``` After: ```ts const rows = await runtime.forRole({ role: 'anon' }).query(plan).toArray(); const db = await supabase({ contract, pg: new Pool({ connectionString }), jwtSecret }); ``` - **A removed Postgres namespace is asked about, and `accessWidening` is renamed `accessChanges`.** When the contract no longer declares a namespace, `migration plan` and `db update` now ask about each model in it, as for any removed model. They used to leave its tables in place without a word. Answer with `--rename <old>:<new>` if you renamed it, or `--delete <namespace>` to drop its tables and the schema. A run without a terminal fails with `CLI.CONSENT_REQUIRED` until you answer. The list of operations that change who can read or write a model's data is now `accessChanges`, in `db update --dry-run --json` and the control API, and the option `acceptAccessWidening` is now `acceptAccessChanges`. The question ends with "who can read and write its data" in place of "its rows". See `removed-namespace-questions` and `access-changes-rename` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). Extension authors: `SchemaTables` gains `hasNamespace`, `SchemaOwnership` gains `namespaceDeclaringSpaces`, and a resolved rename can name a namespace. See `access-changes-rename`, `statement-planning-target-namespaces`, `schema-ownership-namespace-spaces` and `namespace-rename-statement` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). ([#30823](https://github.com/prisma/orm/pull/30823)) Before: ```ts const result = await client.dbUpdate({ contract, mode: 'apply', migrationsDir, acceptAccessWidening: true }); if (result.ok) console.log(result.value.accessWidening); ``` After: ```ts const result = await client.dbUpdate({ contract, mode: 'apply', migrationsDir, acceptAccessChanges: true }); if (result.ok) console.log(result.value.accessChanges); ``` - **`db verify --json` and `db sign --json` report schema differences in `meta.schemaIssues`.** The `CONTRACT.SCHEMA_VERIFICATION_FAILED` diagnostic carried label strings in `meta.issues`. It now carries issue objects in `meta.schemaIssues`, the same key and shape as `MIGRATION.SCHEMA_VERIFY_FAILED`. Each issue has a `path`, and `expected` and `actual`. A failed apply also lists each way out as a separate entry in `nextActions`, and some entries change kind. See `schema-verification-failed-schema-issues` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.20/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.19-to-8.0.0-rc.20/). ([#30814](https://github.com/prisma/orm/pull/30814)) ## Features - A type alias in PSL can set `@default`, `@onCreate` and `@onUpdate`, and each field typed by it gets them, such as `types { UpdatedAt = TimestampString(3) @onCreate(now()) @onUpdate(now()) }`. Postgres, SQLite and MongoDB provide `temporal.CreatedAt` and `temporal.UpdatedAt`, and Postgres also has `String` and `JsDate` variants. MongoDB schemas can now use aliases. The TypeScript builder has a `type.*` helper for every type PSL can write, such as `type.VarChar(64)`. ([#30819](https://github.com/prisma/orm/pull/30819)) - Postgres migrations can rename and move namespaces. `--rename billing:finance` renames the schema, and `--rename public.Invoice:billing.Invoice` moves a table into another schema with its rows, constraints, indexes and policies. `migration.ts` gains `this.renameSchema`, `this.setTableSchema` and `this.dropSchema`. ([#30823](https://github.com/prisma/orm/pull/30823)) - `prisma migration plan` can change a relation's `onDelete` or `onUpdate`, and can change or remove a primary key, on Postgres. It drops the foreign key or primary key and adds it back, dropping and restoring every foreign key that points at an old primary key. It used to refuse both changes with `MIGRATION.PLANNING_FAILED`. ([#30774](https://github.com/prisma/orm/pull/30774)) - Prisma 7's `prisma migrate dev`, `deploy`, `status`, `diff`, `reset` and `resolve` exit with `CLI.COMMAND_MOVED` and name the Prisma 8 command to use. ([#30774](https://github.com/prisma/orm/pull/30774)) - A failed migration check names the object it expected, such as `the database already has table "user"`, in place of a generic sentence. Each check can carry an `expectation` in `ops.json`, and a check you write in a `rawSql` operation can carry one too. Migrations already written keep their hashes and the generic sentence. ([#30814](https://github.com/prisma/orm/pull/30814)) - A failed apply reports `meta.databaseUnchanged`, and its message says whether the database changed. On MongoDB, which has no transaction around a migration, it says so once anything was written. ([#30814](https://github.com/prisma/orm/pull/30814)) - A MongoDB discriminator may be a type alias of `String`. ([#30832](https://github.com/prisma/orm/pull/30832)) ## Fixes - A Supabase client's internal runtime for Supabase's own tables is now closed by `db.close()`, so its queries after close reject with "Runtime is closed" instead of a driver error you could not act on. ([#30828](https://github.com/prisma/orm/pull/30828)) - In the TypeScript builder, passing `undefined` to skip a preset argument no longer loses the arguments after it, so `field.temporal.timestamptz(undefined, 'now')` types correctly. ([#30830](https://github.com/prisma/orm/pull/30830)) - `db migrate` no longer says a failed apply changed nothing on MongoDB when operations before the failure stayed applied. ([#30814](https://github.com/prisma/orm/pull/30814))