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

Prisma v8.0.0-rc.22 โ€” 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.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). 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 - **On PostgreSQL, `DateTime`, `Date` and `Time` are convenience types with new defaults.** Each is named for what a field means and becomes one explicit type, chosen by its optional `as`, `storage` and `precision` arguments. At its default, `DateTime` is a `timestamptz(3)` column read as a JavaScript `Date`, `Date` reads a string such as `"2024-02-29"`, `Time` reads a string such as `"09:30:00"`, and the new `Duration` reads an ISO 8601 duration such as `"P1M"`. Until now the three names read `Temporal` values. To keep a field as it is, rename `DateTime` to `TimestamptzTempor
Read the original context โ†—
Source flags breaking changes โ€” review applicability
๐Ÿ“„ .MD
โšก Executive Summary (TL;DR)

Prisma v8.0.0-rc.22. Source highlight: On PostgreSQL, `DateTime`, `Date`, `Time` and the new `Duration` are convenience types whose defaults read a JavaScript `Date` or a string, with no `Temporal` polyfill. Value objects move into the storage plane, so changing one is a migration, and Postgres checks value object and discriminator colum

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.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). 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 - **On PostgreSQL, `DateTime`, `Date` and `Time` are convenience types with new defaults.** Each is named for what a field means and becomes one explicit type, chosen by its optional `as`, `storage` and `precision` arguments. At its default, `DateTime` is a `timestamptz(3)` column read as a JavaScript `Date`, `Date` reads a string such as `"2024-02-29"`, `Time` reads a string such as `"09:30:00"`, and the new `Duration` reads an ISO 8601 duration such as `"P1M"`. Until now the three names read `Temporal` values. To keep a field as it is, rename `DateTime` to `TimestamptzTempor

