Component: prisma · Channel: prerelease. Automated analysis, not a compatibility certification. How this works.
Analysis updated: 2026-11-06.
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.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). Each breaking change below names the change ids to look for in them. The app recipe opens with the order to do the steps in. After upgrading, run `prisma contract emit` once, so a contract that an extension such as Supabase stamps with its version matches the installed package (`con
Breaking changes - **MongoDB indexes carry their names.** Every index of a MongoDB contract records the name MongoDB stores it under, so every MongoDB contract with an index gets a new storage hash. An index written without a name is named after its keys, such as `email_1`, the name earlier releases already gave it in the database, so no database changes. Migrations create and drop each index by that name, and an operation id names the index, as in `index.users.create(email_1)`. Two indexes of one collection that would get one name, such as a unique and a sparse index on `email`, are refused;
Prisma v8.0.0-rc.23. Source highlight: MongoDB indexes carry their names, and migrations create and drop each index by its name. On PostgreSQL, `Int`, `BigInt`, `Float`, `Decimal`, `String`, `Boolean` and `Bytes` become convenience types, and SQLite and MySQL get the convenience date and time types. The pgvector, PostGIS, ParadeDB and ci
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.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). Each breaking change below names the change ids to look for in them. The app recipe opens with the order to do the steps in. After upgrading, run `prisma contract emit` once, so a contract that an extension such as Supabase stamps with its version matches the installed package (`con
Breaking changes - **MongoDB indexes carry their names.** Every index of a MongoDB contract records the name MongoDB stores it under, so every MongoDB contract with an index gets a new storage hash. An index written without a name is named after its keys, such as `email_1`, the name earlier releases already gave it in the database, so no database changes. Migrations create and drop each index by that name, and an operation id names the index, as in `index.users.create(email_1)`. Two indexes of one collection that would get one name, such as a unique and a sparse index on `email`, are refused;
✨ New Features & Capabilities (6)
**`temporal-polyfill` is a peer dependency of the MySQL and SQLite packages.** The MySQL and SQLite control planes, such as the `prisma` commands, now import it. npm, pnpm and bun install it for you. A project that installs with Yarn adds `temporal-polyfill` (`^1.0.4`) to its dependencies. A MySQL `DateTime` field now refuses to write a year before 1000 or after 9999 with `RUNTIME.ENCODE_FAILED`. On SQLite, `db verify` reads a database default of `date('now')` as the current date, so it matches
On PostgreSQL, `Int`, `BigInt`, `Float`, `Decimal`, `String`, `Boolean` and `Bytes` are convenience types, as `DateTime` is. Each is named for what a field means, and its optional `storage` argument (and `as`, for `BigInt`) chooses an explicit type named after the database type, such as `Int(storage: int2)` for `Int2` or `BigInt(as: number)` for `Int8Number`. Written bare, each gives the same type as before, so every existing schema emits the same contract. (#30942)
SQLite and MySQL get the convenience types `DateTime`, `Date`, `Time` and `Duration`. `as:` chooses the value the application reads, such as a JavaScript `Date`, a string or a `Temporal` value, and on MySQL `storage:` chooses the column, such as `DateTime(storage: timestamp)`. A bare `DateTime` is the type `DateTime` was before, so every existing SQLite and MySQL contract emits the same. (#30922, #30950)
ORM `create`, `update`, `upsert` and `delete` work on MySQL and return the written rows, as on PostgreSQL. MySQL has no `RETURNING`, so the ORM writes and then reads the rows back by their key in the same transaction. (#30927)
`supabase()` takes the options `postgres()` takes, including `cursor`, which streams rows from a server-side cursor, and `binding`. (#30920)
A Supabase database whose pgvector, PostGIS, ParadeDB or citext extension lives in schema `extensions` adopts Prisma 8 with `prisma contract emit` and `prisma db sign`. (#30956)
🔧 Bug Fixes & Patches (4)
Migration statements cover value objects and variants on PostgreSQL and SQLite. `prisma migration plan` and `db update` take `--rename GeoPoint.lat:GeoPoint.latitude`, `--delete GeoPoint.lng` and `--backfill GeoPoint.country` for a value object field, rename or delete an enum value a value object holds, and take `--convert Bug` or `--delete Bug` for a variant whose discriminator value changed or that was removed. Each statement acts on every column that holds the value object. A failed migration
Prisma ORM no longer refuses to start when it is loaded from more than one copy. `RUNTIME.MULTIPLE_ORM_COPIES`, added in 8.0.0-rc.22, is removed for now, because a host that loads the ORM in two module instances, such as Prisma Composer's boot wrapper beside the app bundle, cannot satisfy it. A narrower check may return later. Installing one version of every `@prisma/orm-*` package is still required: values made by one copy are not recognised by another. (#30961)
A released Supabase role session resets its role. Before, its connection went back to the pool still running as the session's role, such as `authenticated`, so the next user of that connection ran under that role. (#30920)
On MySQL, stopping a stream early on a large result no longer ends the process with an unhandled rejection. The driver interrupts the statement itself before it closes the connection. (#30931)
📄 View Raw Release Notes (Original Developer Log)
# v8.0.0-rc.23
MongoDB indexes carry their names, and migrations create and drop each index by its name. On PostgreSQL, `Int`, `BigInt`, `Float`, `Decimal`, `String`, `Boolean` and `Bytes` become convenience types, and SQLite and MySQL get the convenience date and time types. The pgvector, PostGIS, ParadeDB and citext packs find their extension through the search path, so `db sign` adopts a Supabase database. MySQL gets ORM writes. `mongo()` takes extension packs, and `supabase()` takes the options `postgres()` takes. Prisma ORM no longer refuses to start when it is loaded from more than one copy.
The upgrade recipes for this hop: the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). Each breaking change below names the change ids to look for in them. The app recipe opens with the order to do the steps in. After upgrading, run `prisma contract emit` once, so a contract that an extension such as Supabase stamps with its version matches the installed package (`contract-artifacts-restamp` in the app recipe).
## Breaking changes
- **MongoDB indexes carry their names.** Every index of a MongoDB contract records the name MongoDB stores it under, so every MongoDB contract with an index gets a new storage hash. An index written without a name is named after its keys, such as `email_1`, the name earlier releases already gave it in the database, so no database changes. Migrations create and drop each index by that name, and an operation id names the index, as in `index.users.create(email_1)`. Two indexes of one collection that would get one name, such as a unique and a sparse index on `email`, are refused; name one of them. A contract read with `prisma6Schema()` names each index as Prisma 6 did, such as `User_email_key`. Run `prisma contract emit`, run the script the app recipe ships to name the indexes of your migration snapshots, then run `prisma db sign` or plan a migration, which has no operations. Extension authors: `MongoIndex`, `MongoSchemaIndex` and their input types take a required `name`, `CreateIndexCall` and `DropIndexCall` take the index's name and options, and code that calls `buildMongoContractFromDefinition` calls `nameIndexes` first. See `mongo-contracts-record-index-names`, `mongo-unnamed-indexes-with-one-name-refused`, `mongo-prisma6-index-names` and `mongo-index-operations-by-name` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/), and `mongo-index-name-required`, `mongo-index-calls-take-name` and `mongo-build-refusal-index-name-duplicate` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). ([#30952](https://github.com/prisma/orm/pull/30952))
Before:
```ts
createIndex('users', [{ field: 'email', direction: 1 }], { unique: true }),
```
After:
```ts
createIndex('users', [{ field: 'email', direction: 1 }], { name: 'email_1', unique: true }),
```
- **The Prisma 6 MongoDB reader keeps indexes as Prisma 6 wrote them.** `prisma6Schema()` no longer merges indexes. Two indexes of one model with the same fields and the same written sort are refused with `PSL.PRISMA6_MONGO_INDEX_ALREADY_EXISTS`, as Prisma 6 refuses them. A unique and a plain index on the same keys that Prisma 6 accepts are both kept, so the contract gets a new storage hash; run `prisma db sign` again. Prisma 8 PSL and TypeScript still merge identical and redundant indexes. Extension authors: the MongoDB contract builder no longer merges indexes, `BuildRefusal` has the kind `indexDuplicate` again, and `mergeRedundantIndexes` merges before building. See `mongo-prisma6-indexes-as-prisma6-reads-them` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/), and `mongo-build-refusal-index-duplicate-restored` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). ([#30921](https://github.com/prisma/orm/pull/30921))
- **The pgvector, PostGIS, ParadeDB and citext packs find their extension through the search path.** Each pack declares its extension in the unbound namespace, so `db sign` and `db verify` accept the extension in any schema on the connection's search path, such as Supabase's `extensions`. A project that composes one of these packs runs `prisma contract emit`, which writes the pack's new migration, and then `prisma db migrate`, which applies it without changing the database. An application may no longer declare an extension that a composed pack declares; remove its own `extension vector {}` block or `extension('vector')` handle. Extension authors: a pack declares its Postgres extension in the unbound namespace, or the configuration is refused with `CONTRACT.PACK_CONTRIBUTION_INVALID`. See `pack-extension-found-on-search-path` and `remove-pack-extension-declaration` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/), and `pack-declares-extension-unbound` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). ([#30956](https://github.com/prisma/orm/pull/30956))
- **`mongo()` and `mongoStatic()` refuse a contract whose extension packs they are not given.** They take an `extensions` option, as `postgres()` does. A MongoDB project whose `prisma.config.ts` composes extension packs passes each pack's runtime descriptor to `mongo({ extensions })` and `mongoStatic({ extensions })`; otherwise they fail with `RUNTIME.MISSING_EXTENSION_PACK`. A MongoDB `contract.json` must have `"target"`; every contract `prisma contract emit` writes has it. Extension authors: `createMongoExecutionContext` checks the contract against the stack, a MongoDB descriptor declares each codec once as a codec descriptor instead of in a `codecs()` slot, and `mongoStandardCodecs` and `buildStandardCodecRegistry` are removed. See `mongo-client-takes-extensions` and `mongo-contract-requires-target` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/), and `mongo-execution-context-checks-contract-requirements`, `mongo-codecs-declared-once` and `mongo-standard-codecs-removed` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). ([#30943](https://github.com/prisma/orm/pull/30943))
Before:
```ts
export const db = mongo({ contract, url });
```
After:
```ts
import myPack from 'my-mongo-pack/runtime';
export const db = mongo({ contract, url, extensions: [myPack] });
```
- **`supabase()` and `postgres()` check their database input when they are called.** A wrong input fails with `RUNTIME.BINDING_INVALID` at once, not on the first query. Passing both `url` and `pg` to `supabase()` fails; before, `pg` won silently. An empty `url`, or one that is not `postgres://` or `postgresql://`, fails; before, an empty one connected with the `PG*` environment variables or to localhost. `null` as `pg`, `url` or `binding` fails, even beside another input, so leave the option out instead. A `binding` of an unknown kind fails. `supabase()` refuses a `pg.Client` with the message "Supabase takes a pg.Pool or a url, not a pg.Client". See `supabase-one-binding-input` and `postgres-checks-database-input` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). ([#30920](https://github.com/prisma/orm/pull/30920))
Before:
```ts
postgres({ contract, url: process.env['DATABASE_URL'] ?? null });
```
After:
```ts
const url = process.env['DATABASE_URL'];
postgres({ contract, ...(url === undefined ? {} : { url }) });
```
- **On PostgreSQL, seven scalar type names are deprecated, and two column helpers are renamed.** `SmallInt`, `BigIntNumber`, `Numeric`, `UnboundedInt`, `Real`, `VarChar` and `VarBit` still work but report the warning `PSL_DEPRECATED_SCALAR_NAME`. Write the convenience type that gives the same type instead, such as `String(storage: varchar, length: 12)` for `VarChar(12)`; the contract does not change. The same TypeScript helpers, such as `type.VarChar(...)`, are deprecated too. The column helpers `int8Column` and `numericColumn` are renamed `int8BigIntColumn` and `numericStringColumn`, and the old names are removed. Extension authors: `postgresScalarAuthoringTypes`, `postgresNativeAuthoringTypes` and `postgresScalarAndNativeTypeConstructors` are replaced by `postgresScalarTypes` and `postgresExplicitTypes`. See `psl-renamed-postgres-scalar-types`, `ts-renamed-postgres-scalar-helpers` and `ts-renamed-postgres-column-helpers` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/), and the same ids plus `ts-renamed-postgres-type-groupings` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). ([#30942](https://github.com/prisma/orm/pull/30942))
Before:
```prisma
model Account {
id Int @id
visits SmallInt
price Numeric(10, 2)
code VarChar(12)
}
```
After:
```prisma
model Account {
id Int @id
visits Int(storage: int2)
price Decimal(precision: 10, scale: 2)
code String(storage: varchar, length: 12)
}
```
- **`temporal-polyfill` is a peer dependency of the MySQL and SQLite packages.** The MySQL and SQLite control planes, such as the `prisma` commands, now import it. npm, pnpm and bun install it for you. A project that installs with Yarn adds `temporal-polyfill` (`^1.0.4`) to its dependencies. A MySQL `DateTime` field now refuses to write a year before 1000 or after 9999 with `RUNTIME.ENCODE_FAILED`. On SQLite, `db verify` reads a database default of `date('now')` as the current date, so it matches only a `Date @default(now())` field. Extension authors: `mysqlCreateNamespace`, `MysqlDatabase`, `sqliteCreateNamespace` and `SqliteUnboundDatabase` move from the target's `/target/control` entry to its `/target/types` entry. See `temporal-polyfill-is-a-peer-dependency-of-mysql`, `mysql-datetime-writes-are-checked` and `temporal-polyfill-is-a-peer-dependency-of-sqlite` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/), and the same ids plus `mysql-create-namespace-moved-to-target-types` and `sqlite-create-namespace-moved-to-target-types` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.23/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.22-to-8.0.0-rc.23/). ([#30922](https://github.com/prisma/orm/pull/30922), [#30950](https://github.com/prisma/orm/pull/30950))
## Features
- On PostgreSQL, `Int`, `BigInt`, `Float`, `Decimal`, `String`, `Boolean` and `Bytes` are convenience types, as `DateTime` is. Each is named for what a field means, and its optional `storage` argument (and `as`, for `BigInt`) chooses an explicit type named after the database type, such as `Int(storage: int2)` for `Int2` or `BigInt(as: number)` for `Int8Number`. Written bare, each gives the same type as before, so every existing schema emits the same contract. ([#30942](https://github.com/prisma/orm/pull/30942))
- SQLite and MySQL get the convenience types `DateTime`, `Date`, `Time` and `Duration`. `as:` chooses the value the application reads, such as a JavaScript `Date`, a string or a `Temporal` value, and on MySQL `storage:` chooses the column, such as `DateTime(storage: timestamp)`. A bare `DateTime` is the type `DateTime` was before, so every existing SQLite and MySQL contract emits the same. ([#30922](https://github.com/prisma/orm/pull/30922), [#30950](https://github.com/prisma/orm/pull/30950))
- ORM `create`, `update`, `upsert` and `delete` work on MySQL and return the written rows, as on PostgreSQL. MySQL has no `RETURNING`, so the ORM writes and then reads the rows back by their key in the same transaction. ([#30927](https://github.com/prisma/orm/pull/30927))
- Migration statements cover value objects and variants on PostgreSQL and SQLite. `prisma migration plan` and `db update` take `--rename GeoPoint.lat:GeoPoint.latitude`, `--delete GeoPoint.lng` and `--backfill GeoPoint.country` for a value object field, rename or delete an enum value a value object holds, and take `--convert Bug` or `--delete Bug` for a variant whose discriminator value changed or that was removed. Each statement acts on every column that holds the value object. A failed migration's `rowsHoldingValue` detail is now a list of every removal whose check failed. ([#30929](https://github.com/prisma/orm/pull/30929))
- `supabase()` takes the options `postgres()` takes, including `cursor`, which streams rows from a server-side cursor, and `binding`. ([#30920](https://github.com/prisma/orm/pull/30920))
- A Supabase database whose pgvector, PostGIS, ParadeDB or citext extension lives in schema `extensions` adopts Prisma 8 with `prisma contract emit` and `prisma db sign`. ([#30956](https://github.com/prisma/orm/pull/30956))
## Fixes
- Prisma ORM no longer refuses to start when it is loaded from more than one copy. `RUNTIME.MULTIPLE_ORM_COPIES`, added in 8.0.0-rc.22, is removed for now, because a host that loads the ORM in two module instances, such as Prisma Composer's boot wrapper beside the app bundle, cannot satisfy it. A narrower check may return later. Installing one version of every `@prisma/orm-*` package is still required: values made by one copy are not recognised by another. ([#30961](https://github.com/prisma/orm/pull/30961))
- A released Supabase role session resets its role. Before, its connection went back to the pool still running as the session's role, such as `authenticated`, so the next user of that connection ran under that role. ([#30920](https://github.com/prisma/orm/pull/30920))
- On MySQL, stopping a stream early on a large result no longer ends the process with an unhandled rejection. The driver interrupts the statement itself before it closes the connection. ([#30931](https://github.com/prisma/orm/pull/30931))