โœจ New Features & Capabilities (6)

  • **On PostgreSQL, `DateTime`, `Date` and `Time` are convenience types with new defaults.** Each is named for what a field means and becomes one explicit type, chosen by its optional `as`, `storage` and `precision` arguments. At its default, `DateTime` is a `timestamptz(3)` column read as a JavaScript `Date`, `Date` reads a string such as `"2024-02-29"`, `Time` reads a string such as `"09:30:00"`, and the new `Duration` reads an ISO 8601 duration such as `"P1M"`. Until now the three names read `Te
  • `connect()` without options on a `postgres()`, `sqlite()`, `mysql()` or `mongo()` client is safe to call again: it waits for a connection in progress, or resolves with the runtime the client's queries already use. `connect(options)` on a bound client still rejects with `DRIVER.ALREADY_CONNECTED`, now with the message `<Target> client is already bound`. See `client-connect-safe-to-call-again` in the app recipe. (#30899)
  • A Postgres contract can declare the extensions it needs, with `extension pg_trgm {}` in PSL or `extension('pg_trgm')` in TypeScript, at the top level or in a namespace. `db verify` checks them, the planner creates them, and `contract infer` and `contract print` write them. The Prisma 7 reader reads the datasource `extensions` list, so a Prisma 7 database that uses pgvector, PostGIS or ParadeDB adopts Prisma 8 with `contract emit` and `db sign`. (#30902)
  • A new package, `@prisma/orm-postgres-contrib`, holds a `citext` extension pack: the PSL type `citext.Citext`, which compares case-insensitively. The Prisma 7 reader reads `@db.Citext` as `citext.Citext` when the config composes the pack, and refuses it with `PSL.PRISMA7_EXTENSION_PACK_MISSING`, naming the import to add, when it does not. Every Postgres `@db.*` type Prisma 7 accepts is now read. (#30904)
  • PostgreSQL gains the types `Xml`, `Oid` and `Money`, and the Prisma 7 reader reads `@db.Bit`, `@db.VarBit`, `@db.Xml`, `@db.Oid` and `@db.Money`. The Postgres driver sets `lc_monetary=C` on every connection and writes `money` through `numeric`, so `money` reads and writes the same value in any locale. (#30900)
  • MySQL gets ORM and SQL builder reads, including nested and ordered includes, through `@prisma/orm-mysql/runtime` and `@prisma/orm-mysql/static`. The MySQL drivers run on the `mariadb` package, which writes each value into the statement with its own escaping, so Prisma's code never puts a value into SQL and each statement takes one round trip. (#30863, #30893, #30918)

๐Ÿ”ง Bug Fixes & Patches (3)

  • **Value objects are storage entities, and Postgres checks their columns.** A contract keeps its value objects at `storage.namespaces.<ns>.entries.valueObject`, and a field names one by its storage coordinate, so changing a value object changes the storage hash and is a migration. On SQL, a discriminator column names a value set of its variants' values, and a discriminator field is typed by those values, such as `'bug' | 'feature'`. On a managed Postgres table, the contract derives a check for ea
  • On PostgreSQL, the `now` generator of a timestamp column read as a `Date` or a `Temporal` value rounds the time down to the column's precision, so the value a create returns is the value PostgreSQL stores. Before, a `timestamp(0)` column could store a time one second after the write. Re-emit the contract; only the execution hash changes. See `date-now-takes-column-precision` in the app recipe. (#30847)
  • The diagnostic for a Prisma 7 `@db.*` attribute in a Prisma 8 schema suggests the constructor Prisma 8 renamed it to, such as `String` for `@db.Text`, instead of a type that does not exist. (#30909)
๐Ÿ“„ View Raw Release Notes (Original Developer Log)
# v8.0.0-rc.22 On PostgreSQL, `DateTime`, `Date`, `Time` and the new `Duration` are convenience types whose defaults read a JavaScript `Date` or a string, with no `Temporal` polyfill. Value objects move into the storage plane, so changing one is a migration, and Postgres checks value object and discriminator columns. MongoDB's query builder, raw lane, ORM and runtime take an execution context, as SQL's do, and a MongoDB client creates its driver from the execution stack. A contract can declare the Postgres extensions it needs, so `db sign` adopts a database that uses pgvector, PostGIS, ParadeDB or the new citext pack. The Prisma 7 reader now reads every Postgres `@db.*` type Prisma 7 accepts. MySQL gets ORM and SQL builder reads. Prisma ORM refuses to run from two installed copies, and `connect()` on a client is safe to call again. The upgrade recipes for this hop: the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). 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 - **On PostgreSQL, `DateTime`, `Date` and `Time` are convenience types with new defaults.** Each is named for what a field means and becomes one explicit type, chosen by its optional `as`, `storage` and `precision` arguments. At its default, `DateTime` is a `timestamptz(3)` column read as a JavaScript `Date`, `Date` reads a string such as `"2024-02-29"`, `Time` reads a string such as `"09:30:00"`, and the new `Duration` reads an ISO 8601 duration such as `"P1M"`. Until now the three names read `Temporal` values. To keep a field as it is, rename `DateTime` to `TimestamptzTemporal`, `Date` to `DateTemporal` and `Time` to `TimeTemporal`; in TypeScript, call `type.TimestamptzTemporal(...)`, `type.DateTemporal()` and `type.TimeTemporal(...)`. `temporal.CreatedAt` and `temporal.UpdatedAt` are now built on the new `DateTime`, and their `String` and `JsDate` variants are removed. A contract read by `prisma7Schema(...)` now reads a Prisma 7 `DateTime` field as a `Date`, as Prisma 7 did, so run `prisma db sign` after re-emitting it. On PostgreSQL and MySQL, a column read as a `Date`, such as MySQL's `DateTime`, refuses a default with digits below a millisecond. The rest of this change is PostgreSQL only: SQLite, MySQL and MongoDB keep their date and time types. `contract infer` and `contract print` now write the convenience types: a `timestamptz(3)` column is `DateTime`, a `timestamptz` column `DateTime(precision: 6)`, a `timestamp(3)` column `DateTime(storage: timestamp)`, `date` is `Date`, `time` is `Time` and `interval` is `Duration`. So a contract you infer again reads a `timestamptz` field as a `Date`, where it read an ISO 8601 string, and drops its microseconds; add `as: string`, as in `DateTime(as: string, precision: 6)`, to keep the string. See `psl-date-time-types-are-convenience-types`, `ts-date-time-helpers-are-convenience-types`, `temporal-type-aliases-on-datetime`, `prisma7-schema-reads-dates` and `date-default-below-a-millisecond` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30847](https://github.com/prisma/orm/pull/30847)) Before: ```prisma model Event { id Int @id at DateTime day Date opensAt Time(0) } ``` After, to keep each field and its contract: ```prisma model Event { id Int @id at TimestamptzTemporal day DateTemporal opensAt TimeTemporal(0) } ``` - **Value objects are storage entities, and Postgres checks their columns.** A contract keeps its value objects at `storage.namespaces.<ns>.entries.valueObject`, and a field names one by its storage coordinate, so changing a value object changes the storage hash and is a migration. On SQL, a discriminator column names a value set of its variants' values, and a discriminator field is typed by those values, such as `'bug' | 'feature'`. On a managed Postgres table, the contract derives a check for each value object column and each discriminator column; the next `migration plan` adds them, and `db migrate` fails on a row that does not fit. A `contract.json` that keeps `valueObjects` in the domain plane is refused with `CONTRACT.VALIDATION_FAILED`. The app recipe ships a script that rewrites every contract, snapshot and migration that names one; run it, then sign each database before you re-emit. Extension authors: `ValueObjectTypesFromDomain` is now `ValueObjectTypesFromStorage`, `FieldTypesFromDomain` takes the storage namespaces as a sixth argument, `ValueObjectFieldType` is renamed `ValueObjectReference`, and a Postgres codec descriptor declares `jsonType`. See `value-objects-in-storage`, `value-object-types-from-storage`, `postgres-value-object-checks` and `discriminator-typed-by-variant-values` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/), and `mongo-result-shapes-read-storage`, `postgres-check-expression-types-move`, `field-types-read-storage-value-objects`, `value-object-reference-type` and `postgres-codec-json-type` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30869](https://github.com/prisma/orm/pull/30869)) - **MongoDB's query builder, raw lane, ORM and runtime take an execution context.** `mongoQuery`, `mongoRaw` and `mongoOrm` take `{ context }` instead of `{ contract }`, as `sql({ context })` and the SQL ORM do. A context comes from `mongoStatic({ contract })` or `mongo({ contract })`, which validate the contract once. `mongoOrm` takes `{ context, runtime }` and no longer takes `executor`, `enums` or `mutationDefaults`. `createMongoRuntime` takes `{ context, adapter, driver }`. `buildMongoEnums`, `MongoEnumAccessors`, `MongoOrmEnums` and `ORM.MUTATION_DEFAULTS_MISSING` are removed. Extension authors: `createSqlExecutionStack(...)` returns `SqlExecutionStackWithDriver`, whose `driver` is always set, only when given a driver. See `mongo-query-takes-context`, `mongo-orm-takes-context` and `mongo-runtime-takes-adapter` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/), and the same ids plus `sql-stack-with-driver-requires-driver` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30865](https://github.com/prisma/orm/pull/30865)) Before: ```ts import { mongoQuery } from '@prisma/orm-mongo/query-builder'; const query = mongoQuery({ contract }); const raw = mongoRaw({ contract }); ``` After: ```ts import mongoStatic from '@prisma/orm-mongo/static'; const { query, raw } = mongoStatic({ contract }); ``` - **A MongoDB driver is created from its descriptor.** `createMongoDriver` and `MongoDriverImpl` are no longer exported. Put the runtime driver descriptor, the default export of `@prisma/orm-mongo/driver/runtime`, on the execution stack, create the driver from the stack, and connect it. An application that calls `mongo({ contract, url })` sees no difference. Extension authors: `MongoDriver` gains `connect(binding)`, and code that only sends commands takes the new `MongoQueryable`. See `mongo-driver-from-runtime-descriptor` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/), and `mongo-driver-from-runtime-descriptor` and `mongo-driver-connect` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30906](https://github.com/prisma/orm/pull/30906)) Before: ```ts import { createMongoDriver } from '@prisma/orm-mongo/driver'; const driver = await createMongoDriver(url, dbName); ``` After: ```ts import mongoRuntimeDriver from '@prisma/orm-mongo/driver/runtime'; const stack = createMongoExecutionStack({ target, adapter, driver: mongoRuntimeDriver }); const driver = stack.driver.create(); await driver.connect({ kind: 'url', url, dbName }); ``` - **The pgvector, PostGIS and ParadeDB packs declare their Postgres extension, and `contract emit` writes each pack's files.** Each pack's contract now declares its extension, and its head no longer requires an install invariant. `prisma contract emit` writes each composed pack's head ref, contract snapshot and migrations under `migrations/<space-id>/`, as `migration plan` already did: commit them, then run `prisma db migrate` on each database to move the pack's marker. `db sign` now refuses a contract space whose head requires an invariant its marker does not record, with `MIGRATION.SIGN_INVARIANTS_MISSING`. Extension authors: declare a pack's extension in its contract instead of installing it with `installExtension(...)` and an invariant. See `contract-emit-pins-pack-files` and `packs-declare-their-postgres-extension` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/), and `declare-postgres-extension-in-pack-contract` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30902](https://github.com/prisma/orm/pull/30902)) - **Prisma ORM refuses to run from two installed copies.** Every command and client now stops with `RUNTIME.MULTIPLE_ORM_COPIES`, naming each copy and where it is, when more than one copy of Prisma ORM is installed. Before, such a project could fail later with an internal error, for example on the first literal default in `contract emit`. Install one version of every `@prisma/orm-*` package and a `prisma` CLI that runs it. See `one-orm-version` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30883](https://github.com/prisma/orm/pull/30883)) - **MongoDB merges identical and redundant indexes in a collection.** A unique and a plain index on the same keys, such as `@unique` and `@@index` on one field, now give one unique index, and identical indexes, which TypeScript and PSL refused before, give one. Before, the contract held both indexes of such a pair and the migration that created them failed with `MIGRATION.PRECHECK_FAILED`. Re-emit the contract, and replace a planned migration that creates both indexes. Extension authors: `BuildRefusal` loses the kind `indexDuplicate`, and `indexLookupKey`, `MONGO_INDEX_OPTION_KEYS`, `MongoIndexOptionKey` and `canonicalize` move from `@prisma/orm-family-mongo/schema-ir` to `@prisma/orm-family-mongo/contract`. See `mongo-merged-redundant-indexes` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/), and `mongo-build-refusal-index-duplicate-removed` and `mongo-index-lookup-key-moved` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30894](https://github.com/prisma/orm/pull/30894)) ## Features - `connect()` without options on a `postgres()`, `sqlite()`, `mysql()` or `mongo()` client is safe to call again: it waits for a connection in progress, or resolves with the runtime the client's queries already use. `connect(options)` on a bound client still rejects with `DRIVER.ALREADY_CONNECTED`, now with the message `<Target> client is already bound`. See `client-connect-safe-to-call-again` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30899](https://github.com/prisma/orm/pull/30899)) - A Postgres contract can declare the extensions it needs, with `extension pg_trgm {}` in PSL or `extension('pg_trgm')` in TypeScript, at the top level or in a namespace. `db verify` checks them, the planner creates them, and `contract infer` and `contract print` write them. The Prisma 7 reader reads the datasource `extensions` list, so a Prisma 7 database that uses pgvector, PostGIS or ParadeDB adopts Prisma 8 with `contract emit` and `db sign`. ([#30902](https://github.com/prisma/orm/pull/30902)) - A new package, `@prisma/orm-postgres-contrib`, holds a `citext` extension pack: the PSL type `citext.Citext`, which compares case-insensitively. The Prisma 7 reader reads `@db.Citext` as `citext.Citext` when the config composes the pack, and refuses it with `PSL.PRISMA7_EXTENSION_PACK_MISSING`, naming the import to add, when it does not. Every Postgres `@db.*` type Prisma 7 accepts is now read. ([#30904](https://github.com/prisma/orm/pull/30904)) - PostgreSQL gains the types `Xml`, `Oid` and `Money`, and the Prisma 7 reader reads `@db.Bit`, `@db.VarBit`, `@db.Xml`, `@db.Oid` and `@db.Money`. The Postgres driver sets `lc_monetary=C` on every connection and writes `money` through `numeric`, so `money` reads and writes the same value in any locale. ([#30900](https://github.com/prisma/orm/pull/30900)) - MySQL gets ORM and SQL builder reads, including nested and ordered includes, through `@prisma/orm-mysql/runtime` and `@prisma/orm-mysql/static`. The MySQL drivers run on the `mariadb` package, which writes each value into the statement with its own escaping, so Prisma's code never puts a value into SQL and each statement takes one round trip. ([#30863](https://github.com/prisma/orm/pull/30863), [#30893](https://github.com/prisma/orm/pull/30893), [#30918](https://github.com/prisma/orm/pull/30918)) - Prisma's extension packages list the npm keyword `prisma-orm-extension`, so a search for it finds them next to community extensions. ([#30892](https://github.com/prisma/orm/pull/30892)) ## Fixes - On PostgreSQL, the `now` generator of a timestamp column read as a `Date` or a `Temporal` value rounds the time down to the column's precision, so the value a create returns is the value PostgreSQL stores. Before, a `timestamp(0)` column could store a time one second after the write. Re-emit the contract; only the execution hash changes. See `date-now-takes-column-precision` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.22/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.21-to-8.0.0-rc.22/). ([#30847](https://github.com/prisma/orm/pull/30847)) - The diagnostic for a Prisma 7 `@db.*` attribute in a Prisma 8 schema suggests the constructor Prisma 8 renamed it to, such as `String` for `@db.Text`, instead of a type that does not exist. ([#30909](https://github.com/prisma/orm/pull/30909))
โ† Older Version Prisma v8.0.0-rc.21