diff --git a/docs/200-orm/050-overview/100-introduction/100-what-is-prisma.mdx b/docs/200-orm/050-overview/100-introduction/100-what-is-prisma.mdx
new file mode 100644
index 0000000000..dd091d68c0
--- /dev/null
+++ b/docs/200-orm/050-overview/100-introduction/100-what-is-prisma.mdx
@@ -0,0 +1,273 @@
+---
+title: 'What is Prisma?'
+metaTitle: 'What is Prisma? (Overview)'
+metaDescription: "This page gives a high-level overview of what Prisma is and how it works. It's a great starting point for Prisma newcomers!"
+---
+
+## What is Prisma?
+
+Prisma is an [open-source](https://github.com/prisma/prisma) next-generation ORM. It consists of the following parts:
+
+- **Prisma Client**: Auto-generated and type-safe query builder for Node.js & TypeScript
+- **Prisma Migrate**: Migration system
+- **Prisma Studio**: GUI to view and edit data in your database.
+
+
+
+ **Prisma Studio** is the only part of Prisma ORM that is not open source. You can only run Prisma Studio locally.
+
+
+
+Prisma Client can be used in _any_ Node.js (supported versions) or TypeScript backend application (including serverless applications and microservices). This can be a [REST API](/orm/overview/prisma-in-your-stack/rest), a [GraphQL API](/orm/overview/prisma-in-your-stack/graphql), a gRPC API, or anything else that needs a database.
+
+
+
+
+
+## How does Prisma work?
+
+### The Prisma schema
+
+Every project that uses a tool from the Prisma toolkit starts with a [Prisma schema file](/orm/prisma-schema). The Prisma schema allows developers to define their _application models_ in an intuitive data modeling language. It also contains the connection to a database and defines a _generator_:
+
+
+
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String?
+ published Boolean @default(false)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+```
+
+
+
+
+```prisma
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ content String?
+ published Boolean @default(false)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique
+ name String?
+ posts Post[]
+}
+```
+
+
+
+
+> **Note**: The Prisma schema has powerful data modeling features. For example, it allows you to define "Prisma-level" [relation fields](/orm/prisma-schema/data-model/relations) which will make it easier to work with [relations in the Prisma Client API](/orm/prisma-client/queries/relation-queries). In the case above, the `posts` field on `User` is defined only on "Prisma-level", meaning it does not manifest as a foreign key in the underlying database.
+
+In this schema, you configure three things:
+
+- **Data source**: Specifies your database connection (via an environment variable)
+- **Generator**: Indicates that you want to generate Prisma Client
+- **Data model**: Defines your application models
+
+### The Prisma data model
+
+On this page, the focus is on the data model. You can learn more about [Data sources](/orm/prisma-schema/overview/data-sources) and [Generators](/orm/prisma-schema/overview/generators) on the respective docs pages.
+
+#### Functions of Prisma models
+
+The data model is a collection of [models](/orm/prisma-schema/data-model/models#defining-models). A model has two major functions:
+
+- Represent a table in relational databases or a collection in MongoDB
+- Provide the foundation for the queries in the Prisma Client API
+
+#### Getting a data model
+
+There are two major workflows for "getting" a data model into your Prisma schema:
+
+- Manually writing the data model and mapping it to the database with [Prisma Migrate](/orm/prisma-migrate)
+- Generating the data model by [introspecting](/orm/prisma-schema/introspection) a database
+
+Once the data model is defined, you can [generate Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client) which will expose CRUD and more queries for the defined models. If you're using TypeScript, you'll get full type-safety for all queries (even when only retrieving the subsets of a model's fields).
+
+### Accessing your database with Prisma Client
+
+#### Generating Prisma Client
+
+The first step when using Prisma Client is installing the `@prisma/client` npm package:
+
+```terminal
+npm install @prisma/client
+```
+
+Installing the `@prisma/client` package invokes the `prisma generate` command, which reads your Prisma schema and _generates_ Prisma Client code. The code is [generated into the `node_modules/.prisma/client` folder by default](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package).
+
+After you change your data model, you'll need to manually re-generate Prisma Client to ensure the code inside `node_modules/.prisma/client` gets updated:
+
+```terminal
+prisma generate
+```
+
+#### Using Prisma Client to send queries to your database
+
+Once Prisma Client has been generated, you can import it in your code and send queries to your database. This is what the setup code looks like.
+
+##### Import and instantiate Prisma Client
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+```
+
+
+
+
+```js
+const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+```
+
+
+
+
+Now you can start sending queries via the generated Prisma Client API, here are a few sample queries. Note that all Prisma Client queries return _plain old JavaScript objects_.
+
+Learn more about the available operations in the [Prisma Client API reference](/orm/prisma-client).
+
+##### Retrieve all `User` records from the database
+
+```ts
+// Run inside `async` function
+const allUsers = await prisma.user.findMany()
+```
+
+##### Include the `posts` relation on each returned `User` object
+
+```ts
+// Run inside `async` function
+const allUsers = await prisma.user.findMany({
+ include: { posts: true },
+})
+```
+
+##### Filter all `Post` records that contain `"prisma"`
+
+```ts
+// Run inside `async` function
+const filteredPosts = await prisma.post.findMany({
+ where: {
+ OR: [
+ { title: { contains: 'prisma' } },
+ { content: { contains: 'prisma' } },
+ ],
+ },
+})
+```
+
+##### Create a new `User` and a new `Post` record in the same query
+
+```ts
+// Run inside `async` function
+const user = await prisma.user.create({
+ data: {
+ name: 'Alice',
+ email: 'alice@prisma.io',
+ posts: {
+ create: { title: 'Join us for Prisma Day 2020' },
+ },
+ },
+})
+```
+
+##### Update an existing `Post` record
+
+```ts
+// Run inside `async` function
+const post = await prisma.post.update({
+ where: { id: 42 },
+ data: { published: true },
+})
+```
+
+#### Usage with TypeScript
+
+Note that when using TypeScript, the result of this query will be _statically typed_ so that you can't accidentally access a property that doesn't exist (and any typos are caught at compile-time). Learn more about leveraging Prisma Client's generated types on the [Advanced usage of generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types) page in the docs.
+
+## Typical Prisma workflows
+
+As mentioned above, there are two ways for "getting" your data model into the Prisma schema. Depending on which approach you choose, your main Prisma workflow might look different.
+
+### Prisma Migrate
+
+With **Prisma Migrate**, Prisma's integrated database migration tool, the workflow looks as follows:
+
+1. Manually adjust your [Prisma data model](/orm/prisma-schema/data-model/models)
+1. Migrate your development database using the `prisma migrate dev` CLI command
+1. Use Prisma Client in your application code to access your database
+
+
+
+To learn more about the Prisma Migrate workflow, see:
+
+- [Deploying database changes with Prisma Migrate](/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate)
+
+* [Developing with Prisma Migrate](/orm/prisma-migrate)
+
+### SQL migrations and introspection
+
+If for some reason, you can not or do not want to use Prisma Migrate, you can still use introspection to update your Prisma schema from your database schema.
+The typical workflow when using **SQL migrations and introspection** is slightly different:
+
+1. Manually adjust your database schema using SQL or a third-party migration tool
+1. (Re-)introspect your database
+1. Optionally [(re-)configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names))
+1. (Re-)generate Prisma Client
+1. Use Prisma Client in your application code to access your database
+
+
+
+To learn more about the introspection workflow, please refer the [introspection section](/orm/prisma-schema/introspection).
diff --git a/docs/200-orm/050-overview/100-introduction/200-why-prisma.mdx b/docs/200-orm/050-overview/100-introduction/200-why-prisma.mdx
new file mode 100644
index 0000000000..2a895d874a
--- /dev/null
+++ b/docs/200-orm/050-overview/100-introduction/200-why-prisma.mdx
@@ -0,0 +1,95 @@
+---
+title: 'Why Prisma?'
+metaTitle: 'Why Prisma? Comparison with SQL query builders & ORMs'
+metaDescription: 'Learn about the motivation for Prisma and how it compares to other Node.js and TypeScript database tools like ORMs and SQL query builders.'
+---
+
+
+
+On this page, you'll learn about the motivation for Prisma and how it compares to other database tools like ORMs and SQL query builders.
+
+Working with relational databases is a major bottleneck in application development. Debugging SQL queries or complex ORM objects often consume hours of development time.
+
+Prisma makes it easy for developers to reason about their database queries by providing a clean and type-safe API for submitting database queries which returns _plain old JavaScript objects_.
+
+
+
+## TLDR
+
+Prisma's main goal is to make application developers more productive when working with databases. Here are a few examples of how Prisma achieves this:
+
+- **Thinking in objects** instead of mapping relational data
+- **Queries not classes** to avoid complex model objects
+- **Single source of truth** for database and application models
+- **Healthy constraints** that prevent common pitfalls and anti-patterns
+- **An abstraction that makes the right thing easy** ("pit of success")
+- **Type-safe database queries** that can be validated at compile time
+- **Less boilerplate** so developers can focus on the important parts of their app
+- **Auto-completion in code editors** instead of needing to look up documentation
+
+The remaining parts of this page discuss how Prisma compares to existing database tools.
+
+## Problems with SQL, ORMs and other database tools
+
+The main problem with the database tools that currently exist in the Node.js and TypeScript ecosystem is that they require a major tradeoff between _productivity_ and _control_.
+
+
+
+### Raw SQL: Full control, low productivity
+
+With raw SQL (e.g. using the native [`pg`](https://node-postgres.com/) or [`mysql`](https://github.com/mysqljs/mysql#readme) Node.js database drivers) you have full control over your database operations. However, productivity suffers as sending plain SQL strings to the database is cumbersome and comes with a lot of overhead (manual connection handling, repetitive boilerplate, ...).
+
+Another major issue with this approach is that you don't get any type safety for your query results. Of course, you can type the results manually but this is a huge amount of work and requires major refactorings each time you change your database schema or queries to keep the typings in sync.
+
+Furthermore, submitting SQL queries as plain strings means you don't get any autocompletion in your editors.
+
+### SQL query builders: High control, medium productivity
+
+A common solution that retains a high level of control and provides better productivity is to use a SQL query builder (e.g. [knex.js](https://knexjs.org/)). These sort of tools provide a programmatic abstraction to construct SQL queries.
+
+The biggest drawback with SQL query builders is that application developers still need to think about their data in terms of SQL. This incurs a cognitive and practical cost of translating relational data into objects. Another issue is that it's too easy to shoot yourself in the foot if you don't know exactly what you're doing in your SQL queries.
+
+### ORMs: Less control, better productivity
+
+ORMs abstract away from SQL by letting you _define your application models as classes_, these classes are mapped to tables in the database.
+
+> "Object relational mappers" (ORMs) exist to bridge the gap between the programmers' friend (the object), and the database's primitive (the relation). The reasons for these differing models are as much cultural as functional: programmers like objects because they encapsulate the state of a single thing in a running program. Databases like relations because they better suit whole-dataset constraints and efficient access patterns for the entire dataset.
+>
+> [The Troublesome Active Record Pattern, Cal Paterson (2020)](https://calpaterson.com/activerecord.html)
+
+You can then read and write data by calling methods on the instances of your model classes.
+
+This is way more convenient and comes closer to the mental model developers have when thinking about their data. So, what's the catch?
+
+> ORM represents a quagmire which starts well, gets more complicated as time passes, and before long entraps its users in a commitment that has no clear demarcation point, no clear win conditions, and no clear exit strategy.
+>
+> [The Vietnam of Computer Science, Ted Neward (2006)](http://blogs.tedneward.com/post/the-vietnam-of-computer-science/)
+
+As an application developer, the mental model you have for your data is that of an _object_. The mental model for data in SQL on the other hand are _tables_.
+
+The divide between these two different representations of data is often referred to as the [object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch). The object-relational impedance mismatch also is a major reason why many developers don't like working with traditional ORMs.
+
+As an example, consider how data is organized and relationships are handled with each approach:
+
+- **Relational databases**: Data is typically normalized (flat) and uses foreign keys to link across entities. The entities then need to be JOINed to manifest the actual relationships.
+- **Object-oriented**: Objects can be deeply nested structures where you can traverse relationships simply by using dot notation.
+
+This alludes to one of the major pitfalls with ORMs: While they make it _seem_ that you can simply traverse relationships using familiar dot notation, under the hood the ORM generates SQL JOINs which are expensive and have the potential to drastically slow down your application (one symptom of this is the [n+1 problem](https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping)).
+
+To conclude: The appeal of ORMs is the premise of abstracting away the relational model and thinking about your data purely in terms of objects. While the premise is great, it's based on the wrong assumption that relational data can easily be mapped to objects which leads to lots of complications and pitfalls.
+
+## Application developers should care about data – not SQL
+
+Despite being developed in the 1970s(!), SQL has stood the test of time in an impressive manner. However, with the advancement and modernization of developers tools, it's worth asking if SQL really is the best abstraction for application developers to work with?
+
+After all, **developers should only care about the _data_ they need to implement a feature** and not spend time figuring out complicated SQL queries or massaging query results to fit their needs.
+
+There's another argument to be made against SQL in application development. The power of SQL can be a blessing if you know exactly what you're doing, but its complexity can be a curse. There are a lot of [anti-patterns](https://www.slideshare.net/billkarwin/sql-antipatterns-strike-back) and pitfalls that even experienced SQL users struggle to anticipate, often at the cost of performance and hours of debugging time.
+
+Developers should be able to ask for the data they need instead of having to worry about "doing the right thing" in their SQL queries. They should be using an abstraction that makes the right decisions for them. This can mean that the abstraction imposes certain "healthy" constraints that prevent developers from making mistakes.
+
+## Prisma makes developers productive
+
+Prisma's main goal is to make application developers more productive when working with databases. Considering the tradeoff between productivity and control again, this is how Prisma fits in:
+
+
diff --git a/docs/200-orm/050-overview/100-introduction/250-should-you-use-prisma.mdx b/docs/200-orm/050-overview/100-introduction/250-should-you-use-prisma.mdx
new file mode 100644
index 0000000000..4c5bd7ec49
--- /dev/null
+++ b/docs/200-orm/050-overview/100-introduction/250-should-you-use-prisma.mdx
@@ -0,0 +1,112 @@
+---
+title: 'Should you use Prisma?'
+metaTitle: 'Should you use Prisma as a Node.js/TypeScript ORM?'
+metaDescription: 'Prisma is a new kind of ORM. This page explains when Prisma would be a good fit, and provides alternatives for other scenarios.'
+tocDepth: 3
+toc: true
+---
+
+
+
+Prisma is a new kind of ORM that - like any other tool - comes with its own tradeoffs. This page explains when Prisma would be a good fit, and provides alternatives for other scenarios.
+
+
+
+## Prisma likely _is_ a good fit for you if ...
+
+### ... you are building a server-side application that talks to a database
+
+This is the main use case for Prisma. Server-side applications typically are API servers that expose data operations via technologies like REST, GraphQL or gRPC. They are commonly built as microservices or monolithic apps and deployed via long-running servers or serverless functions. Prisma is a great fit for all of these application and deployment models.
+
+Refer to the full list of databases (relational, NoSQL, and NewSQL) that Prisma [supports](/orm/reference/supported-databases).
+
+### ... you care about productivity and developer experience
+
+Productivity and developer experience are core to how we're building our tools. We're looking to build developer-friendly abstractions for tasks that are complex, error-prone and time-consuming when performed manually.
+
+No matter if you're a SQL newcomer or veteran, Prisma will give you a significant productivity boost for the most common database workflows.
+
+Here are a couple of the guiding principles and general practices we apply when designing and building our tools:
+
+- [make the right thing easy](https://www.jason.af/right-thing-easy-thing/)
+- [pit of success](https://blog.codinghorror.com/falling-into-the-pit-of-success/)
+- offer intelligent autocompletion where possible
+- build powerful editor extensions (e.g. for [VS Code](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma))
+- go the extra mile to achieve full type-safety
+
+### ... you are working in a team
+
+Prisma shines especially when used in collaborative environments.
+
+The declarative [Prisma schema](/orm/prisma-schema) provides an overview of the current state of the database that's easy to understand for everyone. This is a major improvement to traditional workflows where developers have to dig through migration files to understand the current table structure.
+
+[Prisma Client](/orm/prisma-client)'s minimal API surface enables developers to pick it up quickly without much learning overhead, so onboarding new developers to a team becomes a lot smoother.
+
+The [Prisma Migrate](/orm/prisma-migrate) workflows are designed in a way to cover database schema changes in collaborative environments. From the initial schema creation up to the point of deploying schema changes to production and resolving conflicts that were introduced by parallel modifications, Prisma Migrate has you covered.
+
+### ... you want a tool that holistically covers your database workflows
+
+Prisma is a lot more than "just another ORM". We are building a database toolkit that covers the daily workflows of application developers that interact with databases. A few examples are:
+
+- querying (with [Prisma Client](/orm/prisma-client))
+- data modeling (in the [Prisma schema](/orm/prisma-schema))
+- migrations (with [Prisma Migrate](/orm/prisma-migrate))
+- prototyping (via [`prisma db push`](/orm/reference/prisma-cli-reference#db-push))
+- seeding (via [`prisma db seed`](/orm/reference/prisma-cli-reference#db-seed))
+- visual viewing and editing (with [Prisma Studio](https://www.prisma.io/studio))
+
+### ... you value type-safety
+
+Prisma is the only _fully_ type-safe ORM in the TypeScript ecosystem. The generated Prisma Client ensures typed query results even for partial queries and relations. You can learn more about this in the [type-safety comparison with TypeORM](/orm/more/comparisons/prisma-and-typeorm#type-safety).
+
+### ... you want an ORM with a transparent development process, proper maintenance & support
+
+Development of Prisma's open source tools is happening in the open. Most of it happens directly on GitHub in the main [`prisma/prisma`](https://github.com/prisma/prisma) repo:
+
+- issues and PRs in our repos are triaged and prioritized (usually within 1-2 days)
+- there is a public [roadmap](https://pris.ly/roadmap) that is kept up to date with our plans
+- new [releases](https://github.com/prisma/prisma/releases) with new features and improvements are issued every three weeks
+- we have a dedicated support team that responds to questions in [GitHub Discussions](https://github.com/prisma/prisma/discussions)
+- our product team is always eager to talk to you in the `#product-feedback` channel on Slack to get your feedback about Prisma
+
+### ... you want to be part of an awesome community
+
+Prisma has a lively [community](https://www.prisma.io/community), which you can find on [Slack](https://slack.prisma.io) and [Discord](https://discord.gg/KQyTW2H5ca). We also regularly host Meetups, conferences and other developer-focused events. Join us!
+
+## Prisma likely is _not_ a good fit for you if ...
+
+### ... you need _full_ control over all database queries
+
+Prisma is an abstraction. As such, an inherent tradeoff of Prisma is a reduced amount of control in exchange for higher productivity. This means, the [Prisma Client API](/orm/prisma-client) might have less capabilities in some scenarios than you get with plain SQL.
+
+If your application has requirements for database queries that Prisma does not provide and the workarounds are too costly, you might be better off with a tool that allows you to exercise full control over your database operations using plain SQL.
+
+> **Note**: If you can work around a certain limitation but still would like to see an improvement in the way how Prisma handles the situation, we encourage you to create a [feature request](https://github.com/prisma/prisma/issues/new?assignees=&labels=&template=feature_request.md&title=) on GitHub so that our Product and Engineering teams can look into it.
+
+_Alternatives_: SQL drivers (e.g. [`node-postgres`](https://node-postgres.com/), [`mysql`](https://github.com/mysqljs/mysql#readme), [`sqlite3`](https://github.com/mapbox/node-sqlite3#README), ...)
+
+### ... you do not want to write any code for your backend
+
+If you don't want to write any code for your backend and just be able to generate your API server and the database out-of-the-box, you might rather choose a Backend-as-a-Service (BaaS) for your project.
+
+With a BaaS, you can typically configure your data model via a high-level API (e.g. [GraphQL SDL](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51)) or a visual editor. Based on this data model, the BaaS generates a CRUD API and provisions a database for you. With this setup, you typically don't have control over the infrastructure the API server and database are running on.
+
+With Prisma, you are building the backend yourself using Node.js or TypeScript. This means you'll have to do a lot more coding work compared to using a BaaS. The benefit of this approach is that you have full flexibility for building, deploying, scaling and maintaining your backend and are not dependent on 3rd party software for a crucial part of your stack.
+
+_Alternatives_: [AWS AppSync](https://aws.amazon.com/appsync/), [8base](https://www.8base.com/), [Nhost](https://nhost.io/), [Supabase](https://supabase.com/), [Firebase](https://firebase.google.com/), [Amplication](https://amplication.com/)
+
+### ... you want a CRUD GraphQL API without writing any code
+
+While tools like the [`nexus-plugin-prisma`](https://nexusjs.org/docs/plugins/prisma/overview) and [`typegraphql-prisma`](https://github.com/MichalLytek/typegraphql-prisma#readme) allow you to quickly generate CRUD operations for your Prisma models in a GraphQL API, these approaches still require you to set up your GraphQL server manually and do some work to expose GraphQL queries and mutations for the models defined in your Prisma schema.
+
+If you want to get a GraphQL endpoint for your database out-of-the box, other tools might be better suited for your use case.
+
+_Alternatives_: [Hasura](https://hasura.io/), [Postgraphile](https://www.graphile.org/postgraphile/)
+
+### ... you want to use raw, type-safe SQL for querying your database
+
+While Prisma does allow you to [send plain SQL queries](/orm/prisma-client/queries/raw-database-access/raw-queries) to your database, it might not be the best fit if you prefer to work with a SQL-based abstraction that you want to be type-safe. Prisma's main benefit is to provide an abstraction layer that makes you more productive compared to writing SQL.
+
+If you're a solo developer that is very comfortable with SQL, and you just want to be sure that your database layer is type-safe, a lower-level TypeScript database library might be better for you.
+
+_Alternatives_: [Slonik](https://github.com/gajus/slonik), [pgtyped](https://github.com/adelsz/pgtyped), [Zapatos](https://jawj.github.io/zapatos/), [postgres-schema-builder](https://github.com/yss14/postgres-schema-builder)
diff --git a/docs/200-orm/050-overview/100-introduction/300-data-modeling.mdx b/docs/200-orm/050-overview/100-introduction/300-data-modeling.mdx
new file mode 100644
index 0000000000..ac5ff0e3a2
--- /dev/null
+++ b/docs/200-orm/050-overview/100-introduction/300-data-modeling.mdx
@@ -0,0 +1,246 @@
+---
+title: 'Data modeling'
+metaTitle: 'Data modeling with Prisma'
+metaDescription: 'Learn how data modeling with Prisma differs from data modeling with SQL or ORMs. Prisma uses a declarative data modeling language to describe a database schema.'
+---
+
+## What is data modeling?
+
+The term _data modeling_ refers to the **process of defining the shape and structure of the objects in an application**, these objects are often called "application models". In relational databases (like PostgreSQL), they are stored in _tables_ . When using document databases (like MongoDB), they are stored in _collections_.
+
+Depending on the domain of your application, the models will be different. For example, if you're writing a blogging application, you might have models such as _blog_, _author_, _article_. When writing a car-sharing app, you probably have models like _driver_, _car_, _route_. Application models enable you to represent these different entities in your code by creating respective _data structures_.
+
+When modeling data, you typically ask questions like:
+
+- What are the main entities/concepts in my application?
+- How do they relate to each other?
+- What are their main characteristics/properties?
+- How can they be represented with my technology stack?
+
+## Data modeling without Prisma
+
+Data modeling typically needs to happen on (at least) two levels:
+
+- On the **database** level
+- On the **application** level (i.e., in your programming language)
+
+The way that the application models are represented on both levels might differ due to a few reasons:
+
+- Databases and programming languages use different data types
+- Relations are represented differently in a database than in a programming language
+- Databases typically have more powerful data modeling capabilities, like indexes, cascading deletes, or a variety of additional constraints (e.g. unique, not null, ...)
+- Databases and programming languages have different technical constraints
+
+### Data modeling on the database level
+
+#### Relational databases
+
+In relational databases, models are represented by _tables_. For example, you might define a `users` table to store information about the users of your application. Using PostgreSQL, you'd define it as follows:
+
+```sql
+CREATE TABLE users (
+ user_id SERIAL PRIMARY KEY NOT NULL,
+ name VARCHAR(255),
+ email VARCHAR(255) UNIQUE NOT NULL,
+ isAdmin BOOLEAN NOT NULL DEFAULT false
+);
+```
+
+A visual representation of the `users` table with some random data might look as follows:
+
+| `user_id` | `name` | `email` | `isAdmin` |
+| :-------- | :------ | :---------------- | :-------- |
+| `1` | `Alice` | `alice@prisma.io` | `false` |
+| `2` | `Bob` | `bob@prisma.io` | `false` |
+| `3` | `Sarah` | `sarah@prisma.io` | `true` |
+
+It has the following columns:
+
+- `user_id`: An integer that increments with every new record in the `users` table. It also represents the [primary key](https://en.wikipedia.org/wiki/Primary_key) for each record.
+- `name`: A string with at most 255 characters.
+- `email`: A string with at most 255 characters. Additionally, the added constraints express that no two records can have duplicate values for the `email` column, and that _every_ record needs to have a value for it.
+- `isAdmin`: A boolean that indicates whether the user has admin rights (default value: `false`)
+
+#### MongoDB
+
+In MongoDB databases, models are represented by _collections_ and contain _documents_ that can have any structure:
+
+```js
+{
+ _id: '607ee94800bbe41f001fd568',
+ slug: 'prisma-loves-mongodb',
+ title: 'Prisma <3 MongoDB',
+ body: "This is my first post. Isn't MongoDB + Prisma awesome?!"
+}
+```
+
+Prisma Client currently expects a consistent model and [normalized model design](https://docs.mongodb.com/manual/core/data-model-design/#normalized-data-models). This means that:
+
+- If a model or field is not present in the Prisma schema, it is ignored
+- If a field is mandatory but not present in the MongoDB dataset, you will get an error
+
+### Data modeling on the application level
+
+In addition to creating the tables that represent the entities from your application domain, you also need to create application models in your programming language. In object-oriented languages, this is often done by creating _classes_ to represent your models. Depending on the programming language, this might also be done with _interfaces_ or _structs_.
+
+There often is a strong correlation between the tables in your database and the models you define in your code. For example, to represent records from the aforementioned `users` table in your application, you might define a JavaScript (ES6) class looking similar to this:
+
+```js
+class User {
+ constructor(user_id, name, email, isAdmin) {
+ this.user_id = user_id
+ this.name = name
+ this.email = email
+ this.isAdmin = isAdmin
+ }
+}
+```
+
+When using TypeScript, you might define an interface instead:
+
+```js
+interface User {
+ user_id: number
+ name: string
+ email: string
+ isAdmin: boolean
+}
+```
+
+Notice how the `User` model in both cases has the same properties as the `users` table in the previous example. While it's often the case that there's a 1:1 mapping between database tables and application models, it can also happen that models are represented completely differently in the database and your application.
+
+With this setup, you can retrieve records from the `users` table and store them as instances of your `User` type. The following example code snippet uses [`pg`](https://node-postgres.com/) as the driver for PostgreSQL and creates a `User` instance based on the above defined JavaScript class:
+
+```js
+const resultRows = await client.query('SELECT * FROM users WHERE user_id = 1')
+const userData = resultRows[0]
+const user = new User(
+ userData.user_id,
+ userData.name,
+ userData.email,
+ userData.isAdmin
+)
+// user = {
+// user_id: 1,
+// name: "Alice",
+// email: "alice@prisma.io",
+// isAdmin: false
+// }
+```
+
+Notice that in these examples, the application models are "dumb", meaning they don't implement any logic but their sole purpose is to carry data as _plain old JavaScript objects_.
+
+### Data modeling with ORMs
+
+ORMs are commonly used in object-oriented languages to make it easier for developers to work with a database. The key characteristic of an ORM is that it lets you model your application data in terms of _classes_ which are mapped to _tables_ in the underlying database.
+
+The main difference compared to the approaches explained above is these classes not only carry data but also implement a substantial amount of logic. Mostly for storage, retrieval, serialization, and deserialization, but sometimes they also implement business logic that's specific to your application.
+
+This means, you don't write SQL statements to read and write data in the database, but instead the instances of your model classes provide an API to store and retrieve data.
+
+[Sequelize](https://sequelize.org/) is a popular ORM in the Node.js ecosystem, this is how you'd define the same `User` model from the sections before using Sequelize's modeling approach:
+
+```js
+class User extends Model {}
+User.init(
+ {
+ user_id: {
+ type: Sequelize.INTEGER,
+ primaryKey: true,
+ autoIncrement: true,
+ },
+ name: Sequelize.STRING(255),
+ email: {
+ type: Sequelize.STRING(255),
+ unique: true,
+ },
+ isAdmin: Sequelize.BOOLEAN,
+ },
+ { sequelize, modelName: 'user' }
+)
+```
+
+To get an example with this `User` class to work, you still need to create the corresponding table in the database. With Sequelize, you have two ways of doing this:
+
+- Run `User.sync()` (typically not recommended for production)
+- Use [Sequelize migrations](https://sequelize.org/v5/manual/migrations.html) to change your database schema
+
+Note that you'll never instantiate the `User` class manually (using `new User(...)`) as was shown in the previous section, but rather call _static_ methods on the `User` class which then return the `User` model instances:
+
+```js
+const user = await User.findByPk(42)
+```
+
+The call to `findByPk` creates a SQL statement to retrieve the `User` record that's identified by the ID value `42`.
+
+The resulting `user` object is an instance of Sequelize's `Model` class (because `User` inherits from `Model`). It's not a POJO, but an object that implements additional behavior from Sequelize.
+
+## Data modeling with Prisma
+
+Depending on which parts of Prisma you want to use in your application, the data modeling flow looks slightly different. The following two sections explain the workflows for using [**only Prisma Client**](#using-only-prisma-client) and using [**Prisma Client and Prisma Migrate**](#using-prisma-client-and-prisma-migrate).
+
+No matter which approach though, with Prisma you never create application models in your programming language by manually defining classes, interfaces, or structs. Instead, the application models are defined in your [Prisma schema](/orm/prisma-schema):
+
+- **Only Prisma Client**: Application models in the Prisma schema are _generated based on the introspection of your database schema_. Data modeling happens primarily on the database-level.
+- **Prisma Client and Prisma Migrate**: Data modeling happens in the Prisma schema by _manually adding application models_ to it. Prisma Migrate maps these application models to tables in the underlying database (currently only supported for relational databases).
+
+As an example, the `User` model from the previous example would be represented as follows in the Prisma schema:
+
+```prisma
+model User {
+ user_id Int @id @default(autoincrement())
+ name String?
+ email String @unique
+ isAdmin Boolean @default(false)
+}
+```
+
+Once the application models are in your Prisma schema (whether they were added through introspection or manually by you), the next step typically is to generate Prisma Client which provides a programmatic and type-safe API to read and write data in the shape of your application models.
+
+Prisma Client uses TypeScript [type aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases) to represent your application models in your code. For example, the `User` model would be represented as follows in the generated Prisma Client library:
+
+```ts
+export declare type User = {
+ id: number
+ name: string | null
+ email: string
+ isAdmin: boolean
+}
+```
+
+In addition to the generated types, Prisma Client also provides a data access API that you can use once you've installed the `@prisma/client` package:
+
+```js
+import { PrismaClient } from '@prisma/client'
+// or
+// const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+
+// use inside an `async` function to `await` the result
+await prisma.user.findUnique(...)
+await prisma.user.findMany(...)
+await prisma.user.create(...)
+await prisma.user.update(...)
+await prisma.user.delete(...)
+await prisma.user.upsert(...)
+```
+
+### Using only Prisma Client
+
+When using only Prisma Client and _not_ using Prisma Migrate in your application, data modeling needs to happen on the database level via SQL. Once your SQL schema is ready, you use Prisma's introspection feature to add the application models to your Prisma schema. Finally, you generate Prisma Client which creates the types as well as the programmatic API for you to read and write data in your database.
+
+Here is an overview of the main workflow:
+
+1. Change your database schema using SQL (e.g. `CREATE TABLE`, `ALTER TABLE`, ...)
+1. Run `prisma db pull` to introspect the database and add application models to the Prisma schema
+1. Run `prisma generate` to update your Prisma Client API
+
+### Using Prisma Client and Prisma Migrate
+
+When using [Prisma Migrate](/orm/prisma-migrate), you define your application in the Prisma schema and with relational databases use the `prisma migrate` subcommand to generate plain SQL migration files, which you can edit before applying. With MongoDB, you use `prisma db push` instead which applies the changes to your database directly.
+
+Here is an overview of the main workflow:
+
+1. Manually change your application models in the Prisma schema (e.g. add a new model, remove an existing one, ...)
+1. Run `prisma migrate dev` to create and apply a migration or run `prisma db push` to apply the changes directly (in both cases Prisma Client is automatically generated)
diff --git a/docs/200-orm/050-overview/100-introduction/index.mdx b/docs/200-orm/050-overview/100-introduction/index.mdx
new file mode 100644
index 0000000000..90a1c1af59
--- /dev/null
+++ b/docs/200-orm/050-overview/100-introduction/index.mdx
@@ -0,0 +1,19 @@
+---
+title: 'Introduction'
+metaTitle: 'Introduction (Overview)'
+metaDescription: "This section gives a high-level overview of what Prisma is and how it works. It's a great starting point for Prisma newcomers!"
+---
+
+
+
+This page gives a high-level overview of what Prisma is and how it works.
+
+If you want to get started with a _practical introduction_ and learn about the Prisma Client API, head over to the [**Getting Started**](/getting-started) documentation.
+
+To learn more about the _motivation_ for Prisma, check out the [**Why Prisma?**](/orm/overview/introduction/why-prisma) page.
+
+
+
+## In this section
+
+
diff --git a/docs/200-orm/050-overview/100-introduction/node-js-db-tools-tradeoffs.png b/docs/200-orm/050-overview/100-introduction/node-js-db-tools-tradeoffs.png
new file mode 100644
index 0000000000..8037da2e08
Binary files /dev/null and b/docs/200-orm/050-overview/100-introduction/node-js-db-tools-tradeoffs.png differ
diff --git a/docs/200-orm/050-overview/100-introduction/prisma-makes-devs-productive.png b/docs/200-orm/050-overview/100-introduction/prisma-makes-devs-productive.png
new file mode 100644
index 0000000000..fcd68959c6
Binary files /dev/null and b/docs/200-orm/050-overview/100-introduction/prisma-makes-devs-productive.png differ
diff --git a/docs/200-orm/050-overview/100-introduction/prisma-rest-apis.png b/docs/200-orm/050-overview/100-introduction/prisma-rest-apis.png
new file mode 100644
index 0000000000..9e374a2fa0
Binary files /dev/null and b/docs/200-orm/050-overview/100-introduction/prisma-rest-apis.png differ
diff --git a/docs/200-orm/050-overview/100-introduction/user-post-relation-1-n.png b/docs/200-orm/050-overview/100-introduction/user-post-relation-1-n.png
new file mode 100644
index 0000000000..bab7611d32
Binary files /dev/null and b/docs/200-orm/050-overview/100-introduction/user-post-relation-1-n.png differ
diff --git a/docs/200-orm/050-overview/100-introduction/user-table.png b/docs/200-orm/050-overview/100-introduction/user-table.png
new file mode 100644
index 0000000000..a44df94e25
Binary files /dev/null and b/docs/200-orm/050-overview/100-introduction/user-table.png differ
diff --git a/docs/200-orm/050-overview/100-introduction/user-table.svg b/docs/200-orm/050-overview/100-introduction/user-table.svg
new file mode 100644
index 0000000000..1bc2e636a6
--- /dev/null
+++ b/docs/200-orm/050-overview/100-introduction/user-table.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/200-orm/050-overview/300-prisma-in-your-stack/01-rest.mdx b/docs/200-orm/050-overview/300-prisma-in-your-stack/01-rest.mdx
new file mode 100644
index 0000000000..cb65d49966
--- /dev/null
+++ b/docs/200-orm/050-overview/300-prisma-in-your-stack/01-rest.mdx
@@ -0,0 +1,166 @@
+---
+title: 'REST'
+metaTitle: 'Building REST APIs with Prisma'
+metaDescription: 'This page gives an overview of the most important things when building REST APIs with Prisma. It shows practical examples and the supported libraries.'
+---
+
+
+
+When building REST APIs, Prisma Client can be used inside your _route controllers_ to send databases queries.
+
+
+
+
+
+## Supported libraries
+
+As Prisma Client is "only" responsible for sending queries to your database, it can be combined with any HTTP server library or web framework of your choice.
+
+Here's a non-exhaustive list of libraries and frameworks you can use with Prisma:
+
+- [Express](https://expressjs.com/)
+- [koa](https://koajs.com/)
+- [hapi](https://hapi.dev/)
+- [Fastify](https://www.fastify.io/)
+- [Sails](https://sailsjs.com/)
+- [AdonisJs](https://adonisjs.com/)
+- [NestJS](https://nestjs.com/)
+- [Next.js](https://nextjs.org/)
+- [Foal TS](https://foalts.org/)
+- [Polka](https://github.com/lukeed/polka)
+- [Micro](https://github.com/zeit/micro)
+- [Feathers](https://feathersjs.com/)
+- [Remix](https://remix.run/)
+
+## REST API server example
+
+Assume you have a Prisma schema that looks similar to this:
+
+```prisma
+datasource db {
+ provider = "sqlite"
+ url = "file:./dev.db"
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String?
+ published Boolean @default(false)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+```
+
+You can now implement route controller (e.g. using Express) that use the generated [Prisma Client API](/orm/prisma-client) to perform a database operation when an incoming HTTP request arrives. This page only shows few sample code snippets; if you want to run these code snippets, you can use a [REST API example](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-express).
+
+#### `GET`
+
+```ts
+app.get('/feed', async (req, res) => {
+ const posts = await prisma.post.findMany({
+ where: { published: true },
+ include: { author: true },
+ })
+ res.json(posts)
+})
+```
+
+Note that the `feed` endpoint in this case returns a nested JSON response of `Post` objects that _include_ an `author` object. Here's a sample response:
+
+```json
+[
+ {
+ "id": "21",
+ "title": "Hello World",
+ "content": "null",
+ "published": "true",
+ "authorId": 42,
+ "author": {
+ "id": "42",
+ "name": "Alice",
+ "email": "alice@prisma.io"
+ }
+ }
+]
+```
+
+#### `POST`
+
+```ts
+app.post(`/post`, async (req, res) => {
+ const { title, content, authorEmail } = req.body
+ const result = await prisma.post.create({
+ data: {
+ title,
+ content,
+ published: false,
+ author: { connect: { email: authorEmail } },
+ },
+ })
+ res.json(result)
+})
+```
+
+#### `PUT`
+
+```ts
+app.put('/publish/:id', async (req, res) => {
+ const { id } = req.params
+ const post = await prisma.post.update({
+ where: { id: Number(id) },
+ data: { published: true },
+ })
+ res.json(post)
+})
+```
+
+#### `DELETE`
+
+```ts
+app.delete(`/post/:id`, async (req, res) => {
+ const { id } = req.params
+ const post = await prisma.post.delete({
+ where: {
+ id: Number(id),
+ },
+ })
+ res.json(post)
+})
+```
+
+## Ready-to-run example projects
+
+You can find several ready-to-run examples that show how to implement a REST API with Prisma Client, as well as build full applications, in the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository.
+
+### TypeScript
+
+| **Example** | **Stack** | **Description** |
+| ----------------------------------------------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------- |
+| [`rest-express`](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-express) | Backend only | REST API with Express for TypeScript |
+| [`rest-fastify`](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-fastify) | Backend only | REST API using Fastify and Prisma Client. |
+| [`rest-hapi`](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-hapi) | Backend only | REST API using hapi and Prisma Client |
+| [`rest-nestjs`](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-nestjs) | Backend only | Nest.js app (Express) with a REST API |
+| [`rest-nextjs-express`](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-nextjs-express) | Fullstack | Next.js app (React, Express) and Prisma Client |
+| [`rest-nextjs-api-routes`](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-nextjs-api-routes) | Fullstack | Next.js app (React) with a REST API |
+| [`rest-nextjs-api-routes-auth`](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-nextjs-api-routes-auth) | Fullstack | Implement authentication using NextAuth.js |
+
+### JavaScript
+
+| **Example** | **Stack** | **Description** |
+| ----------------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------- |
+| [`rest-express`](https://github.com/prisma/prisma-examples/tree/latest/javascript/rest-express) | Backend only | REST API using Express and Prisma Client |
+| [`rest-fastify`](https://github.com/prisma/prisma-examples/tree/latest/javascript/rest-fastify) | Backend only | REST API using Fastify and Prisma Client |
+| [`rest-nextjs`](https://github.com/prisma/prisma-examples/tree/latest/javascript/rest-nextjs) | Fullstack | Next.js app (React) with a REST API |
+| [`rest-nuxtjs`](https://github.com/prisma/prisma-examples/tree/latest/javascript/rest-nuxtjs) | Fullstack | App with NuxtJs using Vue (frontend), Express, and Prisma Client |
diff --git a/docs/200-orm/050-overview/300-prisma-in-your-stack/02-graphql.mdx b/docs/200-orm/050-overview/300-prisma-in-your-stack/02-graphql.mdx
new file mode 100644
index 0000000000..9482816f77
--- /dev/null
+++ b/docs/200-orm/050-overview/300-prisma-in-your-stack/02-graphql.mdx
@@ -0,0 +1,85 @@
+---
+title: 'GraphQL'
+metaTitle: 'Building GraphQL servers with Prisma'
+metaDescription: 'This page gives explains how to build GraphQL servers with Prisma. It shows how Prisma fits into the GraphQL ecosystem and provides practical examples.'
+---
+
+
+
+[GraphQL](https://graphql.org/) is a query language for APIs. It is often used as an alternative to RESTful APIs, but can also be used as an additional "gateway" layer on top of existing RESTful services.
+
+With Prisma, you can build GraphQL servers that connect to a database. Prisma is completely agnostic to the GraphQL tools you use. When building a GraphQL server, you can combine Prisma with tools like Apollo Server, GraphQL Yoga, TypeGraphQL, GraphQL.js, or pretty much any tool or library that you're using in your GraphQL server setup.
+
+
+
+## GraphQL servers under the hood
+
+A GraphQL server consists of two major components:
+
+- GraphQL schema (type definitions + resolvers)
+- HTTP server
+
+Note that a GraphQL schema can be written code-first or SDL-first. Check out this [article](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3) to learn more about these two approaches. If you like the SDL-first approach but still want to make your code type-safe, check out [GraphQL Code Generator](https://graphql-code-generator.com/) to generate various type definitions based on SDL.
+
+The GraphQL schema and HTTP server are typically handled by separate libraries. Here is an overview of current GraphQL server tools and their purpose:
+
+| Library (npm package) | Purpose | Compatible with Prisma | Prisma integration |
+| :-------------------- | :-------------------------- | :--------------------- | :----------------------------------------------------------------------------- |
+| `graphql` | GraphQL schema (code-first) | Yes | No |
+| `graphql-tools` | GraphQL schema (SDL-first) | Yes | No |
+| `type-graphql` | GraphQL schema (code-first) | Yes | [`typegraphql-prisma`](https://www.npmjs.com/package/typegraphql-prisma) |
+| `nexus` | GraphQL schema (code-first) | Yes | [`nexus-prisma`](https://graphql-nexus.github.io/nexus-prisma) _Early Preview_ |
+| `apollo-server` | HTTP server | Yes | n/a |
+| `express-graphql` | HTTP server | Yes | n/a |
+| `fastify-gql` | HTTP server | Yes | n/a |
+| `graphql-yoga` | HTTP server | Yes | n/a |
+
+In addition to these standalone and single-purpose libraries, there are several projects building integrated _application frameworks_:
+
+| Framework | Stack | Built by | Prisma | Description |
+| :---------------------------------- | :-------- | :------------------------------------------------ | :--------------------- | :------------------------------------- |
+| [Redwood.js](https://redwoodjs.com) | Fullstack | [Tom Preston-Werner](https://github.com/mojombo/) | Built on top of Prisma | _Bringing full-stack to the JAMstack._ |
+
+> **Note**: If you notice any GraphQL libraries/frameworks missing from the list, please let us know.
+
+## Prisma & GraphQL examples
+
+In the following section will find several ready-to-run examples that showcase how to use Prisma with different combinations of the tools mentioned in the table above.
+
+### TypeScript
+
+| Example | HTTP Server | GraphQL schema | Description |
+| :------------------------------------------------------------------------------------------------------------------------------- | :---------------------- | :-------------- | :--------------------------------------------------------------------------------------------- |
+| [GraphQL API (Pothos)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql) | `graphql-yoga` | `pothos` | GraphQL server based on [`graphql-yoga`](https://the-guild.dev/graphql/yoga-server) |
+| [GraphQL API (SDL-first)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-sdl-first) | `graphql-yoga` | n/a | GraphQL server based on the SDL-first approach |
+| [GraphQL API -- NestJs](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-nestjs) | `@nestjs/apollo` | n/a | GraphQL server based on [NestJS](https://nestjs.com/) |
+| [GraphQL API -- NestJs (SDL-first)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-nestjs-sdl-first) | `@nestjs/apollo` | n/a | GraphQL server based on [NestJS](https://nestjs.com/) |
+| [GraphQL API (Nexus)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-nexus) | `@apollo/server` | `nexus` | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) |
+| [GraphQL API (TypeGraphQL)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-typegraphql) | `apollo-server` | `type-graphql` | GraphQL server based on the code-first approach of [TypeGraphQL](https://typegraphql.com/) |
+| [GraphQL API (Auth)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-auth) | `apollo-server` | `nexus` | GraphQL server with email-password authentication & permissions |
+| [Fullstack app](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-nextjs) | `graphql-yoga` | `pothos` | Fullstack app with Next.js (React), Apollo Client, GraphQL Yoga and Pothos |
+| [GraphQL subscriptions](https://github.com/prisma/prisma-examples/tree/latest/typescript/subscriptions-pubsub) | `apollo-server` | `nexus` | GraphQL server implementing realtime GraphQL subscriptions |
+| [GraphQL API -- Hapi](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-hapi) | `apollo-server-hapi` | `nexus` | GraphQL server based on [Hapi](https://hapi.dev/) |
+| [GraphQL API -- Hapi (SDL-first)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-hapi-sdl-first) | `apollo-server-hapi` | `graphql-tools` | GraphQL server based on [Hapi](https://hapi.dev/) |
+| [GraphQL API -- Fastify](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-fastify) | `fastify` & `mercurius` | n/a | GraphQL server based on [Fastify](https://fastify.io/) and [Mercurius](https://mercurius.dev/) |
+| [GraphQL API -- Fastify (SDL-first)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-fastify-sdl-first) | `fastify` | `Nexus` | GraphQL server based on [Fastify](https://fastify.io/) and [Mercurius](https://mercurius.dev/) |
+
+### JavaScript (Node.js)
+
+| Demo | HTTP Server | GraphQL schema | Description |
+| :------------------------------------------------------------------------------------------------------------ | :-------------- | :-------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| [GraphQL API (Apollo Server)](https://github.com/prisma/prisma-examples/tree/latest/javascript/graphql) | `apollo-server` | `nexus` | GraphQL server based on [`apollo-server`](https://www.apollographql.com/docs/apollo-server/) |
+| [GraphQL API (Auth)](https://github.com/prisma/prisma-examples/tree/latest/javascript/graphql-auth) | `apollo-server` | `nexus` | GraphQL server with email-password authentication & permissions |
+| [GraphQL API (SDL-first)](https://github.com/prisma/prisma-examples/tree/latest/javascript/graphql-sdl-first) | `apollo-server` | `graphql-tools` | GraphQL server based on the SDL-first approach of [`graphql-tools`](https://www.apollographql.com/docs/graphql-tools/) (Apollo) |
+
+## FAQ
+
+### What is Prisma's role in a GraphQL server?
+
+No matter which of the above GraphQL tools/libraries you use, Prisma is used inside your GraphQL resolvers to connect to your database. It has the same role that any other ORM or SQL query builder would have inside your resolvers.
+
+In the resolver of a GraphQL query, Prisma typically reads data from the database to return it in the GraphQL response. In the resolver of a GraphQL mutation, Prisma typically also writes data to the database (e.g. creating new or updating existing records).
+
+## Other GraphQL Resources
+
+Prisma curates [GraphQL Weekly](https://www.graphqlweekly.com/), a newsletter highlighting resources and updates from the GraphQL community. Subscribe to keep up-to-date with GraphQL articles, videos, tutorials, libraries, and more.
diff --git a/docs/200-orm/050-overview/300-prisma-in-your-stack/03-fullstack.mdx b/docs/200-orm/050-overview/300-prisma-in-your-stack/03-fullstack.mdx
new file mode 100644
index 0000000000..637f008e44
--- /dev/null
+++ b/docs/200-orm/050-overview/300-prisma-in-your-stack/03-fullstack.mdx
@@ -0,0 +1,122 @@
+---
+title: 'Fullstack'
+metaTitle: 'Building fullstack applications with Prisma'
+metaDescription: 'This page gives explains how to build fullstack applications with Prisma. It shows how Prisma fits in with fullstack frameworks and provides practical examples'
+---
+
+
+
+Fullstack frameworks, such as Next.js, Remix or SvelteKit, blur the lines between the server and the client. These frameworks also provide different patterns for fetching and mutating data on the server.
+
+You can query your database using Prisma Client, using your framework of choice, from the server-side part of your application.
+
+
+
+## Supported frameworks
+
+Here's a non-exhaustive list of frameworks and libraries you can use with Prisma:
+
+- [Next.js](https://nextjs.org/)
+- [Remix](https://remix.run)
+- [SvelteKit](https://kit.svelte.dev/)
+- [Nuxt](https://nuxt.com/)
+- [Redwood](https://redwoodjs.com/)
+- [t3 stack — using tRPC](https://create.t3.gg/)
+- [Wasp](https://wasp-lang.dev/)
+
+## Fullstack app example (e.g. Next.js)
+
+Assume you have a Prisma schema that looks similar to this:
+
+```prisma
+datasource db {
+ provider = "sqlite"
+ url = "file:./dev.db"
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String?
+ published Boolean @default(false)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+```
+
+You can now implement the logic for querying your database using [Prisma Client API](/orm/prisma-client) inside `getServerSideProps`, `getStaticProps`, API routes, or using API libraries such as [tRPC](https://trpc.io/) and [GraphQL](https://graphql.org/).
+
+### ` getServerSideProps`
+
+```ts
+// (in /pages/index.tsx)
+
+// Alternatively, you can use `getStaticProps`
+// in place of `getServerSideProps`.
+export const getServerSideProps = async () => {
+ const feed = await prisma.post.findMany({
+ where: {
+ published: true,
+ },
+ })
+ return { props: { feed } }
+}
+```
+
+Next.js will pass the props to your React component where you can display the data from your database.
+
+### API Routes
+
+```ts
+// Fetch all posts (in /pages/api/posts.ts)
+const prisma = new PrismaClient()
+
+export default async function handle(req, res) {
+ const posts = await prisma.post.findMany({
+ where: {
+ published: true,
+ },
+ })
+ res.json(posts)
+}
+```
+
+Note that you can use Prisma inside of Next.js API routes to send queries to your database – with REST, GraphQL, and tRPC.
+
+You can then fetch data and display it in your frontend.
+
+## Ready-to-run fullstack example projects
+
+You can find several ready-to-run examples that show how to fullstack apps with Prisma Client in the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository.
+
+### TypeScript
+
+| **Example** | **Description** |
+| :----------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- |
+| [Next.js (API Routes)](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-nextjs-api-routes) | Fullstack Next.js app using `getServerSideProps` & API Routes |
+| [Next.js (GraphQL)](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-nextjs) | Fullstack Next.js app using GraphQL Yoga, Pothos, & Apollo Client |
+| [Next.js (tRPC)](https://github.com/prisma/prisma-examples/tree/latest/typescript/trpc-nextjs) | Fullstack Next.js app using tRPC |
+| [Next.js (API Routes with auth)](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-nextjs-api-routes-auth) | Fullstack Next.js app using `getServerSideProps`, API Routes, & [NextAuth](https://next-auth.js.org/) |
+| [Remix](https://github.com/prisma/prisma-examples/tree/latest/typescript/remix) | Fullstack Remix app using actions and loaders |
+| [SvelteKit](https://github.com/prisma/prisma-examples/tree/latest/typescript/sveltekit) | Fullstack Sveltekit app using actions and loaders |
+| [SvelteKit (REST API)](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-sveltekit) | Fullstack Sveltekit app using API routes |
+| [Nuxt (REST API)](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-nuxtjs) | Fullstack Nuxt app using API routes |
+
+### JavaScript
+
+| **Example** | **Description** |
+| :------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------ |
+| [Next.js (API Routes)](https://github.com/prisma/prisma-examples/tree/latest/javascript/rest-nextjs) | Fullstack Next.js app using `getServerSideProps` & API Routes |
+| [SvelteKit (REST API)](https://github.com/prisma/prisma-examples/tree/latest/javascript/rest-sveltekit) | Fullstack Sveltekit app using API routes |
+| [Nuxt (REST API)](https://github.com/prisma/prisma-examples/tree/latest/javascript/rest-nuxtjs) | Fullstack Nuxt app using API routes |
diff --git a/docs/200-orm/050-overview/300-prisma-in-your-stack/04-is-prisma-an-orm.mdx b/docs/200-orm/050-overview/300-prisma-in-your-stack/04-is-prisma-an-orm.mdx
new file mode 100644
index 0000000000..274decd080
--- /dev/null
+++ b/docs/200-orm/050-overview/300-prisma-in-your-stack/04-is-prisma-an-orm.mdx
@@ -0,0 +1,445 @@
+---
+title: 'Is Prisma an ORM?'
+metaTitle: 'Is Prisma an ORM? | What is an ORM?'
+metaDescription: 'Learn about how Prisma implements the Data Mapper ORM pattern and how it achieves the same goal as traditional ORMs without requiring you to map classes to tables as traditional ORMs do.'
+---
+
+
+
+To answer the question briefly: _Yes, Prisma is a new kind of ORM that fundamentally differs from traditional ORMs and doesn't suffer from many of the problems commonly associated with these_.
+
+Traditional ORMs provide an object-oriented way for working with relational databases by mapping tables to _model classes_ in your programming language. This approach leads to many problems that are caused by the [object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object%E2%80%93relational_impedance_mismatch).
+
+Prisma works fundamentally different compared to that. With Prisma, you define your models in the declarative [Prisma schema](/orm/prisma-schema) which serves as the single source of truth for your database schema and the models in your programming language. In your application code, you can then use Prisma Client to read and write data in your database in a type-safe manner without the overhead of managing complex model instances. This makes the process of querying data a lot more natural as well as more predictable since Prisma Client always returns plain JavaScript objects.
+
+In this article, you will learn in more detail about ORM patterns and workflows, how Prisma implements the Data Mapper pattern, and the benefits of Prisma's approach.
+
+
+
+## What are ORMs?
+
+If you're already familiar with ORMs, feel free to jump to the [next section](#prisma) on Prisma.
+
+### ORM Patterns - Active Record and Data Mapper
+
+ORMs provide a high-level database abstraction. They expose a programmatic interface through objects to create, read, delete, and manipulate data while hiding some of the complexity of the database.
+
+The idea with ORMs is that you define your models as **classes** that map to tables in a database. The classes and their instances provide you with a programmatic API to read and write data in the database.
+
+There are two common ORM patterns: [_Active Record_](https://en.wikipedia.org/wiki/Active_record_pattern) and [_Data Mapper_](https://en.wikipedia.org/wiki/Data_mapper_pattern) which differ in how they transfer data between objects and the database. While both patterns require you to define classes as the main building block, the most notable difference between the two is that the Data Mapper pattern decouples in-memory objects in the application code from the database and uses the data mapper layer to transfer data between the two. In practice, this means that with Data Mapper the in-memory objects (representing data in the database) don't even know that there’s a database present.
+
+#### Active Record
+
+_Active Record_ ORMs map model classes to database tables where the structure of the two representations is closely related, e.g. each field in the model class will have a matching column in the database table. Instances of the model classes wrap database rows and carry both the data and the access logic to handle persisting changes in the database. Additionally, model classes can carry business logic specific to the data in the model.
+
+The model class typically has methods that do the following:
+
+- Construct an instance of the model from an SQL query.
+- Construct a new instance for later insertion into the table.
+- Wrap commonly used SQL queries and return Active Record objects.
+- Update the database and insert into it the data in the Active Record.
+- Get and set the fields.
+- Implement business logic.
+
+#### Data Mapper
+
+_Data Mapper_ ORMs, in contrast to Active Record, decouple the application's in-memory representation of data from the database's representation. The decoupling is achieved by requiring you to separate the mapping responsibility into two types of classes:
+
+- **Entity classes**: The application's in-memory representation of entities which have no knowledge of the database
+- **Mapper classes**: These have two responsibilities:
+ - Transforming the data between the two representations.
+ - Generating the SQL necessary to fetch data from the database and persist changes in the database.
+
+Data Mapper ORMs allow for greater flexibility between the problem domain as implemented in code and the database. This is because the data mapper pattern allows you to hide the ways in which your database is implemented which isn’t an ideal way to think about your domain behind the whole data-mapping layer.
+
+One of the reasons that traditional data mapper ORMs do this is due to the structure of organizations where the two responsibilities would be handled by separate teams, e.g., [DBAs](https://en.wikipedia.org/wiki/Database_administrator) and backend developers.
+
+In reality, not all Data Mapper ORMs adhere to this pattern strictly. For example, [TypeORM](https://github.com/typeorm/typeorm/blob/master/docs/active-record-data-mapper.md#what-is-the-data-mapper-pattern), a popular ORM in the TypeScript ecosystem which supports both Active Record and Data Mapper, takes the following approach to Data Mapper:
+
+- Entity classes use decorators (`@Column`) to map class properties to table columns and are aware of the database.
+- Instead of mapper classes, _repository_ classes are used for querying the database and may contain custom queries. Repositories use the decorators to determine the mapping between entity properties and database columns.
+
+Given the following `User` table in the database:
+
+
+
+This is what the corresponding entity class would look like:
+
+```ts
+import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
+
+@Entity()
+export class User {
+ @PrimaryGeneratedColumn()
+ id: number
+
+ @Column({ name: 'first_name' })
+ firstName: string
+
+ @Column({ name: 'last_name' })
+ lastName: string
+
+ @Column({ unique: true })
+ email: string
+}
+```
+
+### Schema migration workflows
+
+A central part of developing applications that make use of a database is changing the database schema to accommodate new features and to better fit the problem you're solving. In this section, we'll discuss what [schema migrations](https://www.prisma.io/dataguide/types/relational/what-are-database-migrations) are and how they affect the workflow.
+
+Because the ORM sits between the developer and the database, most ORMs provide a **migration tool** to assist with the creation and modification of the database schema.
+
+A migration is a set of steps to take the database schema from one state to another. The first migration usually creates tables and indices. Subsequent migrations may add or remove columns, introduce new indices, or create new tables. Depending on the migration tool, the migration may be in the form of SQL statements or programmatic code which will get converted to SQL statements (as with [ActiveRecord](https://guides.rubyonrails.org/active_record_migrations.html) and [SQLAlchemy](https://alembic.sqlalchemy.org/en/latest/tutorial.html#create-a-migration-script)).
+
+Because databases usually contain data, migrations assist you with breaking down schema changes into smaller units which helps avoid inadvertent data loss.
+
+Assuming you were starting a project from scratch, this is what a full workflow would look like: you create a migration that will create the `User` table in the database schema and define the `User` entity class as in the example above.
+
+Then, as the project progresses and you decide you want to add a new `salutation` column to the `User` table, you would create another migration which would alter the table and add the `salutation` column.
+
+Let's take a look at how that would look like with a TypeORM migration:
+
+```ts
+import { MigrationInterface, QueryRunner } from 'typeorm'
+
+export class UserRefactoring1604448000 implements MigrationInterface {
+ async up(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`ALTER TABLE "User" ADD COLUMN "salutation" TEXT`)
+ }
+
+ async down(queryRunner: QueryRunner): Promise {
+ await queryRunner.query(`ALTER TABLE "User" DROP COLUMN "salutation"`)
+ }
+}
+```
+
+Once a migration is carried out and the database schema has been altered, the entity and mapper classes must also be updated to account for the new `salutation` column.
+
+With TypeORM that means adding a `salutation` property to the `User` entity class:
+
+```ts highlight=17,18;normal
+import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
+
+@Entity()
+export class User {
+ @PrimaryGeneratedColumn()
+ id: number
+
+ @Column({ name: 'first_name' })
+ firstName: string
+
+ @Column({ name: 'last_name' })
+ lastName: string
+
+ @Column({ unique: true })
+ email: string
+
+ @Column()
+ salutation: string
+}
+```
+
+Synchronizing such changes can be a challenge with ORMs because the changes are applied manually and are not easily verifiable programmatically. Renaming an existing column can be even more cumbersome and involve searching and replacing references to the column.
+
+> **Note:** Django's [makemigrations](https://docs.djangoproject.com/en/3.1/ref/django-admin/#django-admin-makemigrations) CLI generates migrations by inspecting changes in models which, similar to Prisma, does away with the synchronization problem.
+
+In summary, evolving the schema is a key part of building applications. With ORMs, the workflow for updating the schema involves using a migration tool to create a migration followed by updating the corresponding entity and mapper classes (depending on the implementation). As you'll see, Prisma takes a different approach to this.
+
+Now that you've seen what migrations are and how they fit into the development workflows, you will learn more about the benefits and drawbacks of ORMs.
+
+### Benefits of ORMs
+
+There are different reasons why developers choose to use ORMs:
+
+- ORMs facilitate implementing the domain model. The domain model is an object model that incorporates the behavior and data of your business logic. In other words, it allows you to focus on real business concepts rather than the database structure or SQL semantics.
+- ORMs help reduce the amount of code. They save you from writing repetitive SQL statements for common CRUD (Create Read Update Delete) operations and escaping user input to prevent vulnerabilities such as SQL injections.
+- ORMs require you to write little to no SQL (depending on your complexity you may still need to write the odd raw query). This is beneficial for developers who are not familiar with SQL but still want to work with a database.
+- Many ORMs abstract database-specific details. In theory, this means that an ORM can make changing from one database to another easier. It should be noted that in practice applications rarely change the database they use.
+
+As with all abstractions that aim to improve productivity, there are also drawbacks to using ORMs.
+
+### Drawbacks of ORMs
+
+The drawbacks of ORMs are not always apparent when you start using them. This section covers some of the commonly accepted ones:
+
+- With ORMs, you form an object graph representation of database tables which may lead to the [object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch). This happens when the problem you are solving forms a complex object graph which doesn't trivially map to a relational database. Synchronizing between two different representations of data, one in the relational database, and the other in-memory (with objects) is quite difficult. This is because objects are more flexible and varied in the way they can relate to each other compared to relational database records.
+- While ORMs handle the complexity associated with the problem, the synchronization problem doesn't go away. Any changes to the database schema or the data model require the changes to be mapped back to the other side. This burden is often on the developer. In the context of a team working on a project, database schema changes require coordination.
+- ORMs tend to have a large API surface due to the complexity they encapsulate. The flip side of not having to write SQL is that you spend a lot of time learning how to use the ORM. This applies to most abstractions, however without understanding how the database works, improving slow queries can be difficult.
+- Some _complex queries_ aren't supported by ORMs due to the flexibility that SQL offers. This problem is alleviated by raw SQL querying functionality in which you pass the ORM a SQL statement string and the query is run for you.
+
+Now that the costs and benefits of ORMs have been covered, you can better understand what Prisma is and how it fits in.
+
+## Prisma
+
+Prisma is a **next-generation ORM** that makes working with databases easy for application developers and features the following tools:
+
+- [**Prisma Client**](/orm/prisma-client): Auto-generated and type-safe database client for use in your application.
+- [**Prisma Migrate**](/orm/prisma-migrate): A declarative data modeling and migration tool.
+- [**Prisma Studio**](/orm/tools/prisma-studio): A modern GUI for browsing and managing data in your database.
+
+> **Note:** Since Prisma Client is the most prominent tool, we often refer to it as simply Prisma.
+
+The three tools use the [Prisma schema](/orm/prisma-schema) as a single source of truth for the database schema, your application's object schema, and the mapping between the two. It's defined by you and is your main configuration file for Prisma.
+
+Prisma makes you productive and confident in the software you're building with features such as _type safety_, rich auto-completion, and a natural API for fetching relations.
+
+In the next section, you will learn about how Prisma implements the Data Mapper ORM pattern.
+
+### How Prisma implements the Data Mapper pattern
+
+As mentioned earlier in the article, the Data Mapper pattern aligns well with organizations where the database and application are owned by different teams.
+
+With the rise of modern cloud environments with managed database services and DevOps practices, more teams embrace a cross-functional approach, whereby teams own both the full development cycle including the database and operational concerns.
+
+Prisma enables the evolution of the DB schema and object schema in tandem, thereby reducing the need for deviation in the first place, while still allowing you to keep your application and database somewhat decoupled using `@map` attributes. While this may seem like a limitation, it prevents the domain model's evolution (through the object schema) from getting imposed on the database as an afterthought.
+
+To understand how Prisma's implementation of the Data Mapper pattern differs conceptually to traditional Data Mapper ORMs, here's a brief comparison of their concepts and building blocks:
+
+| Concept | Description | Building block in traditional ORMs | Building block in Prisma | Source of truth in Prisma |
+| --------------- | -------------------------------------------------------------------- | ---------------------------------------------- | ------------------------------------ | ------------------------------------ |
+| Object schema | The in-memory data structures in your applications | Model classes | Generated TypeScript types | Models in the Prisma schema |
+| Data Mapper | The code which transforms between the object schema and the database | Mapper classes | Generated functions in Prisma Client | @map attributes in the Prisma schema |
+| Database schema | The structure of data in the database, e.g., tables and columns | SQL written by hand or with a programmatic API | SQL generated by Prisma Migrate | Prisma schema |
+
+Prisma aligns with the Data Mapper pattern with the following added benefits:
+
+- Reducing the boilerplate of defining classes and mapping logic by generating a Prisma Client based on the Prisma schema.
+- Eliminating the synchronization challenges between application objects and the database schema.
+- Database migrations are a first-class citizen as they're derived from the Prisma schema.
+
+Now that we've talked about the concepts behind Prisma's approach to Data Mapper, we can go through how the Prisma schema works in practice.
+
+### Prisma schema
+
+At the heart of Prisma's implementation of the Data Mapper pattern is the _Prisma schema_ – a single source of truth for the following responsibilities:
+
+- Configuring how Prisma connects to your database.
+- Generating Prisma Client – the type-safe ORM for use in your application code.
+- Creating and evolving the database schema with Prisma Migrate.
+- Defining the mapping between application objects and database columns.
+
+Models in Prisma mean something slightly different to Active Record ORMs. With Prisma, models are defined in the Prisma schema as abstract entities which describe tables, relations, and the mappings between columns to properties in Prisma Client.
+
+As an example, here's a Prisma schema for a blog:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String? @map("post_content")
+ published Boolean @default(false)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+```
+
+Here's a break down of the example above:
+
+- The `datasource` block defines the connection to the database.
+- The `generator` block tells Prisma to generate Prisma Client for TypeScript and Node.js.
+- The `Post` and `User` models map to database tables.
+- The two models have a _1-n_ relation where each `User` can have many related `Post`s.
+- Each field in the models has a type, e.g. the `id` has the type `Int`.
+- Fields may contain field attributes to define:
+ - Primary keys with the `@id` attribute.
+ - Unique keys with the `@unique` attribute.
+ - Default values with the `@default` attribute.
+ - Mapping between table columns and Prisma Client fields with the `@map` attribute, e.g., the `content` field (which will be accessible in Prisma Client) maps to the `post_content` database column.
+
+The `User` / `Post` relation can be visualized with the following diagram:
+
+
+
+At a Prisma level, the `User` / `Post` relation is made up of:
+
+- The scalar `authorId` field, which is referenced by the `@relation` attribute. This field exists in the database table – it is the foreign key that connects Post and User.
+- The two relation fields: `author` and `posts` **do not exist** in the database table. Relation fields define connections between models at the Prisma level and exist only in the Prisma schema and generated Prisma Client, where they are used to access the relations.
+
+The declarative nature of Prisma schema is concise and allows defining the database schema and corresponding representation in Prisma Client.
+
+In the next section, you will learn about Prisma's supported workflows.
+
+### Prisma workflow
+
+The workflow with Prisma is slightly different to traditional ORMs. You can use Prisma when building new applications from scratch or adopt it incrementally:
+
+- _New application_ (greenfield): Projects that have no database schema yet can use Prisma Migrate to create the database schema.
+- _Existing application_ (brownfield): Projects that already have a database schema can be [introspected](/orm/prisma-schema/introspection) by Prisma to generate the Prisma schema and Prisma Client. This use-case works with any existing migration tool and is useful for incremental adoption. It's possible to switch to Prisma Migrate as the migration tool. However, this is optional.
+
+With both workflows, the Prisma schema is the main configuration file.
+
+#### Workflow for incremental adoption in projects with an existing database
+
+Brownfield projects typically already have some database abstraction and schema. Prisma can integrate with such projects by introspecting the existing database to obtain a Prisma schema that reflects the existing database schema and to generate Prisma Client. This workflow is compatible with any migration tool and ORM which you may already be using. If you prefer to incrementally evaluate and adopt, this approach can be used as part of a [parallel adoption strategy](https://en.wikipedia.org/wiki/Parallel_adoption).
+
+A non-exhaustive list of setups compatible with this workflow:
+
+- Projects using plain SQL files with `CREATE TABLE` and `ALTER TABLE` to create and alter the database schema.
+- Projects using a third party migration library like [db-migrate](https://github.com/db-migrate/node-db-migrate) or [Umzug](https://github.com/sequelize/umzug).
+- Projects already using an ORM. In this case, database access through the ORM remains unchanged while the generated Prisma Client can be incrementally adopted.
+
+In practice, these are the steps necessary to introspect an existing DB and generate Prisma Client:
+
+1. Create a `schema.prisma` defining the `datasource` (in this case, your existing DB) and `generator`:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://janedoe:janedoe@localhost:5432/hello-prisma"
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+```
+
+2. Run `prisma db pull` to populate the Prisma schema with models derived from your database schema.
+3. (Optional) Customize [field and model mappings](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections) between Prisma Client and the database.
+4. Run `prisma generate`.
+
+Prisma will generate Prisma Client inside the `node_modules` folder, from which it can be imported in your application. For more extensive usage documentation, see the [Prisma Client API](/orm/prisma-client) docs.
+
+To summarize, Prisma Client can be integrated into projects with an existing database and tooling as part of a parallel adoption strategy. New projects will use a different workflow detailed next.
+
+#### Workflow for new projects
+
+Prisma is different from ORMs in terms of the workflows it supports. A closer look at the steps necessary to create and change a new database schema is useful for understanding Prisma Migrate.
+
+Prisma Migrate is a CLI for declarative data modeling & migrations. Unlike most migration tools that come as part of an ORM, you only need to describe the current schema, instead of the operations to move from one state to another. Prisma Migrate infers the operations, generates the SQL and carries out the migration for you.
+
+This example demonstrates using Prisma in a new project with a new database schema similar to the blog example above:
+
+1. Create the Prisma schema:
+
+```prisma
+// schema.prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://janedoe:janedoe@localhost:5432/hello-prisma"
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String? @map("post_content")
+ published Boolean @default(false)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+```
+
+2. Run `prisma migrate` to generate the SQL for the migration, apply it to the database, and generate Prisma Client.
+
+For any further changes to the database schema:
+
+1. Apply changes to the Prisma schema, e.g., add a `registrationDate` field to the `User` model
+1. Run `prisma migrate` again.
+
+The last step demonstrates how declarative migrations work by adding a field to the Prisma schema and using Prisma Migrate to transform the database schema to the desired state. After the migration is run, Prisma Client is automatically regenerated so that it reflects the updated schema.
+
+If you don't want to use Prisma Migrate but still want to use the type-safe generated Prisma Client in a new project, see the next section.
+
+##### Alternative for new projects without Prisma Migrate
+
+It is possible to use Prisma Client in a new project with a third-party migration tool instead of Prisma Migrate. For example, a new project could choose to use the Node.js migration framework [db-migrate](https://github.com/db-migrate/node-db-migrate) to create the database schema and migrations and Prisma Client for querying. In essence, this is covered by the [workflow for existing databases](#workflow-for-incremental-adoption-in-projects-with-an-existing-database).
+
+## Accessing data with Prisma Client
+
+So far, the article covered the concepts behind Prisma, its implementation of the Data Mapper pattern, and the workflows it supports. In this last section, you will see how to access data in your application using Prisma Client.
+
+Accessing the database with Prisma Client happens through the query methods it exposes. All queries return plain old JavaScript objects. Given the blog schema from above, fetching a user looks as follows:
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+const user = await prisma.user.findUnique({
+ where: {
+ email: 'alice@prisma.io',
+ },
+})
+```
+
+In this query, the `findUnique` method is used to fetch a single row from the `User` table. By default, Prisma will return all the scalar fields in the `User` table.
+
+> **Note:** The example uses TypeScript to make full use of the type safety features offered by Prisma Client. However, Prisma also works with [JavaScript in Node.js](https://dev.to/prisma/productive-development-with-prisma-s-zero-cost-type-safety-4od2).
+
+Prisma Client maps queries and results to [structural types](https://en.wikipedia.org/wiki/Structural_type_system) by generating code from the Prisma schema. This means that `user` has an associated type in the generated Prisma Client:
+
+```
+export type User = {
+ id: number
+ email: string
+ name: string | null
+}
+```
+
+This ensures that accessing a non-existent field will raise a type error. More broadly, it means that the result's type for every query is known ahead of running the query, which helps catch errors. For example, the following code snippet will raise a type error:
+
+```ts
+console.log(user.lastName) // Property 'lastName' does not exist on type 'User'.
+```
+
+### Fetching relations
+
+Fetch relations with Prisma Client is done with the `include` option. For example, to fetch a user and their posts would be done as follows:
+
+```ts
+const user = await prisma.user.findUnique({
+ where: {
+ email: 'alice@prisma.io',
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+With this query, `user`'s type will also include `Post`s which can be accessed with the `posts` array field:
+
+```ts
+console.log(user.posts[0].title)
+```
+
+The example only scratches the surface of Prisma Client's API for [CRUD operations](/orm/prisma-client/queries/crud) which you can learn more about in the docs. The main idea is that all queries and results are backed by types and you have full control over how relations are fetched.
+
+## Conclusion
+
+In summary, Prisma is a new kind of Data Mapper ORM that differs from traditional ORMs and doesn't suffer from the problems commonly associated with them.
+
+Unlike traditional ORMs, with Prisma, you define the Prisma schema – a declarative single source of truth for the database schema and application models. All queries in Prisma Client return plain JavaScript objects which makes the process of interacting with the database a lot more natural as well as more predictable.
+
+Prisma supports two main workflows for starting new projects and adopting in an existing project. For both workflows, the Prisma schema is the main configuration file.
+
+Like all abstractions, both Prisma and other ORMs hide away some of the underlying details of the database with different assumptions.
+
+These differences and your use case all affect the workflow and cost of adoption. Hopefully understanding how they differ can help you make an informed decision.
diff --git a/docs/200-orm/050-overview/300-prisma-in-your-stack/index.mdx b/docs/200-orm/050-overview/300-prisma-in-your-stack/index.mdx
new file mode 100644
index 0000000000..3ba9ab5661
--- /dev/null
+++ b/docs/200-orm/050-overview/300-prisma-in-your-stack/index.mdx
@@ -0,0 +1,16 @@
+---
+title: 'Prisma in your stack'
+metaTitle: 'How Prisma fits into your stack'
+metaDescription: 'How Prisma fits into your stack'
+toc: false
+---
+
+
+
+Prisma is an ORM that provides a fully type-safe API and simplified database access. You can use Prisma tools to build a GraphQL or REST API, or as part of a fullstack application - the extent to which you incorporate Prisma is up to you.
+
+
+
+## In this section
+
+
diff --git a/docs/200-orm/050-overview/500-databases/200-database-drivers.mdx b/docs/200-orm/050-overview/500-databases/200-database-drivers.mdx
new file mode 100644
index 0000000000..d9297fb4cc
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/200-database-drivers.mdx
@@ -0,0 +1,132 @@
+---
+title: 'Database drivers'
+metaTitle: 'Database drivers'
+metaDescription: 'Learn how Prisma connects to your database using the built-in drivers and how you can use Prisma along with other JavaScript database drivers using driver adapters (Preview)'
+tocDepth: 4
+---
+
+## Default built-in drivers
+
+One of Prisma Client's components is the [Query Engine](/orm/more/under-the-hood/engines) . The Query Engine is responsible for transforming Prisma Client queries to SQL statements. The Query Engine connects to your database using the included drivers that don't require additional setup. The built-in drivers use TCP connections to connect to the database.
+
+
+
+## Driver adapters
+
+Prisma Client can connect and run queries against your database using JavaScript database drivers using **driver adapters**. Adapters act as _translators_ between Prisma Client and the JavaScript database driver.
+
+Prisma will use the Query Engine to transform the Prisma Client query to SQL and run the generated SQL queries via the JavaScript database driver.
+
+
+
+There are 2 different types of driver adapters:
+
+- [Database driver adapters](#database-driver-adapters)
+- [Serverless driver adapters](#serverless-driver-adapters)
+
+### Database driver adapters
+
+You can connect to your database using a Node.js-based driver from Prisma Client using a database driver adapter. Prisma maintains the following database driver adapters:
+
+- [PostgreSQL](/orm/overview/databases/postgresql#using-the-node-postgres-driver)
+- [Turso](/orm/overview/databases/turso#how-to-connect-and-query-a-turso-database)
+
+### Serverless driver adapters
+
+Database providers, such as Neon and PlanetScale, allow you to connect to your database using other protocols besides TCP, such as HTTP and WebSockets. These database drivers are optimized for connecting to your database in serverless and edge environments.
+
+Prisma maintains the following serverless driver adapters:
+
+- [Neon](/orm/overview/databases/neon#how-to-use-neons-serverless-driver-with-prisma-preview)
+- [PlanetScale](/orm/overview/databases/planetscale#how-to-use-the-planetscale-serverless-driver-with-prisma-preview)
+
+## Community maintained database driver adapters
+
+You can also build your own driver adapter for the database you're using. The following is a list of community maintained driver adapters:
+
+- [TiDB](https://github.com/tidbcloud/prisma-adapter)
+
+### How to use driver adapters
+
+To use this feature:
+
+1. Update the `previewFeatures` block in your schema to include the the `driverAdapters` Preview feature:
+
+ ```prisma
+ generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["driverAdapters"]
+ }
+ ```
+
+2. Generate Prisma Client:
+
+ ```sh
+ npx prisma generate
+ ```
+
+3. Refer to the following pages to learn more how to use the specific driver adapters with the specific database providers:
+
+ - [Neon](/orm/overview/databases/neon#how-to-use-neons-serverless-driver-with-prisma-preview)
+ - [PlanetScale](/orm/overview/databases/planetscale#how-to-use-the-planetscale-serverless-driver-with-prisma-preview)
+ - [Turso](/orm/overview/databases/turso#how-to-connect-and-query-a-turso-database)
+
+### Driver adapters and custom output paths
+
+Since Prisma 5.9.0, when using the driver adapters Preview feature along with a [custom output path for Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path), you cannot reference Prisma Client using a relative path.
+
+Let's assume you had `output` in your Prisma schema set to `../src/generated/client`:
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+ output = "../src/generated/client"
+}
+```
+
+What you should **not** do is reference that path relatively:
+
+```ts no-copy
+// what not to do!
+import { PrismaClient } from './src/generated/client'
+
+const client = new PrismaClient()
+```
+
+Instead, you will need to use a linked dependency.
+
+
+
+
+
+```terminal
+npm add db@./src/generated/client
+```
+
+
+
+
+
+```terminal
+pnpm add db@link:./src/generated/client
+```
+
+
+
+
+
+```terminal
+yarn add db@link:./src/generated/client
+```
+
+
+
+
+
+Now you should be able to reference your generated client using `db`!
+
+```ts
+import { PrismaClient } from 'db'
+
+const client = new PrismaClient()
+```
diff --git a/docs/200-orm/050-overview/500-databases/300-postgresql.mdx b/docs/200-orm/050-overview/500-databases/300-postgresql.mdx
new file mode 100644
index 0000000000..a1a48a64cd
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/300-postgresql.mdx
@@ -0,0 +1,302 @@
+---
+title: 'PostgreSQL'
+metaTitle: 'PostgreSQL database connector'
+metaDescription: 'This page explains how Prisma can connect to a PostgreSQL database using the PostgreSQL database connector.'
+tocDepth: 3
+---
+
+
+
+The PostgreSQL data source connector connects Prisma to a [PostgreSQL](https://www.postgresql.org/) database server.
+
+By default, the PostgreSQL connector contains a database driver responsible for connecting to your database. You can use a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) (Preview) to connect to your database using a JavaScript database driver from Prisma Client.
+
+
+
+## Example
+
+To connect to a PostgreSQL database server, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema file](/orm/prisma-schema):
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+```
+
+The fields passed to the `datasource` block are:
+
+- `provider`: Specifies the `postgresql` data source connector.
+- `url`: Specifies the [connection URL](#connection-url) for the PostgreSQL database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL.
+
+## Using the `node-postgres` driver
+
+As of [`v5.4.0`](https://github.com/prisma/prisma/releases/tag/5.4.0), you can use Prisma ORM with database drivers from the JavaScript ecosystem (instead of using Prisma ORM's built-in drivers). You can do this by using a [driver adapter](/orm/overview/databases/database-drivers).
+
+For PostgreSQL, [`node-postgres`](https://node-postgres.com) (`pg`) is one of the most popular drivers in the JavaScript ecosystem. It can be used with any PostgreSQL database that's accessed via TCP.
+
+This section explains how you can use it with Prisma ORM and the `@prisma/adapter-pg` driver adapter.
+
+### 1. Enable the `driverAdapters` Preview feature flag
+
+Since driver adapters are currently in [Preview](/orm/more/releases#preview), you need to enable its feature flag on the `datasource` block in your Prisma schema:
+
+```prisma
+// schema.prisma
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["driverAdapters"]
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+```
+
+Once you have added the feature flag to your schema, re-generate Prisma Client:
+
+```terminal copy
+npx prisma generate
+```
+
+### 2. Install the dependencies
+
+Next, install the `pg` package and Prisma ORM's driver adapter:
+
+```terminal copy
+npm install pg
+npm install @prisma/adapter-pg
+```
+
+### 3. Instantiate Prisma Client using the driver adapter
+
+Finally, when you instantiate Prisma Client, you need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor:
+
+```ts copy
+import { Pool } from 'pg'
+import { PrismaPg } from '@prisma/adapter-pg'
+import { PrismaClient } from '@prisma/client'
+
+const connectionString = `${process.env.DATABASE_URL}`
+
+const pool = new Pool({ connectionString })
+const adapter = new PrismaPg(pool)
+const prisma = new PrismaClient({ adapter })
+```
+
+Notice that this code requires the `DATABASE_URL` environment variable to be set to your PostgreSQL connection string. You can learn more about the connection string below.
+
+## Connection details
+
+### Connection URL
+
+Prisma is based on the [official PostgreSQL format](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING) for connection URLs, but does not support all arguments and includes additional arguments such as `schema`. Here's an overview of the components needed for a PostgreSQL connection URL:
+
+
+
+#### Base URL and path
+
+Here is an example of the structure of the _base URL_ and the _path_ using placeholder values in uppercase letters:
+
+```
+postgresql://USER:PASSWORD@HOST:PORT/DATABASE
+```
+
+The following components make up the _base URL_ of your database, they are always required:
+
+| Name | Placeholder | Description |
+| :------- | :---------- | :-------------------------------------------------------------------------------------------------------------- |
+| Host | `HOST` | IP address/domain of your database server, e.g. `localhost` |
+| Port | `PORT` | Port on which your database server is running, e.g. `5432` |
+| User | `USER` | Name of your database user, e.g. `janedoe` |
+| Password | `PASSWORD` | Password for your database user |
+| Database | `DATABASE` | Name of the [database](https://www.postgresql.org/docs/12/manage-ag-overview.html) you want to use, e.g. `mydb` |
+
+
+
+You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters).
+
+
+
+#### Arguments
+
+A connection URL can also take arguments. Here is the same example from above with placeholder values in uppercase letters for three _arguments_:
+
+```
+postgresql://USER:PASSWORD@HOST:PORT/DATABASE?KEY1=VALUE&KEY2=VALUE&KEY3=VALUE
+```
+
+The following arguments can be used:
+
+| Argument name | Required | Default | Description |
+| :--------------------- | :------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `schema` | **Yes** | `public` | Name of the [schema](https://www.postgresql.org/docs/12/ddl-schemas.html) you want to use, e.g. `myschema` |
+| `connection_limit` | No | `num_cpus * 2 + 1` | Maximum size of the [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) |
+| `connect_timeout` | No | `5` | Maximum number of seconds to wait for a new connection to be opened, `0` means no timeout |
+| `pool_timeout` | No | `10` | Maximum number of seconds to wait for a new connection from the pool, `0` means no timeout |
+| `sslmode` | No | `prefer` | Configures whether to use TLS. Possible values: `prefer`, `disable`, `require` |
+| `sslcert` | No | | Path of the server certificate. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections) |
+| `sslidentity` | No | | Path to the PKCS12 certificate |
+| `sslpassword` | No | | Password that was used to secure the PKCS12 file |
+| `sslaccept` | No | `accept_invalid_certs` | Configures whether to check for missing values in the certificate. Possible values: `accept_invalid_certs`, `strict` |
+| `host` | No | | Points to a directory that contains a socket to be used for the connection |
+| `socket_timeout` | No | | Maximum number of seconds to wait until a single query terminates |
+| `pgbouncer` | No | `false` | Configure the Engine to [enable PgBouncer compatibility mode](/orm/prisma-client/setup-and-configuration/databases-connections/pgbouncer) |
+| `statement_cache_size` | No | `500` | Since 2.1.0: Specifies the number of [prepared statements](#prepared-statement-caching) cached per connection |
+| `application_name` | No | | Since 3.3.0: Specifies a value for the application_name configuration parameter |
+| `channel_binding` | No | `prefer` | Since 4.8.0: Specifies a value for the channel_binding configuration parameter |
+| `options` | No | | Since 3.8.0: Specifies command line options to send to the server at connection start |
+
+As an example, if you want to connect to a schema called `myschema`, set the connection pool size to `5` and configure a timeout for queries of `3` seconds. You can use the following arguments:
+
+```
+postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=myschema&connection_limit=5&socket_timeout=3
+```
+
+### Configuring an SSL connection
+
+You can add various parameters to the connection URL if your database server uses SSL. Here's an overview of the possible parameters:
+
+- `sslmode=(disable|prefer|require)`:
+ - `prefer` (default): Prefer TLS if possible, accept plain text connections.
+ - `disable`: Do not use TLS.
+ - `require`: Require TLS or fail if not possible.
+- `sslcert=`: Path to the server certificate. This is the root certificate used by the database server to sign the client certificate. You need to provide this if the certificate doesn't exist in the trusted certificate store of your system. For Google Cloud this likely is `server-ca.pem`. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections)
+- `sslidentity=`: Path to the PKCS12 certificate database created from client cert and key. This is the SSL identity file in PKCS12 format which you will generate using the client key and client certificate. It combines these two files in a single file and secures them via a password (see next parameter). You can create this file using your client key and client certificate by using the following command (using `openssl`):
+ ```
+ openssl pkcs12 -export -out client-identity.p12 -inkey client-key.pem -in client-cert.pem
+ ```
+- `sslpassword=`: Password that was used to secure the PKCS12 file. The `openssl` command listed in the previous step will ask for a password while creating the PKCS12 file, you will need to provide that same exact password here.
+- `sslaccept=(strict|accept_invalid_certs)`:
+ - `strict`: Any missing value in the certificate will lead to an error. For Google Cloud, especially if the database doesn't have a domain name, the certificate might miss the domain/IP address, causing an error when connecting.
+ - `accept_invalid_certs` (default): Bypass this check. Be aware of the security consequences of this setting.
+
+Your database connection URL will look similar to this:
+
+```
+postgresql://USER:PASSWORD@HOST:PORT/DATABASE?sslidentity=client-identity.p12&sslpassword=mypassword&sslcert=rootca.cert
+```
+
+### Connecting via sockets
+
+To connect to your PostgreSQL database via sockets, you must add a `host` field as a _query parameter_ to the connection URL (instead of setting it as the `host` part of the URI).
+The value of this parameter then must point to the directory that contains the socket, e.g.: `postgresql://USER:PASSWORD@localhost/database?host=/var/run/postgresql/`
+
+Note that `localhost` is required, the value itself is ignored and can be anything.
+
+> **Note**: You can find additional context in this [GitHub issue](https://github.com/prisma/prisma-client-js/issues/437#issuecomment-592436707).
+
+## Type mapping between PostgreSQL and Prisma schema
+
+These two tables show the type mapping between PostgreSQL and Prisma schema. First [how Prisma scalar types are translated into PostgreSQL database column types](#mapping-between-prisma-scalar-types-and-postgresql-database-column-types), and then [how PostgreSQL database column types relate to Prisma scalar and native types](#mapping-between-postgresql-database-column-types-to-prisma-scalar-and-native-types).
+
+> Alternatively, see [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma type.
+
+### Mapping between Prisma scalar types and PostgreSQL database column types
+
+The PostgreSQL connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma [data model](/orm/prisma-schema/data-model/models) as follows to database column types:
+
+| Prisma | PostgreSQL |
+| ---------- | ------------------ |
+| `String` | `text` |
+| `Boolean` | `boolean` |
+| `Int` | `integer` |
+| `BigInt` | `bigint` |
+| `Float` | `double precision` |
+| `Decimal` | `decimal(65,30)` |
+| `DateTime` | `timestamp(3)` |
+| `Json` | `jsonb` |
+| `Bytes` | `bytea` |
+
+### Mapping between PostgreSQL database column types to Prisma scalar and native types
+
+- When [introspecting](/orm/prisma-schema/introspection) a PostgreSQL database, the database types are mapped to Prisma types according to the following table.
+- When [creating a migration](/orm/prisma-migrate) or [prototyping your schema](/orm/prisma-migrate/workflows/prototyping-your-schema) the table is also used - in the other direction.
+
+| PostgreSQL (Type \| Aliases) | Supported | Prisma | Native database type attribute | Notes |
+| ------------------------------------------- | :-------: | ------------- | :--------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `bigint` \| `int8` | ✔️ | `BigInt` | `@db.BigInt`\* | \*Default mapping for `BigInt` - no type attribute added to schema. |
+| `boolean` \| `bool` | ✔️ | `Bool` | `@db.Boolean`\* | \*Default mapping for `Bool` - no type attribute added to schema. |
+| `timestamp with time zone` \| `timestamptz` | ✔️ | `DateTime` | `@db.Timestamptz(x)` |
+| `time without time zone` \| `time` | ✔️ | `DateTime` | `@db.Time(x)` |
+| `time with time zone` \| `timetz` | ✔️ | `DateTime` | `@db.Timetz(x)` |
+| `numeric(p,s)` \| `decimal(p,s)` | ✔️ | `Decimal` | `@db.Decimal(x, y)` |
+| `real` \| `float`, `float4` | ✔️ | `Float` | `@db.Real` |
+| `double precision` \| `float8` | ✔️ | `Float` | `@db.DoublePrecision`\* | \*Default mapping for `Float` - no type attribute added to schema. |
+| `smallint` \| `int2` | ✔️ | `Int` | `@db.SmallInt` | |
+| `integer` \| `int`, `int4` | ✔️ | `Int` | `@db.Int`\* | \*Default mapping for `Int` - no type attribute added to schema. |
+| `smallserial` \| `serial2` | ✔️ | `Int` | `@db.SmallInt @default(autoincrement())` |
+| `serial` \| `serial4` | ✔️ | `Int` | `@db.Int @default(autoincrement())` |
+| `bigserial` \| `serial8` | ✔️ | `Int` | `@db.BigInt @default(autoincrement()` |
+| `character(n)` \| `char(n)` | ✔️ | `String` | `@db.Char(x)` |
+| `character varying(n)` \| `varchar(n)` | ✔️ | `String` | `@db.VarChar(x)` |
+| `money` | ✔️ | `Decimal` | `@db.Money` |
+| `text` | ✔️ | `String` | `@db.Text`\* | \*Default mapping for `String` - no type attribute added to schema. |
+| `timestamp` | ✔️ | `DateTime` | `@db.TimeStamp`\* | \*Default mapping for `DateTime` - no type attribute added to schema. |
+| `date` | ✔️ | `DateTime` | `@db.Date` |
+| `enum` | ✔️ | `Enum` | N/A |
+| `inet` | ✔️ | `String` | `@db.Inet` |
+| `bit(n)` | ✔️ | `String` | `@Bit(x)` |
+| `bit varying(n)` | ✔️ | `String` | `@VarBit` |
+| `oid` | ✔️ | `Int` | `@db.Oid` |
+| `uuid` | ✔️ | `String` | `@db.Uuid` |
+| `json` | ✔️ | `Json` | `@db.Json` |
+| `jsonb` | ✔️ | `Json` | `@db.JsonB`\* | \*Default mapping for `Json` - no type attribute added to schema. |
+| `bytea` | ✔️ | `Bytes` | `@db.ByteA`\* | \*Default mapping for `Bytes` - no type attribute added to schema. |
+| `xml` | ✔️ | `String` | `@db.Xml` |
+| Array types | ✔️ | `[]` |
+| `citext` | ✔️\* | `String` | `@db.Citext` | \* Only available if [Citext extension is enabled](/orm/prisma-schema/data-model/unsupported-database-features#enable-postgresql-extensions-for-native-database-functions). |
+| `interval` | Not yet | `Unsupported` | | |
+| `cidr` | Not yet | `Unsupported` | | |
+| `macaddr` | Not yet | `Unsupported` | | |
+| `tsvector` | Not yet | `Unsupported` | | |
+| `tsquery` | Not yet | `Unsupported` | | |
+| `int4range` | Not yet | `Unsupported` | | |
+| `int8range` | Not yet | `Unsupported` | | |
+| `numrange` | Not yet | `Unsupported` | | |
+| `tsrange` | Not yet | `Unsupported` | | |
+| `tstzrange` | Not yet | `Unsupported` | | |
+| `daterange` | Not yet | `Unsupported` | | |
+| `point` | Not yet | `Unsupported` | | |
+| `line` | Not yet | `Unsupported` | | |
+| `lseg` | Not yet | `Unsupported` | | |
+| `box` | Not yet | `Unsupported` | | |
+| `path` | Not yet | `Unsupported` | | |
+| `polygon` | Not yet | `Unsupported` | | |
+| `circle` | Not yet | `Unsupported` | | |
+| Composite types | Not yet | n/a | | |
+| Domain types | Not yet | n/a | | |
+
+[Introspection](/orm/prisma-schema/introspection) adds native database types that are **not yet supported** as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) fields:
+
+```prisma file=schema.prisma
+model Device {
+ id Int @id @default(autoincrement())
+ name String
+ data Unsupported("circle")
+}
+```
+
+## Prepared statement caching
+
+A [prepared statement](https://www.postgresql.org/docs/current/sql-prepare.html) is a feature that can be used to optimize performance. A prepared statement is parsed, compiled, and optimized only once and then can be executed directly multiple times without the overhead of parsing the query again.
+
+By caching prepared statements, Prisma Client's [query engine](/orm/more/under-the-hood/engines) does not repeatedly compile the same query which reduces database CPU usage and query latency.
+
+For example, here is the generated SQL for two different queries made by Prisma Client:
+
+```sql
+SELECT * FROM user WHERE name = "John";
+SELECT * FROM user WHERE name = "Brenda";
+```
+
+The two queries after parameterization will be the same, and the second query can skip the preparing step, saving database CPU and one extra roundtrip to the database. Query after parameterization:
+
+```sql
+SELECT * FROM user WHERE name = $1
+```
+
+Every database connection maintained by Prisma has a separate cache for storing prepared statements. The size of this cache can be tweaked with the `statement_cache_size` parameter in the connection string. By default, Prisma Client caches 500 statements per connection.
+
+Due to the nature of pgBouncer, if the `pgbouncer` parameter is set to `true`, the prepared statement cache is automatically disabled for that connection.
diff --git a/docs/200-orm/050-overview/500-databases/400-mysql.mdx b/docs/200-orm/050-overview/500-databases/400-mysql.mdx
new file mode 100644
index 0000000000..cabbaee1e0
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/400-mysql.mdx
@@ -0,0 +1,206 @@
+---
+title: 'MySQL'
+metaTitle: 'MySQL database connector'
+metaDescription: 'This page explains how Prisma can connect to a MySQL database using the MySQL database connector.'
+tocDepth: 3
+---
+
+
+
+The MySQL data source connector connects Prisma to a [MySQL](https://www.mysql.com/) database server.
+
+By default, the MySQL connector contains a database driver responsible for connecting to your database. You can use a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) (Preview) to connect to your database using a JavaScript database driver from Prisma Client.
+
+
+
+## Example
+
+To connect to a MySQL database server, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema file](/orm/prisma-schema):
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "mysql"
+ url = env("DATABASE_URL")
+}
+```
+
+The fields passed to the `datasource` block are:
+
+- `provider`: Specifies the `mysql` data source connector.
+- `url`: Specifies the [connection URL](#connection-url) for the MySQL database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL.
+
+## Connection details
+
+### Connection URL
+
+Here's an overview of the components needed for a MySQL connection URL:
+
+
+
+#### Base URL and path
+
+Here is an example of the structure of the _base URL_ and the _path_ using placeholder values in uppercase letters:
+
+```
+mysql://USER:PASSWORD@HOST:PORT/DATABASE
+```
+
+The following components make up the _base URL_ of your database, they are always required:
+
+| Name | Placeholder | Description |
+| :------- | :---------- | :------------------------------------------------------------------------------------------------------------------ |
+| Host | `HOST` | IP address/domain of your database server, e.g. `localhost` |
+| Port | `PORT` | Port on which your database server is running, e.g. `5432` |
+| User | `USER` | Name of your database user, e.g. `janedoe` |
+| Password | `PASSWORD` | Password for your database user |
+| Database | `DATABASE` | Name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) you want to use, e.g. `mydb` |
+
+
+
+You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters).
+
+
+
+#### Arguments
+
+A connection URL can also take arguments. Here is the same example from above with placeholder values in uppercase letters for three _arguments_:
+
+```
+mysql://USER:PASSWORD@HOST:PORT/DATABASE?KEY1=VALUE&KEY2=VALUE&KEY3=VALUE
+```
+
+The following arguments can be used:
+
+| Argument name | Required | Default | Description |
+| :----------------- | :------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `connection_limit` | No | `num_cpus * 2 + 1` | Maximum size of the [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) |
+| `connect_timeout` | No | `5` | Maximum number of seconds to wait for a new connection to be opened, `0` means no timeout |
+| `pool_timeout` | No | `10` | Maximum number of seconds to wait for a new connection from the pool, `0` means no timeout |
+| `sslcert` | No | | Path to the server certificate. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections) |
+| `sslidentity` | No | | Path to the PKCS12 certificate |
+| `sslpassword` | No | | Password that was used to secure the PKCS12 file |
+| `sslaccept` | No | `accept_invalid_certs` | Configures whether to check for missing values in the certificate. Possible values: `accept_invalid_certs`, `strict` |
+| `socket` | No | | Points to a directory that contains a socket to be used for the connection |
+| `socket_timeout` | No | | Number of seconds to wait until a single query terminates |
+
+As an example, if you want to set the connection pool size to `5` and configure a timeout for queries of `3` seconds, you can use the following arguments:
+
+```
+mysql://USER:PASSWORD@HOST:PORT/DATABASE?connection_limit=5&socket_timeout=3
+```
+
+### Configuring an SSL connection
+
+You can add various parameters to the connection URL if your database server uses SSL. Here's an overview of the possible parameters:
+
+- `sslcert=`: Path to the server certificate. This is the root certificate used by the database server to sign the client certificate. You need to provide this if the certificate doesn't exist in the trusted certificate store of your system. For Google Cloud this likely is `server-ca.pem`. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections)
+
+- `sslidentity=`: Path to the PKCS12 certificate database created from client cert and key. This is the SSL identity file in PKCS12 format which you will generate using the client key and client certificate. It combines these two files in a single file and secures them via a password (see next parameter). You can create this file using your client key and client certificate by using the following command (using `openssl`):
+ ```
+ openssl pkcs12 -export -out client-identity.p12 -inkey client-key.pem -in client-cert.pem
+ ```
+- `sslpassword=`: Password that was used to secure the PKCS12 file. The `openssl` command listed in the previous step will ask for a password while creating the PKCS12 file, you will need to provide that same exact password here.
+- `sslaccept=(strict|accept_invalid_certs)`:
+ - `strict`: Any missing value in the certificate will lead to an error. For Google Cloud, especially if the database doesn't have a domain name, the certificate might miss the domain/IP address, causing an error when connecting.
+ - `accept_invalid_certs` (default): Bypass this check. Be aware of the security consequences of this setting.
+
+Your database connection URL will look similar to this:
+
+```
+mysql://USER:PASSWORD@HOST:PORT/DATABASE?sslidentity=client-identity.p12&sslpassword=mypassword&sslcert=rootca.cert
+```
+
+### Connecting via sockets
+
+To connect to your MySQL database via sockets, you must add a `socket` field as a _query parameter_ to the connection URL (instead of setting it as the `host` part of the URI).
+The value of this parameter then must point to the directory that contains the socket, e.g.: `mysql://USER:POST@localhost/database?socket=/var/run/mysql/`
+
+Note that `localhost` is required, the value itself is ignored and can be anything.
+
+> **Note**: You can find additional context in this [GitHub issue](https://github.com/prisma/prisma-client-js/issues/437#issuecomment-592436707).
+
+## Type mapping between MySQL to Prisma schema
+
+The MySQL connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma [data model](/orm/prisma-schema/data-model/models) as follows to native column types:
+
+> Alternatively, see [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma type.
+
+### Native type mapping from Prisma to MySQL
+
+| Prisma | MySQL | Notes |
+| ---------- | ---------------- | ------------------------------------------------ |
+| `String` | `VARCHAR(191)` | |
+| `Boolean` | `BOOLEAN` | In MySQL `BOOLEAN` is a synonym for `TINYINT(1)` |
+| `Int` | `INT` | |
+| `BigInt` | `BIGINT` |
+| `Float` | `DOUBLE` | |
+| `Decimal` | `DECIMAL(65,30)` |
+| `DateTime` | `DATETIME(3)` | |
+| `Json` | `JSON` | Supported in MySQL 5.7+ only |
+| `Bytes` | `LONGBLOB` |
+
+### Native type mappings
+
+When introspecting a MySQL database, the database types are mapped to Prisma according to the following table:
+
+| MySQL | Prisma | Supported | Native database type attribute | Notes |
+| ------------------------- | ------------- | --------- | ---------------------------------------------- | ------------------------------------------------------------------ |
+| `serial` | `BigInt` | ✔️ | `@db.UnsignedBigInt @default(autoincrement())` |
+| `bigint` | `BigInt` | ✔️ | `@db.BigInt` |
+| `bigint unsigned` | `BigInt` | ✔️ | `@db.UnsignedBigInt` |
+| `bit` | `Bytes` | ✔️ | `@db.Bit(x)` | `bit(1)` maps to `Boolean` - all other `bit(x)` map to `Bytes` |
+| `boolean` \| `tinyint(1)` | `Boolean` | ✔️ | `@db.TinyInt(1)` |
+| `varbinary` | `Bytes` | ✔️ | `@db.VarBinary` |
+| `longblob` | `Bytes` | ✔️ | `@db.LongBlob` |
+| `tinyblob` | `Bytes` | ✔️ | `@db.TinyBlob` |
+| `mediumblob` | `Bytes` | ✔️ | `@db.MediumBlob` |
+| `blob` | `Bytes` | ✔️ | `@db.Blob` |
+| `binary` | `Bytes` | ✔️ | `@db.Binary` |
+| `date` | `DateTime` | ✔️ | `@db.Date` |
+| `datetime` | `DateTime` | ✔️ | `@db.DateTime` |
+| `timestamp` | `DateTime` | ✔️ | `@db.TimeStamp` |
+| `time` | `DateTime` | ✔️ | `@db.Time` |
+| `decimal(a,b)` | `Decimal` | ✔️ | `@db.Decimal(x,y)` |
+| `numeric(a,b)` | `Decimal` | ✔️ | `@db.Decimal(x,y)` |
+| `enum` | `Enum` | ✔️ | N/A |
+| `float` | `Float` | ✔️ | `@db.Float` |
+| `double` | `Float` | ✔️ | `@db.Double` |
+| `smallint` | `Int` | ✔️ | `@db.SmallInt` |
+| `smallint unsigned` | `Int` | ✔️ | `@db.UnsignedSmallInt` |
+| `mediumint` | `Int` | ✔️ | `@db.MediumInt` |
+| `mediumint unsigned` | `Int` | ✔️ | `@db.UnsignedMediumInt` |
+| `int` | `Int` | ✔️ | `@db.Int` |
+| `int unsigned` | `Int` | ✔️ | `@db.UnsignedInt` |
+| `tinyint` | `Int` | ✔️ | `@db.TinyInt(x)` | `tinyint(1)` maps to `Boolean` all other `tinyint(x)` map to `Int` |
+| `tinyint unsigned` | `Int` | ✔️ | `@db.UnsignedTinyInt(x)` | `tinyint(1) unsigned` **does not** map to `Boolean` |
+| `year` | `Int` | ✔️ | `@db.Year` |
+| `json` | `Json` | ✔️ | `@db.Json` | Supported in MySQL 5.7+ only |
+| `char` | `String` | ✔️ | `@db.Char(x)` |
+| `varchar` | `String` | ✔️ | `@db.VarChar(x)` |
+| `tinytext` | `String` | ✔️ | `@db.TinyText` |
+| `text` | `String` | ✔️ | `@db.Text` |
+| `mediumtext` | `String` | ✔️ | `@db.MediumText` |
+| `longtext` | `String` | ✔️ | `@db.LongText` |
+| `set` | `Unsupported` | Not yet | |
+| `geometry` | `Unsupported` | Not yet | |
+| `point` | `Unsupported` | Not yet | |
+| `linestring` | `Unsupported` | Not yet | |
+| `polygon` | `Unsupported` | Not yet | |
+| `multipoint` | `Unsupported` | Not yet | |
+| `multilinestring` | `Unsupported` | Not yet | |
+| `multipolygon` | `Unsupported` | Not yet | |
+| `geometrycollection` | `Unsupported` | Not yet | |
+
+[Introspection](/orm/prisma-schema/introspection) adds native database types that are **not yet supported** as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) fields:
+
+```prisma file=schema.prisma
+model Device {
+ id Int @id @default(autoincrement())
+ name String
+ data Unsupported("circle")
+}
+```
+
+## Engine
+
+If you are using a version of MySQL where MyISAM is the default engine, you must specify `ENGINE = InnoDB;` when you create a table. If you introspect a database that uses a different engine, relations in the Prisma Schema are not created (or lost, if the relation already existed).
diff --git a/docs/200-orm/050-overview/500-databases/500-sqlite.mdx b/docs/200-orm/050-overview/500-databases/500-sqlite.mdx
new file mode 100644
index 0000000000..fc31ca5d47
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/500-sqlite.mdx
@@ -0,0 +1,93 @@
+---
+title: 'SQLite'
+metaTitle: 'SQLite database connector'
+metaDescription: 'This page explains how Prisma can connect to a SQLite database using the SQLite database connector.'
+tocDepth: 3
+---
+
+
+
+The SQLite data source connector connects Prisma to a [SQLite](https://www.sqlite.org/) database file. These files always have the file ending `.db` (e.g.: `dev.db`).
+
+By default, the SQLite connector contains a database driver responsible for connecting to your database. You can use a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) (Preview) to connect to your database using a JavaScript database driver from Prisma Client.
+
+
+
+## Example
+
+To connect to a SQLite database file, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [schema file](/orm/prisma-schema):
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "sqlite"
+ url = "file:./dev.db"
+}
+```
+
+The fields passed to the `datasource` block are:
+
+- `provider`: Specifies the `sqlite` data source connector.
+- `url`: Specifies the [connection URL](/orm/reference/connection-urls) for the SQLite database. The connection URL always starts with the prefix `file:` and then contains a file path pointing to the SQLite database file. In this case, the file is located in the same directory and called `dev.db`.
+
+## Type mapping between SQLite to Prisma schema
+
+The SQLite connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the [data model](/orm/prisma-schema/data-model/models) to native column types as follows:
+
+> Alternatively, see [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma type.
+
+### Native type mapping from Prisma to SQLite
+
+| Prisma | SQLite |
+| ---------- | ------------- |
+| `String` | `TEXT` |
+| `Boolean` | `BOOLEAN` |
+| `Int` | `INTEGER` |
+| `BigInt` | `INTEGER` |
+| `Float` | `REAL` |
+| `Decimal` | `DECIMAL` |
+| `DateTime` | `NUMERIC` |
+| `Json` | Not supported |
+| `Bytes` | `BLOB` |
+
+## Rounding errors on big numbers
+
+SQLite is a loosely-typed database. If your Schema has a field of type `Int`, then Prisma prevents you from inserting a value larger than an integer. However, nothing prevents the database from directly accepting a bigger number. These manually-inserted big numbers cause rounding errors when queried.
+
+To avoid this problem, Prisma 4.0.0 and later checks numbers on the way out of the database to verify that they fit within the boundaries of an integer. If a number does not fit, then Prisma throws a P2023 error, such as:
+
+```
+Inconsistent column data: Conversion failed:
+Value 9223372036854775807 does not fit in an INT column,
+try migrating the 'int' column type to BIGINT
+```
+
+## Connection details
+
+### Connection URL
+
+The connection URL of a SQLite connector points to a file on your file system. For example, the following two paths are equivalent because the `.db` is in the same directory:
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "sqlite"
+ url = "file:./dev.db"
+}
+```
+
+is the same as:
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "sqlite"
+ url = "file:dev.db"
+}
+```
+
+You can also target files from the root or any other place in your file system:
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "sqlite"
+ url = "file:/Users/janedoe/dev.db"
+}
+```
diff --git a/docs/200-orm/050-overview/500-databases/600-mongodb.mdx b/docs/200-orm/050-overview/500-databases/600-mongodb.mdx
new file mode 100644
index 0000000000..e350510857
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/600-mongodb.mdx
@@ -0,0 +1,573 @@
+---
+title: 'MongoDB'
+metaTitle: 'MongoDB database connector'
+metaDescription: 'How Prisma can connect to a MongoDB database using the MongoDB database connector.'
+hidePage: false
+tocDepth: 3
+codeStyle: false
+---
+
+
+
+This guide discusses the concepts behind using Prisma and MongoDB, explains the commonalities and differences between MongoDB and other database providers, and leads you through the process for configuring your application to integrate with MongoDB using Prisma.
+
+
+
+To connect Prisma with MongoDB, refer to our [Getting Started documentation](/getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb).
+
+
+
+
+
+## What is MongoDB?
+
+[MongoDB](https://www.mongodb.com/) is a NoSQL database that stores data in [BSON](https://bsonspec.org/) format, a JSON-like document format designed for storing data in key-value pairs. It is commonly used in JavaScript application development because the document model maps easily to objects in application code, and there is built in support for high availability and horizontal scaling.
+
+MongoDB stores data in collections that do not need a schema to be defined in advance, as you would need to do with tables in a relational database. The structure of each collection can also be changed over time. This flexibility can allow rapid iteration of your data model, but it does mean that there are a number of differences when using Prisma to work with your MongoDB database.
+
+## Commonalities with other database providers
+
+Some aspects of using Prisma with MongoDB are the same as when using Prisma with a relational database. You can still:
+
+- model your database with the [Prisma Schema Language](/orm/prisma-schema)
+- connect to your database, using the [`mongodb` database connector](/orm/overview/databases)
+- use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a MongoDB database
+- use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) to push changes in your schema to the database
+- use [Prisma Client](/orm/prisma-client) in your application to query your database in a type safe way based on your Prisma Schema
+
+## Differences to consider
+
+MongoDB's document-based structure and flexible schemas means that using Prisma with MongoDB differs from using it with a relational database in a number of ways. These are some areas where there are differences that you need to be aware of:
+
+- **Defining IDs**: MongoDB documents have an `_id` field (that often contains an [ObjectID](https://www.mongodb.com/docs/manual/reference/bson-types/#std-label-objectid)). Prisma does not support fields starting with `_`, so this needs to be mapped to a Prisma field using the `@map` attribute. For more information, see [Defining IDs in MongoDB](/orm/prisma-schema/data-model/models#defining-ids-in-mongodb).
+
+- **Migrating existing data to match your Prisma schema**: In relational databases, all your data must match your schema. If you change the type of a particular field in your schema when you migrate, all the data must also be updated to match. In contrast, MongoDB does not enforce any particular schema, so you need to take care when migrating. For more information, see [How to migrate old data to new schemas](#how-to-migrate-existing-data-to-match-your-prisma-schema).
+
+- **Introspection and Prisma relations**: When you introspect an existing MongoDB database, you will get a schema with no relations and will need to add the missing relations in manually. For more information, see [How to add in missing relations after Introspection](#how-to-add-in-missing-relations-after-introspection).
+
+- **Filtering for `null` and missing fields**: MongoDB makes a distinction between setting a field to `null` and not setting it at all, which is not present in relational databases. Prisma currently does not express this distinction, which means that you need to be careful when filtering for `null` and missing fields. For more information, see [How to filter for `null` and missing fields](#how-to-filter-for-null-and-missing-fields)
+
+- **Enabling replication**: Prisma uses [MongoDB transactions](https://www.mongodb.com/docs/manual/core/transactions/) internally to avoid partial writes on nested queries. When using transactions, MongoDB requires replication of your data set to be enabled. To do this, you will need to configure a [replica set](https://www.mongodb.com/docs/manual/replication/) — this is a group of MongoDB processes that maintain the same data set. Note that it is still possible to use a single database, by creating a replica set with only one node in it. If you use MongoDB's [Atlas](https://www.mongodb.com/atlas/database) hosting service, the replica set is configured for you, but if you are running MongoDB locally you will need to set up a replica set yourself. For more information, see MongoDB's [guide to deploying a replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/).
+
+## How to use Prisma with MongoDB
+
+This section provides instructions for how to carry out tasks that require steps specific to MongoDB.
+
+### How to migrate existing data to match your Prisma schema
+
+Migrating your database over time is an important part of the development cycle. During development, you will need to update your Prisma schema file (for example, to add new fields), then update the data in your development environment’s database, and eventually push both the updated schema and the new data to the production database.
+
+
+
+When using MongoDB, be aware that the “coupling” between your schema and the database is purposefully designed to be less rigid than with with SQL databases; MongoDB will not enforce the schema, so you have to verify data integrity.
+
+
+
+These iterative tasks of updating the schema and the database can result in inconsistencies between your schema and the actual data in the database. Let’s look at one scenario where this can happen, and then examine several strategies for you and your team to consider for handling these inconsistencies.
+
+**Scenario**: you need to include a phone number for users, as well as an email. You currently have the following `User` model in your `schema.prisma` file:
+
+```prisma file=prisma/schema.prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String
+}
+```
+
+There are a number of strategies you could use for migrating this schema:
+
+- **"On-demand" updates**: with this strategy, you and your team have agreed that updates can be made to the schema as needed. However, in order to avoid migration failures due to inconsistencies between the data and schema, there is agreement in the team that any new fields added are explicitly defined as optional.
+
+ In our scenario above, you can add an optional `phoneNumber` field to the `User` model in your Prisma schema:
+
+ ```prisma file=prisma/schema.prisma highlight=4;add
+ model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String
+ phoneNumber String?
+ }
+ ```
+
+ Then regenerate your Prisma Client using the `npx prisma generate` command. Next, update your application to reflect the new field, and redeploy your app.
+
+ As the `phoneNumber` field is optional, you can still query the old users where the phone number has not been defined. The records in the database will be updated "on demand" as the application's users begin to enter their phone number in the new field.
+
+ Another option is to add a default value on a required field, for example:
+
+ ```prisma file=prisma/schema.prisma highlight=4;add
+ model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String
+ phoneNumber String @default("000-000-0000")
+ }
+ ```
+
+ Then when you encounter a missing `phoneNumber`, the value will be coerced into `000-000-0000`.
+
+- **"No breaking changes" updates**: this strategy builds on the first one, with further consensus amongst your team that you don't rename or delete fields, only add new fields, and always define the new fields as optional. This policy can be reenforced by adding checks in the CI/CD process to verify that there are no backwards-incompatible changes to the schema.
+
+- **"All-at-once" updates**: this strategy is similar to traditional migrations in relational databases, where all data is updated to reflect the new schema. In the scenario above, you would create a script to add a value for the phone number field to all existing users in your database. You can then make the field a required field in the application because the schema and the data are consistent.
+
+### How to add in missing relations after Introspection
+
+After introspecting an existing MongoDB database, you will need to manually add in relations between models. MongoDB does not have the concept of defining relations via foreign keys, as you would in a relational database. However, if you have a collection in MongoDB with a "foreign-key-like" field that matches the ID field of another collection, Prisma will allow you to emulate relations between the collections.
+
+As an example, take a MongoDB database with two collections, `User` and `Post`. The data in these collections has the following format, with a `userId` field linking users to posts:
+
+`User` collection:
+
+- `_id` field with a type of `objectId`
+- `email` field with a type of `string`
+
+`Post` collection:
+
+- `_id` field with a type of `objectId`
+- `title` field with a type of `string`
+- `userId` with a type of `objectID`
+
+On introspection with `db pull`, this is pulled in to the Prisma schema file as follows:
+
+```prisma file=prisma/schema.prisma
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ userId String @db.ObjectId
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String
+}
+```
+
+This is missing the relation between the `User` and `Post` models. To fix this, manually add a `user` field to the `Post` model with a `@relation` attribute using `userId` as the `fields` value, linking it to the `User` model, and a `posts` field to the `User` model as the back relation:
+
+```prisma file=prisma/schema.prisma highlight=5;add|11;add
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ userId String @db.ObjectId
+ user User @relation(fields: [userId], references: [id])
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String
+ posts Post[]
+}
+```
+
+For more information on how to use relations in Prisma, see [our documentation](/orm/prisma-schema/data-model/relations).
+
+### How to filter for `null` and missing fields
+
+To understand how MongoDB distinguishes between `null` and missing fields, consider the example of a `User` model with an optional `name` field:
+
+```ts
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String
+ name String?
+}
+```
+
+First, try creating a record with the `name` field explicitly set to `null`. Prisma will return `name: null` as expected:
+
+
+
+
+
+```ts
+const createNull = await prisma.user.create({
+ data: {
+ email: 'user1@prisma.io',
+ name: null,
+ },
+})
+console.log(createNull)
+```
+
+
+
+
+
+```code no-copy
+{
+ id: '6242c4ae032bc76da250b207',
+ email: 'user1@prisma.io',
+ name: null
+}
+```
+
+
+
+
+
+If you check your MongoDB database directly, you will also see a new record with `name` set to `null`:
+
+```json
+{
+ "_id": "6242c4af032bc76da250b207",
+ "email": "user1@prisma.io",
+ "name": null
+}
+```
+
+Next, try creating a record without explicitly setting the `name` field:
+
+
+
+
+
+```ts
+const createMissing = await prisma.user.create({
+ data: {
+ email: 'user2@prisma.io',
+ },
+})
+console.log(createMissing)
+```
+
+
+
+
+
+```code no-copy
+{
+ id: '6242c4ae032bc76da250b208',
+ email: 'user2@prisma.io',
+ name: null
+}
+```
+
+
+
+
+
+Prisma still returns `name: null`, but if you look in the database directly you will see that the record has no `name` field defined at all:
+
+```json
+{
+ "_id": "6242c4af032bc76da250b208",
+ "email": "user2@prisma.io"
+}
+```
+
+Prisma returns the same result in both cases, because we currently don't have a way to specify this difference in MongoDB between fields that are `null` in the underlying database, and fields that are not defined at all — see [this Github issue](https://github.com/prisma/prisma/issues/12555) for more information.
+
+This means that you currently have to be careful when filtering for `null` and missing fields. Filtering for records with `name: null` will only return the first record, with the `name` explicitly set to `null`:
+
+
+
+
+
+```ts
+const findNulls = await prisma.user.findMany({
+ where: {
+ name: null,
+ },
+})
+console.log(findNulls)
+```
+
+
+
+
+
+```terminal no-copy
+[
+ {
+ id: '6242c4ae032bc76da250b207',
+ email: 'user1@prisma.io',
+ name: null
+ }
+]
+```
+
+
+
+
+
+This is because `name: null` is checking for equality, and a non-existing field isn't equal to `null`.
+
+To include missing fields as well, use the [`isSet` filter](/orm/reference/prisma-client-reference#isset) to explicitly search for fields which are either `null` or not set. This will return both records:
+
+
+
+
+
+```ts
+const findNullOrMissing = await prisma.user.findMany({
+ where: {
+ OR: [
+ {
+ name: null,
+ },
+ {
+ name: {
+ isSet: false,
+ },
+ },
+ ],
+ },
+})
+console.log(findNullOrMissing)
+```
+
+
+
+
+
+```terminal no-copy
+[
+ {
+ id: '6242c4ae032bc76da250b207',
+ email: 'user1@prisma.io',
+ name: null
+ },
+ {
+ id: '6242c4ae032bc76da250b208',
+ email: 'user2@prisma.io',
+ name: null
+ }
+]
+```
+
+
+
+
+
+## More on using MongoDB with Prisma
+
+The fastest way to start using MongoDB with Prisma is to refer to our Getting Started documentation:
+
+- [Start from scratch](/getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb)
+- [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb)
+
+These tutorials will take you through the process of connecting to MongoDB, pushing schema changes, and using Prisma Client.
+
+Further reference information is available in the [MongoDB connector documentation](/orm/overview/databases/mongodb).
+
+For more information on how to set up and manage a MongoDB database, see the [Prisma Data Guide](https://www.prisma.io/dataguide#mongodb).
+
+## Example
+
+To connect to a MongoDB server, configure the [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema file](/orm/prisma-schema):
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+```
+
+The fields passed to the `datasource` block are:
+
+- `provider`: Specifies the `mongodb` data source connector.
+- `url`: Specifies the [connection URL](#connection-url) for the MongoDB server. In this case, an [environment variable is used](/orm/more/development-environment/environment-variables) to provide the connection URL.
+
+
+
+The MongoDB database connector uses transactions to support nested writes. Transactions **require** a [replica set](https://docs.mongodb.com/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://docs.atlas.mongodb.com/getting-started/). It's free to get started.
+
+
+
+## Connection details
+
+### Connection URL
+
+The MongoDB connection URL can be configured in different ways depending on how you are hosting your database. The standard configuration is made up of the following components:
+
+
+
+#### Base URL and path
+
+The base URL and path sections of the connection URL are made up of your authentication credentials followed by the host (and optionally, a port number) and database.
+
+```
+mongodb://USERNAME:PASSWORD@HOST/DATABASE
+```
+
+The following components make up the _base URL_ of your database:
+
+| Name | Placeholder | Description |
+| :------- | :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| User | `USERNAME` | Name of your database user, e.g. `janedoe` |
+| Password | `PASSWORD` | Password for your database user |
+| Host | `HOST` | The host where a [`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#mongodb-binary-bin.mongod) instance is running. If you are running a sharded cluster this will a [`mongos`](https://docs.mongodb.com/manual/reference/program/mongos/#mongodb-binary-bin.mongos) instance. This can be a hostname, IP address or UNIX domain socket. |
+| Port | `PORT` | Port on which your database server is running, e.g. `1234`. If none is provided the default `27017` is used. |
+| Database | `DATABASE` | Name of the database to use. If none is specified but the `authSource` option is set then the `authSource` database name is used. If neither the database in the connection string nor the `authSource` option is specified then it defaults to `admin` |
+
+
+
+You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters).
+
+
+
+#### Arguments
+
+A connection URL can also take arguments. The following example sets three arguments:
+
+- An `ssl` connection
+- A `connectTimeoutMS`
+- And the `maxPoolSize`
+
+```
+mongodb://USERNAME:PASSWORD@HOST/DATABASE?ssl=true&connectTimeoutMS=5000&maxPoolSize=50
+```
+
+Refer to the [MongoDB connection string documentation](https://docs.mongodb.com/manual/reference/connection-string/#connection-string-options) for a complete list of connection string arguments. There are no Prisma-specific arguments.
+
+## Using `ObjectId`
+
+It is common practice for the `_id` field of a MongoDB document to contain an [ObjectId](https://docs.mongodb.com/manual/reference/bson-types/#std-label-objectid):
+
+```json
+{
+ "_id": { "$oid": "60d599cb001ef98000f2cad2" },
+ "createdAt": { "$date": { "$numberLong": "1624611275577" } },
+ "email": "ella@prisma.io",
+ "name": "Ella",
+ "role": "ADMIN"
+}
+```
+
+Any field (most commonly IDs and relation scalar fields) that maps to an `ObjectId` in the underlying database:
+
+- Must be of type `String` or `Bytes`
+- Must include the `@db.ObjectId` attribute
+- Can optionally use `@default(auto())` to auto-generate a valid `ObjectId` on document creation
+
+Here is an example that uses `String`:
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ // Other fields
+}
+```
+
+And here is another example that uses `Bytes`:
+
+```prisma
+model User {
+ id Bytes @id @default(auto()) @map("_id") @db.ObjectId
+ // Other fields
+}
+```
+
+See also: [Defining ID fields in MongoDB](/orm/prisma-schema/data-model/models#defining-ids-in-mongodb)
+
+### Generating `ObjectId`
+
+To generate a valid `ObjectId` (for testing purposes or to manually set an ID field value) in your application, use the [`bson`](https://www.npmjs.com/package/bson) package.
+
+```
+npm install --save bson
+```
+
+```ts
+import { ObjectId } from 'bson'
+
+const id = new ObjectId()
+```
+
+## Differences to connectors for relational databases
+
+This section covers ways in which the MongoDB connector differs from Prisma connectors for relational databases.
+
+### No support for Prisma Migrate
+
+Currently, there are no plans to add support for [Prisma Migrate](/orm/prisma-migrate) as MongoDB projects do not rely on internal schemas where changes need to be managed with an extra tool. Management of `@unique` indexes is realized through `db push`.
+
+### No support for `@@id` and `autoincrement()`
+
+The [`@@id`](/orm/reference/prisma-schema-reference#id-1) attribute (an ID for multiple fields) is not supported because primary keys in MongoDB are always on the `_id` field of a model.
+
+The [`autoincrement()`](/orm/reference/prisma-schema-reference#generate-autoincrementing-integers-as-ids) function (which creates incrementing `@id` values) is not supported because `autoincrement()` does not work with the `ObjectID` type that the `_id` field has in MongoDB.
+
+### Cyclic references and referential actions
+
+If you have cyclic references in your models, either from self-relations or a cycle of relations between models, and you use [referential actions](/orm/prisma-schema/data-model/relations/referential-actions), you must set a referential action of `NoAction` to prevent an infinite loop of actions.
+
+See [Special rules for referential actions](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions) for more details.
+
+### Replica set configuration
+
+MongoDB only allows you to start a transaction on a replica set. Prisma uses transactions internally to avoid partial writes on nested queries. This means we inherit the requirement of needing a replica set configured.
+
+When you try to use Prisma's MongoDB connector on a deployment that has no replica set configured, Prisma shows the message `Error: Transactions are not supported by this deployment`. The full text of the error message is the following:
+
+```
+PrismaClientUnknownRequestError2 [PrismaClientUnknownRequestError]:
+Invalid `prisma.post.create()` invocation in
+/index.ts:9:21
+
+ 6 await prisma.$connect()
+ 7
+ 8 // Create the first post
+→ 9 await prisma.post.create(
+ Error in connector: Database error. error code: unknown, error message: Transactions are not supported by this deployment
+ at cb (/node_modules/@prisma/client/runtime/index.js:34804:17)
+ at processTicksAndRejections (internal/process/task_queues.js:97:5) {
+ clientVersion: '3.xx.0'
+}
+```
+
+To resolve this, we suggest you change your deployment to one with a replica set configured.
+
+One simple way for this is to use [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) to launch a free instance that has replica set support out of the box.
+
+There's also an option to run the replica set locally with this guide: https://docs.mongodb.com/manual/tutorial/convert-standalone-to-replica-set
+
+## Type mapping between MongoDB and the Prisma schema
+
+The MongoDB connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma [data model](/orm/prisma-schema/data-model/models) to MongoDB's native column types as follows:
+
+> Alternatively, see [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma type.
+
+### Native type mapping from Prisma to MongoDB
+
+| Prisma | MongoDB |
+| ---------- | ---------------------------------------------------------------------- |
+| `String` | `string` |
+| `Boolean` | `bool` |
+| `Int` | `int` |
+| `BigInt` | `long` |
+| `Float` | `double` |
+| `Decimal` | [Currently unsupported](https://github.com/prisma/prisma/issues/12637) |
+| `DateTime` | `timestamp` |
+| `Bytes` | `binData` |
+| `Json` | |
+
+MongoDB types that are currently unsupported:
+
+- `Decimal128`
+- `Undefined`
+- `DBPointer`
+- `Null`
+- `Symbol`
+- `MinKey`
+- `MaxKey`
+- `Object`
+- `Javascript`
+- `JavascriptWithScope`
+- `Regex`
+
+### Mapping from MongoDB to Prisma types on Introspection
+
+When introspecting a MongoDB database, Prisma uses the relevant [scalar types](/orm/prisma-schema/data-model/models#scalar-fields). Some special types also get additional native type annotations:
+
+| MongoDB (Type \| Aliases) | Prisma | Supported | Native database type attribute | Notes |
+| ------------------------- | -------- | :-------: | :----------------------------- | :---- |
+| `objectId` | `String` | ✔️ | `@db.ObjectId` | |
+
+[Introspection](/orm/prisma-schema/introspection) adds native database types that are **not yet supported** as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) fields:
+
+```prisma file=schema.prisma
+model Example {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ regex Unsupported("RegularExpression")
+}
+```
diff --git a/docs/200-orm/050-overview/500-databases/800-sql-server/020-sql-server-local.mdx b/docs/200-orm/050-overview/500-databases/800-sql-server/020-sql-server-local.mdx
new file mode 100644
index 0000000000..f52fd1c524
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/800-sql-server/020-sql-server-local.mdx
@@ -0,0 +1,53 @@
+---
+title: 'SQL Server on Windows (local)'
+metaTitle: 'SQL Server on Windows'
+metaDescription: 'Set up and configure SQL Server on Windows.'
+---
+
+
+
+To run a Microsoft SQL Server locally on a Windows machine:
+
+1. If you do not have access to an instance of Microsoft SQL Server, download and set up [SQL Server 2019 Developer](https://www.microsoft.com/en-us/sql-server/sql-server-downloads).
+
+1. Download and install [SQL Server Management Studio](https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver15).
+
+1. Use Windows Authentication to log in to Microsoft SQL Server Management Studio (expand the **Server Name** dropdown and click **<Browse for more...>** to find your database engine):
+
+
+
+
+
+## Enable TCP/IP
+
+Prisma Client requires TCP/IP to be enabled. To enable TCP/IP:
+
+1. Open SQL Server Configuration Manager. (Search for "SQL Server Configuration Manager" in the Start Menu, or open the Start Menu and type "SQL Server Configuration Manager".)
+
+1. In the left-hand panel, click **SQL Server Network Configuration** > **Protocols for MSSQLSERVER**
+
+1. Right-click **TCP/IP** and choose **Enable**.
+
+## Enable authentication with SQL logins (Optional)
+
+If you want to use a username and password in your connection URL rather than integrated security, [enable mixed authentication mode](https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/change-server-authentication-mode?view=sql-server-ver15) as follows:
+
+1. Right-click on your database engine in the Object Explorer and click **Properties**.
+
+1. In the Server Properties window, click **Security** in the left-hand list and tick the **SQL Server and Windows Authentication Mode** option, then click **OK**.
+
+1. Right-click on your database engine in the Object Explorer and click **Restart**.
+
+### Enable the `sa` login
+
+To enable the default `sa` (administrator) SQL Server login:
+
+1. In SQL Server Management Studio, in the Object Explorer, expand **Security** > **Logins** and double-click **sa**.
+
+1. On the **General** page, choose a password for the `sa` account (untick **Enforce password policy** if you do not want to enforce a policy).
+
+1. On the **Status** page, under **Settings** > **Login**, tick **Enabled**, then click **OK**.
+
+You can now use the `sa` account in a connection URL and when you log in to SQL Server Management Studio.
+
+> **Note**: The `sa` user has extensive permissions. You can also [create your own login with fewer permissions](https://docs.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-login?view=sql-server-ver15).
diff --git a/docs/200-orm/050-overview/500-databases/800-sql-server/030-sql-server-docker.mdx b/docs/200-orm/050-overview/500-databases/800-sql-server/030-sql-server-docker.mdx
new file mode 100644
index 0000000000..a4179f25f2
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/800-sql-server/030-sql-server-docker.mdx
@@ -0,0 +1,49 @@
+---
+title: 'SQL Server on Docker'
+metaTitle: 'SQL Server on Docker'
+metaDescription: 'Download and use the Microsoft SQL Server Docker image.'
+---
+
+
+
+To run a Microsoft SQL Server container image with Docker:
+
+1. Install and set up [Docker](https://docs.docker.com/get-docker/)
+1. Run the following command in your terminal to download the Microsoft SQL Server 2019 image:
+
+ ```terminal
+ docker pull mcr.microsoft.com/mssql/server:2019-latest
+ ```
+
+1. Create an instance of the container image, replacing the value of `SA_PASSWORD` with a password of your choice:
+
+ ```terminal wrap
+ docker run --name sql_container -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=myPassword' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest
+ ```
+
+1. [Follow Microsoft's instructions to connect to SQL Server and use the `sqlcmd` tool](https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-ver15&pivots=cs1-cmd#connect-to-sql-server), replacing the image name and password with your own.
+
+1. From the `sqlcmd` command prompt, create a new database:
+
+ ```terminal
+ CREATE DATABASE quickstart
+ GO
+ ```
+
+1. Run the following command to check that your database was created successfully:
+
+ ```terminal
+ sp_databases
+ GO
+ ```
+
+
+
+## Connection URL credentials
+
+Based on this example, your credentials are:
+
+- **Username**: sa
+- **Password**: myPassword
+- **Database**: quickstart
+- **Port**: 1433
diff --git a/docs/200-orm/050-overview/500-databases/800-sql-server/index.mdx b/docs/200-orm/050-overview/500-databases/800-sql-server/index.mdx
new file mode 100644
index 0000000000..79dcac9272
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/800-sql-server/index.mdx
@@ -0,0 +1,185 @@
+---
+title: 'Microsoft SQL Server'
+metaTitle: 'Microsoft SQL Server'
+metaDescription: 'This page explains how Prisma can connect to a Microsoft SQL Server database using the Microsoft SQL Server database connector.'
+tocDepth: 4
+---
+
+
+
+The Microsoft SQL Server data source connector connects Prisma to a [Microsoft SQL Server](https://docs.microsoft.com/en-us/sql/sql-server/?view=sql-server-ver15) database server.
+
+
+
+## Example
+
+To connect to a Microsoft SQL Server database, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema file](/orm/prisma-schema):
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "sqlserver"
+ url = env("DATABASE_URL")
+}
+```
+
+The fields passed to the `datasource` block are:
+
+- `provider`: Specifies the `sqlserver` data source connector.
+- `url`: Specifies the [connection URL](#connection-details) for the Microsoft SQL Server database. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL.
+
+## Connection details
+
+The connection URL used to connect to an Microsoft SQL Server database follows the [JDBC standard](https://docs.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15).
+
+The following example uses SQL authentication (username and password) with an enabled TLS encrypted connection:
+
+```
+sqlserver://HOST:PORT;database=DATABASE;user=USER;password=PASSWORD;encrypt=true
+```
+
+
+
+Note: If you are using any of the following characters in your connection string, [you will need to escape them](https://learn.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver16#escaping-values-in-the-connection-url).
+
+```terminal
+:\=;/[]{} # these are characters that will need to be escaped
+```
+
+To escape these characters, use curly braces `{}` around values that contain special characters. As an example:
+
+```terminal
+sqlserver://HOST:PORT;database=DATABASE;user={MyServer/MyUser};password={ThisIsA:SecurePassword;};encrypt=true
+```
+
+
+
+### Using [integrated security](https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/authentication-in-sql-server) (Windows only)
+
+The following example uses the currently logged in Windows user to log in to Microsoft SQL Server:
+
+```
+sqlserver://localhost:1433;database=sample;integratedSecurity=true;trustServerCertificate=true;
+```
+
+The following example uses a specific Active Directory user to log in to Microsoft SQL Server:
+
+```
+sqlserver://localhost:1433;database=sample;integratedSecurity=true;username=prisma;password=aBcD1234;trustServerCertificate=true;
+```
+
+### Using SQL Browser to connect to a named instance
+
+The following example connects to a named instance of Microsoft SQL Server (`mycomputer\sql2019`) using integrated security:
+
+```
+sqlserver://mycomputer\sql2019;database=sample;integratedSecurity=true;trustServerCertificate=true;
+```
+
+### Arguments
+
+| Argument name | Required | Default | Comments |
+| :------------------------------------------------------------------------------------ | :---------------- | :----------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|
`database`
`initial catalog`
| No | `master` | The database to connect to. |
+|
`username`
`user`
`uid`
`userid`
| No - see Comments | | SQL Server login (such as `sa`) _or_ a valid Windows (Active Directory) username if `integratedSecurity` is set to `true` (Windows only). |
+|
`password`
`pwd`
| No - see Comments | | Password for SQL Server login _or_ Windows (Active Directory) username if `integratedSecurity` is set to `true` (Windows only). |
+| `encrypt` | No | `true` | Configures whether to use TLS all the time, or only for the login procedure, possible values: `true` (use always), `false` (only for login credentials). |
+| `integratedSecurity` | No | | Enables [Windows authentication (integrated security)](https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/authentication-in-sql-server), possible values: `true`, `false`, `yes`, `no`. If set to `true` or `yes` and `username` and `password` are present, login is performed through Windows Active Directory. If login details are not given via separate arguments, the current logged in Windows user is used to login to the server. |
+| `connectionLimit` | No | `num_cpus * 2 + 1` | Maximum size of the [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) |
+| `connectTimeout` | No | `5` | Maximum number of seconds to wait for a new connection |
+| `schema` | No | `dbo` | Added as a prefix to all the queries if schema name is not the default. |
+|
`loginTimeout`
`connectTimeout`
`connectionTimeout`
| No | | Number of seconds to wait for login to succeed. |
+| `socketTimeout` | No | | Number of seconds to wait for each query to succeed. |
+| `isolationLevel` | No | | Sets [transaction isolation level](https://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-ver15). |
+| `poolTimeout` | No | `10` | Maximum number of seconds to wait for a new connection from the pool. If all connections are in use, the database will return a `PoolTimeout` error after waiting for the given time. |
+|
`ApplicationName`
`Application Name`
(case insensitive) | No | | Sets the application name for the connection. Since version 2.28.0. |
+| `trustServerCertificate` | No | `false` | Configures whether to trust the server certificate. |
+| `trustServerCertificateCA` | No | | A path to a certificate authority file to be used instead of the system certificates to authorize the server certificate. Must be either in `pem`, `crt` or `der` format. Cannot be used together with `trustServerCertificate` parameter. |
+
+## Type mapping between Microsoft SQL Server to Prisma schema
+
+For type mappings organized by Prisma type, refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) documentation.
+
+## Supported versions
+
+See [Supported databases](/orm/reference/supported-databases).
+
+## Limitations and known issues
+
+### Prisma Migrate caveats
+
+Prisma Migrate is supported in [2.13.0](https://github.com/prisma/prisma/releases/tag/2.13.0) and later with the following caveats:
+
+#### Database schema names
+
+SQL Server does not have an equivalent to the PostgreSQL `SET search_path` command familiar from PostgreSQL. This means that when you create migrations, you must define the same schema name in the connection URL that is used by the production database. For most of the users this is `dbo` (the default value). However, if the production database uses another schema name, all the migration SQL must be either edited by hand to reflect the production _or_ the connection URL must be changed before creating migrations (for example: `schema=name`).
+
+#### Cyclic references
+
+Circular references can occur between models when each model references another, creating a closed loop. When using a Microsoft SQL Server database, Prisma will show a validation error if the [referential action](/orm/prisma-schema/data-model/relations/referential-actions) on a relation is set to something other than [`NoAction`](/orm/prisma-schema/data-model/relations/referential-actions#noaction).
+
+See [Special rules for referential actions in SQL Server](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions) for more information.
+
+#### Destructive changes
+
+Certain migrations will cause more changes than you might expect. For example:
+
+- Adding or removing `autoincrement()`. This cannot be achieved by modifying the column, but requires recreating the table (including all constraints, indices, and foreign keys) and moving all data between the tables.
+- Additionally, it is not possible to delete all the columns from a table (possible with PostgreSQL or MySQL). If a migration needs to recreate all table columns, it will also re-create the table.
+
+#### Shared default values are not supported
+
+In some cases, user might want to define default values as shared objects:
+
+```sql file=default_objects.sql
+CREATE DEFAULT catcat AS 'musti';
+
+CREATE TABLE cats (
+ id INT IDENTITY PRIMARY KEY,
+ name NVARCHAR(1000)
+);
+
+sp_bindefault 'catcat', 'dbo.cats.name';
+```
+
+Using the stored procedure `sp_bindefault`, the default value `catcat` can be used in more than one table. The way Prisma manages default values is per table:
+
+```sql file=default_per_table.sql
+CREATE TABLE cats (
+ id INT IDENTITY PRIMARY KEY,
+ name NVARCHAR(1000) CONSTRAINT DF_cat_name DEFAULT 'musti'
+);
+```
+
+The last example, when introspected, leads to the following model:
+
+```prisma file=schema.prisma
+model cats {
+ id Int @id @default(autoincrement())
+ name String? @default("musti")
+}
+```
+
+And the first doesn't get the default value introspected:
+
+```prisma file=schema.prisma
+model cats {
+ id Int @id @default(autoincrement())
+ name String?
+}
+```
+
+If using Prisma Migrate together with shared default objects, changes to them must be done manually to the SQL.
+
+### Data model limitations
+
+#### Cannot use column with `UNIQUE` constraint and filtered index as foreign key
+
+Microsoft SQL Server [only allows one `NULL` value in a column that has a `UNIQUE` constraint](https://docs.microsoft.com/en-us/sql/relational-databases/tables/unique-constraints-and-check-constraints?view=sql-server-ver15#Unique). For example:
+
+- A table of users has a column named `license_number`
+- The `license_number` field has a `UNIQUE` constraint
+- The `license_number` field only allows **one** `NULL` value
+
+The standard way to get around this issue is to create a filtered unique index that excludes `NULL` values. This allows you to insert multiple `NULL` values. If you do not create an index in the database, you will get an error if you try to insert more than one `null` value into a column with Prisma Client.
+
+_However_, creating an index makes it impossible to use `license_number` as a foreign key in the database (or a relation scalar field in corresponding Prisma Schema)
diff --git a/docs/200-orm/050-overview/500-databases/850-planetscale.mdx b/docs/200-orm/050-overview/500-databases/850-planetscale.mdx
new file mode 100644
index 0000000000..a018c3d3df
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/850-planetscale.mdx
@@ -0,0 +1,316 @@
+---
+title: 'PlanetScale'
+metaTitle: 'PlanetScale'
+metaDescription: 'Guide to PlanetScale'
+tocDepth: 3
+toc: true
+---
+
+
+
+Prisma and [PlanetScale](https://planetscale.com/) together provide a development arena that optimizes rapid, type-safe development of data access applications, using Prisma's ORM and PlanetScale's highly scalable MySQL-based platform.
+
+This document discusses the concepts behind using Prisma and PlanetScale, explains the commonalities and differences between PlanetScale and other database providers, and leads you through the process for configuring your application to integrate with PlanetScale.
+
+
+
+## What is PlanetScale?
+
+PlanetScale uses the [Vitess](https://vitess.io/) database clustering system to provide a MySQL-compatible database platform. Features include:
+
+- **Enterprise scalability.** PlanetScale provides a highly available production database cluster that supports scaling across multiple database servers. This is particularly useful in a serverless context, as it avoids the problem of having to [manage connection limits](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas).
+- **Database branches.** PlanetScale allows you to create [branches of your database schema](https://planetscale.com/docs/concepts/branching), so that you can test changes on a development branch before applying them to your production database.
+- **Support for [non-blocking schema changes](https://planetscale.com/docs/concepts/nonblocking-schema-changes).** PlanetScale provides a workflow that allows users to update database schemas without locking the database or causing downtime.
+
+## Commonalities with other database providers
+
+Many aspects of using Prisma with PlanetScale are just like using Prisma with any other relational database. You can still:
+
+- model your database with the [Prisma Schema Language](/orm/prisma-schema)
+- use Prisma's existing [`mysql` database connector](/orm/overview/databases/mysql) in your schema, along with the [connection string PlanetScale provides you](https://planetscale.com/docs/concepts/connection-strings)
+- use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a database schema in PlanetScale
+- use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) to push changes in your schema to the database
+- use [Prisma Client](/orm/prisma-client) in your application to talk to the database server at PlanetScale
+
+## Differences to consider
+
+PlanetScale's branching model and design for scalability means that there are also a number of differences to consider. You should be aware of the following points when deciding to use PlanetScale with Prisma:
+
+- **Branching and deploy requests.** PlanetScale provides two types of database branches: _development branches_, which allow you to test out schema changes, and _production branches_, which are protected from direct schema changes. Instead, changes must be first created on a development branch and then deployed to production using a deploy request. Production branches are highly available and include automated daily backups. To learn more, see [How to use branches and deploy requests](#how-to-use-branches-and-deploy-requests).
+
+- **Referential actions and integrity.** To support scaling across multiple database servers, PlanetScale [does not allow the use of foreign key constraints](https://planetscale.com/docs/learn/operating-without-foreign-key-constraints), which are normally used in relational databases to enforce relationships between data in different tables, and asks users to handle this manually in their applications.
+ With Prisma you can maintain these relationships in your data and allow the use of [referential actions](/orm/prisma-schema/data-model/relations/referential-actions) by using Prisma's ability to [emulate relations in Prisma Client](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-with-the-prisma-relation-mode) with the `prisma` relation mode. For more information, see [How to emulate relations in Prisma Client](#how-to-emulate-relations-in-prisma-client).
+
+- **Creating indexes on foreign keys.** When emulating relations in Prisma, you will need to create indexes on foreign keys. In a standard MySQL database, if a table has a column with a foreign key constraint, an index is automatically created on that column. Because PlanetScale does not support foreign keys, these indexes are [currently](https://github.com/prisma/prisma/issues/10611) not created when Prisma Client emulates relations, which can lead to issues with queries not being well optimised. To avoid this, you can create indexes in Prisma. For more information, see [How to create indexes on foreign keys](#how-to-create-indexes-on-foreign-keys).
+
+- **Making schema changes with `db push`.** When you merge a development branch into your production branch, PlanetScale will automatically compare the two schemas and generate its own schema diff. This means that Prisma's [`prisma migrate`](/orm/prisma-migrate) workflow, which generates its own history of migration files, is not a natural fit when working with PlanetScale. These migration files may not reflect the actual schema changes run by PlanetScale when the branch is merged.
+
+
+
+ Prisma recommends not using `prisma migrate` when making schema changes with PlanetScale. Instead, we recommend that you use the `prisma db push` command.
+
+
+
+ For an example of how this works, see [How to make schema changes with `db push`](#how-to-make-schema-changes-with-db-push)
+
+- **Introspection**. When you introspect on an existing database, you will get a schema with no relations, as they are usually defined based on foreign keys that connect tables. Because PlanetScale does not support foreign keys, and you use Prisma to emulate relations, you will need to add the missing relations in manually. For more information, see [How to add in missing relations after Introspection](#how-to-add-in-missing-relations-after-introspection).
+
+## How to use branches and deploy requests
+
+When connecting to PlanetScale with Prisma, you will need to use the correct connection string for your branch. The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' from the dropdown to get the Prisma format for the connection URL. See Prisma's [Getting Started guide](/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale) for more details of how to connect to a PlanetScale database.
+
+Every PlanetScale database is created with a branch called `main`, which is initially a development branch that you can use to test schema changes on. Once you are happy with the changes you make there, you can [promote it](https://planetscale.com/docs/concepts/branching#promote-a-branch-to-production) to become a production branch. Note that you can only push new changes to a development branch, so further changes will need to be created on a separate development branch and then later deployed to production using a [deploy request](https://planetscale.com/docs/concepts/branching#2.-create-a-deploy-request).
+
+If you try to push to a production branch, you will get the [error message](/orm/reference/error-reference#p3022) `Direct execution of DDL (Data Definition Language) SQL statements is disabled on this database.`
+
+## How to emulate relations in Prisma Client
+
+PlanetScale does not allow foreign keys in its database schema. By default, Prisma uses foreign keys in the underlying database to enforce relations between fields in your Prisma schema. In Prisma versions 3.1.1 and later, you can [emulate relations in Prisma Client with the `prisma` relation mode](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-with-the-prisma-relation-mode), which avoids the need for foreign keys in the database.
+
+To enable emulation of relations in Prisma Client, set the `relationMode` field to `"prisma"` in the `datasource` block:
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "mysql"
+ url = env("DATABASE_URL")
+ relationMode = "prisma"
+}
+```
+
+
+
+The ability to set the relation mode was introduced as part of the `referentialIntegrity` preview feature in Prisma version 3.1.1, and is generally available in Prisma versions 4.8.0 and later.
The `relationMode` field was renamed in Prisma version 4.5.0, and was previously named `referentialIntegrity`.
+
+
+
+If you use relations in your Prisma schema with the default `"foreignKeys"` option for the `referentialIntegrity` field, PlanetScale will error when Prisma tries to create foreign keys. In versions 2.27.0 and later, Prisma will output the [P3021 error message](/orm/reference/error-reference#p3021).
+
+## How to create indexes on foreign keys
+
+When [you emulate relations in Prisma Client](#how-to-emulate-relations-in-prisma-client), you need to create your own indexes. As an example of a situation where you would want to add an index, take this schema for a blog with posts and comments:
+
+```prisma file=schema.prisma
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String
+ likes Int @default(0)
+ comments Comment[]
+}
+
+model Comment {
+ id Int @id @default(autoincrement())
+ comment String
+ postId Int
+ post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
+}
+```
+
+The `postId` field in the `Comment` model refers to the corresponding `id` field in the `Post` model. However this is not implemented as a foreign key in PlanetScale, so the column doesn't have an automatic index. This means that some queries may not be well optimised. For example, if you query for all comments with a certain post `id`, PlanetScale may have to do a full table lookup. This could be slow, and also expensive because PlanetScale's billing model charges for the number of rows read.
+
+To avoid this, you can define an index on the `postId` field using [Prisma's `@@index` argument](/orm/reference/prisma-schema-reference#index):
+
+```prisma file=schema.prisma highlight=15;add
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String
+ likes Int @default(0)
+ comments Comment[]
+}
+
+model Comment {
+ id Int @id @default(autoincrement())
+ comment String
+ postId Int
+ post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
+
+ @@index([postId])
+}
+```
+
+You can then add this change to your schema [using `db push`](#how-to-make-schema-changes-with-db-push).
+
+In Prisma versions 4.7.0 and later, Prisma warns you if you have a relation with no index on the relation scalar field. For more information, see [Index validation](/orm/prisma-schema/data-model/relations/relation-mode#index-validation).
+
+
+
+One issue to be aware of is that [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) cannot have an index added in this way. If query speed or cost is an issue, you may instead want to use an [explicit many-to-many relation](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations) in this case.
+
+
+
+## How to make schema changes with `db push`
+
+To use `db push` with PlanetScale, you will first need to [enable emulation of relations in Prisma Client](#how-to-emulate-relations-in-prisma-client). Pushing to your branch without referential emulation enabled will give the [error message](/orm/reference/error-reference#p3021) `Foreign keys cannot be created on this database.`
+
+As an example, let's say you decide to decide to add a new `excerpt` field to the blog post schema above. You will first need to [create a new development branch and connect to it](#how-to-use-branches-and-deploy-requests).
+
+Next, add the following to your `schema.prisma` file:
+
+```prisma file=schema.prisma highlight=5;edit
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String
+ excerpt String?
+ likes Int @default(0)
+ comments Comment[]
+}
+
+model Comment {
+ id Int @id @default(autoincrement())
+ comment String
+ postId Int
+ post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
+
+ @@index([postId])
+}
+```
+
+To push these changes, navigate to your project directory in your terminal and run
+
+```terminal
+npx prisma db push
+```
+
+Once you are happy with your changes on your development branch, you can open a deploy request to deploy these to your production branch.
+
+For more examples, see PlanetScale's tutorial on [automatic migrations with Prisma](https://planetscale.com/docs/prisma/automatic-prisma-migrations) using `db push`.
+
+## How to add in missing relations after Introspection
+
+After introspecting with `npx prisma db pull`, the schema you get may be missing some relations. For example, the following schema is missing a relation between the `User` and `Post` models:
+
+```prisma file=schema.prisma
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ title String @db.VarChar(255)
+ content String?
+ authorId Int
+
+ @@index([authorId])
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+}
+```
+
+In this case you need to add the relation in manually:
+
+```prisma file=schema.prisma highlight=6,16;add
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ title String @db.VarChar(255)
+ content String?
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+
+ @@index([authorId])
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+```
+
+For a more detailed example, see the [Getting Started guide for PlanetScale](/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-planetscale).
+
+## How to use the PlanetScale serverless driver with Prisma (Preview)
+
+The [PlanetScale serverless driver](https://planetscale.com/docs/tutorials/planetscale-serverless-driver) provides a way of communicating with your database and executing queries over HTTP.
+
+You can use Prisma along with the PlanetScale serverless driver using the [`@prisma/adapter-planetscale`](https://www.npmjs.com/package/@prisma/adapter-planetscale) driver adapter. The driver adapter allows you to communicate with your database over HTTP.
+
+
+
+This feature is available in Preview from Prisma versions 5.4.2 and later.
+
+
+
+To get started, enable the `driverAdapters` Preview feature flag:
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["driverAdapters"]
+}
+```
+
+Generate Prisma Client:
+
+```sh
+npx prisma generate
+```
+
+
+
+Ensure you update the host value in your connection string to `aws.connect.psdb.cloud`. You can learn more about this [here](https://planetscale.com/docs/tutorials/planetscale-serverless-driver#add-and-use-the-planetscale-serverless-driver-for-javascript-to-your-project).
+
+```bash
+DATABASE_URL='mysql://johndoe:strongpassword@aws.connect.psdb.cloud/clear_nightsky?sslaccept=strict'
+```
+
+
+
+Install the Prisma adapter for PlanetScale, PlanetScale serverless driver and `undici` packages:
+
+```sh
+npm install @prisma/adapter-planetscale @planetscale/database undici
+```
+
+
+
+When using a Node.js version below 18, you must provide a custom fetch function implementation. We recommend the `undici` package on which Node's built-in fetch is based. Node.js versions 18 and later include a built-in global `fetch` function, so you don't have to install an extra package.
+
+
+
+Update your Prisma Client instance to use the PlanetScale serverless driver:
+
+```ts
+import { Client } from '@planetscale/database'
+import { PrismaPlanetScale } from '@prisma/adapter-planetscale'
+import { PrismaClient } from '@prisma/client'
+import dotenv from 'dotenv'
+import { fetch as undiciFetch } from 'undici'
+
+dotenv.config()
+const connectionString = `${process.env.DATABASE_URL}`
+
+const client = new Client({ url: connectionString, fetch: undiciFetch })
+const adapter = new PrismaPlanetScale(client)
+const prisma = new PrismaClient({ adapter })
+```
+
+You can then use Prisma Client as you normally would with full type-safety. Prisma Migrate, introspection, and Prisma Studio will continue working as before using the connection string defined in the Prisma schema.
+
+## More on using PlanetScale with Prisma
+
+The fastest way to start using PlanetScale with Prisma is to refer to our Getting Started documentation:
+
+- [Start from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale)
+- [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale)
+
+These tutorials will take you through the process of connecting to PlanetScale, pushing schema changes, and using Prisma Client.
+
+For further tips on best practices when using Prisma and PlanetScale together, watch our video:
+
+
+
+
+
+
diff --git a/docs/200-orm/050-overview/500-databases/860-cockroachdb.mdx b/docs/200-orm/050-overview/500-databases/860-cockroachdb.mdx
new file mode 100644
index 0000000000..eda18fc474
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/860-cockroachdb.mdx
@@ -0,0 +1,224 @@
+---
+title: 'CockroachDB'
+metaTitle: 'CockroachDB'
+metaDescription: 'Guide to CockroachDB'
+tocDepth: 3
+toc: true
+---
+
+
+
+This guide discusses the concepts behind using Prisma and CockroachDB, explains the commonalities and differences between CockroachDB and other database providers, and leads you through the process for configuring your application to integrate with CockroachDB.
+
+
+
+
+
+The CockroachDB connector is generally available in versions `3.14.0` and later. It was first added as a [Preview feature](/orm/reference/preview-features) in version [`3.9.0`](https://github.com/prisma/prisma/releases/tag/3.9.0) with support for Introspection, and Prisma Migrate support was added in [`3.11.0`](https://github.com/prisma/prisma/releases/tag/3.11.0).
+
+
+
+## What is CockroachDB?
+
+CockroachDB is a distributed database that is designed for scalability and high availability. Features include:
+
+- **Built-in scaling:** CockroachDB comes with automated replication, failover and repair capabilities to allow easy horizontal scaling of your application
+- **Consistent transactions:** CockroachDB is a relational database that supports consistent transactions that maintain data integrity
+- **Compatibility with PostgreSQL:** CockroachDB is compatible with PostgreSQL, allowing interoperability with a large ecosystem of existing products
+
+## Commonalities with other database providers
+
+CockroachDB is largely compatible with PostgreSQL, and can mostly be used with Prisma in the same way. You can still:
+
+- model your database with the [Prisma Schema Language](/orm/prisma-schema)
+- connect to your database, using Prisma's [`cockroachdb` database connector](/orm/overview/databases/cockroachdb)
+- use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a CockroachDB database
+- use [Prisma Migrate](/orm/prisma-migrate) to migrate your database schema to a new version
+- use [Prisma Client](/orm/prisma-client) in your application to query your database in a type safe way based on your Prisma Schema
+
+## Differences to consider
+
+There are some CockroachDB-specific differences to be aware of when working with Prisma's `cockroachdb` connector:
+
+- **Cockroach-specific native types:** Prisma's `cockroachdb` database connector provides support for CockroachDB's native data types. To learn more, see [How to use CockroachDB's native types](#how-to-use-cockroachdbs-native-types).
+
+- **Creating database keys:** Prisma allows you to generate a unique identifier for each record using the [`autoincrement()`](/orm/reference/prisma-schema-reference#autoincrement) function. For more information, see [How to use database keys with CockroachDB](#how-to-use-database-keys-with-cockroachdb).
+
+## How to use Prisma with CockroachDB
+
+This section provides more details on how to use CockroachDB-specific features.
+
+### How to use CockroachDB's native types
+
+CockroachDB has its own set of native [data types](https://www.cockroachlabs.com/docs/stable/data-types.html) which are supported in Prisma. For example, CockroachDB uses the `STRING` data type instead of PostgreSQL's `VARCHAR`.
+
+As a demonstration of this, say you create a `User` table in your CockroachDB database using the following SQL command:
+
+```sql
+CREATE TABLE public."Post" (
+ "id" INT8 NOT NULL,
+ "title" VARCHAR(200) NOT NULL,
+ CONSTRAINT "Post_pkey" PRIMARY KEY ("id" ASC),
+ FAMILY "primary" ("id", "title")
+);
+```
+
+After introspecting your database with `npx prisma db pull`, you will have a new `Post` model in your `schema.prisma` file:
+
+```prisma file=schema.prisma
+model Post {
+ id BigInt @id
+ title String @db.String(200)
+}
+```
+
+Notice that the `title` field has been annotated with `@db.String(200)` — this differs from PostgreSQL where the annotation would be `@db.VarChar(200)`.
+
+For a full list of type mappings, see our [connector documentation](/orm/overview/databases/cockroachdb#type-mapping-between-cockroachdb-and-the-prisma-schema).
+
+### How to use database keys with CockroachDB
+
+When generating unique identifiers for records in a distributed database like CockroachDB, it is best to avoid using sequential IDs – for more information on this, see CockroachDB's [blog post on choosing index keys](https://cockroachlabs.com/blog/how-to-choose-db-index-keys).
+
+Instead, Prisma provides the [`autoincrement()`](/orm/reference/prisma-schema-reference#autoincrement) attribute function, which uses CockroachDB's [`unique_rowid()` function](https://www.cockroachlabs.com/docs/stable/serial.html) for generating unique identifiers. For example, the following `User` model has an `id` primary key, generated using the `autoincrement()` function:
+
+```prisma file=schema.prisma
+model User {
+ id BigInt @id @default(autoincrement())
+ name String
+}
+```
+
+For compatibility with existing databases, you may sometimes still need to generate a fixed sequence of integer key values. In these cases, you can use Prisma's inbuilt [`sequence()`](/orm/reference/prisma-schema-reference#sequence) function for CockroachDB. For a list of available options for the `sequence()` function, see our [reference documentation](/orm/reference/prisma-schema-reference#sequence).
+
+For more information on generating database keys, see CockroachDB's [Primary key best practices](https://www.cockroachlabs.com/docs/v21.2/schema-design-table#primary-key-best-practices) guide.
+
+## Example
+
+To connect to a CockroachDB database server, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema file](/orm/prisma-schema):
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "cockroachdb"
+ url = env("DATABASE_URL")
+}
+```
+
+The fields passed to the `datasource` block are:
+
+- `provider`: Specifies the `cockroachdb` data source connector.
+- `url`: Specifies the [connection URL](#connection-details) for the CockroachDB database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL.
+
+
+
+While `cockroachdb` and `postgresql` connectors are similar, it is mandatory to use the `cockroachdb` connector instead of `postgresql` when connecting to a CockroachDB database from version 5.0.0.
+
+
+
+## Connection details
+
+CockroachDB uses the PostgreSQL format for its connection URL. See the [PostgreSQL connector documentation](/orm/overview/databases/postgresql#connection-details) for details of this format, and the optional arguments it takes.
+
+## Differences between CockroachDB and PostgreSQL
+
+The following table lists differences between CockroachDB and PostgreSQL:
+
+| Issue | Area | Notes |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| By default, the `INT` type is an alias for `INT8` in CockroachDB, whereas in PostgreSQL it is an alias for `INT4`. This means that Prisma will introspect an `INT` column in CockroachDB as `BigInt`, whereas in PostgreSQL Prisma will introspect it as `Int`. | Schema | For more information on the `INT` type, see the [CockroachDB documentation](https://www.cockroachlabs.com/docs/stable/int.html#considerations-for-64-bit-signed-integers) |
+| When using `@default(autoincrement())` on a field, CockroachDB will automatically generate 64-bit integers for the row IDs. These integers will be increasing but not consecutive. This is in contrast to PostgreSQL, where generated row IDs are consecutive and start from 1. | Schema | For more information on generated values, see the [CockroachDB documentation](https://www.cockroachlabs.com/docs/stable/serial.html#generated-values-for-modes-rowid-and-virtual_sequence) |
+| The `@default(autoincrement())` attribute can only be used together with the `BigInt` field type. | Schema | For more information on generated values, see the [CockroachDB documentation](https://www.cockroachlabs.com/docs/stable/serial.html#generated-values-for-modes-rowid-and-virtual_sequence) |
+
+## Type mapping limitations in CockroachDB
+
+The CockroachDB connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma [data model](/orm/prisma-schema/data-model/models) to native column types. These native types are mostly the same as for PostgreSQL — see the [Native type mapping from Prisma to CockroachDB](#native-type-mapping-from-prisma-to-cockroachdb) for details. However, there are some limitations:
+
+| CockroachDB (Type \| Aliases) | Prisma | Supported | Native database type attribute | Notes |
+| ----------------------------- | --------- | :-------: | :----------------------------- | :------------------------------------------------------------------------------------------------------------------------- |
+| `money` | `Decimal` | Not yet | `@db.Money` | Supported in PostgreSQL but [not currently in CockroachDB](https://github.com/cockroachdb/cockroach/issues/41578) |
+| `xml` | `String` | Not yet | `@db.Xml` | Supported in PostgreSQL but [not currently in CockroachDB](https://github.com/cockroachdb/cockroach/issues/43355) |
+| `jsonb` arrays | `Json[]` | Not yet | N/A | `Json[]` supported in PostgreSQL but [not currently in CockroachDB](https://github.com/cockroachdb/cockroach/issues/23468) |
+
+## Other limitations
+
+The following table lists any other current known limitations of CockroachDB compared to PostgreSQL:
+
+| Issue | Area | Notes |
+| ------------------------------------------------------------------------------------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Primary keys are named `primary` instead of `TABLE_pkey`, the Prisma default. | Introspection | This means that they are introspected as `@id(map: "primary")`. This will be [fixed in CockroachDB 22.1](https://github.com/cockroachdb/cockroach/pull/70604). |
+| Foreign keys are named `fk_COLUMN_ref_TABLE` instead of `TABLE_COLUMN_fkey`, the Prisma default. | Introspection | This means that they are introspected as `@relation([...], map: "fk_COLUMN_ref_TABLE")`. This will be [fixed in CockroachDB 22.1](https://github.com/cockroachdb/cockroach/pull/70658) |
+| Index types `Hash`, `Gist`, `SpGist` or `Brin` are not supported. | Schema | In PostgreSQL, Prisma allows [configuration of indexes](/orm/prisma-schema/data-model/indexes#configuring-the-access-type-of-indexes-with-type-postgresql) to use the different index access method. CockroachDB only currently supports `BTree` and `Gin`. |
+| Pushing to `Enum` types not supported | Client | Pushing to `Enum` types (e.g. `data: { enum { push: "A" }, }`) is currently [not supported in CockroachDB](https://github.com/cockroachdb/cockroach/issues/71388) |
+| Searching on `String` fields without a full text index not supported | Client | Searching on `String` fields without a full text index (e.g. `where: { text: { search: "cat & dog", }, },`) is currently [not supported in CockroachDB](https://github.com/cockroachdb/cockroach/issues/7821) |
+| Integer division not supported | Client | Integer division (e.g. `data: { int: { divide: 10, }, }`) is currently [not supported in CockroachDB](https://github.com/cockroachdb/cockroach/issues/41448) |
+| Limited filtering on `Json` fields | Client | Currently CockroachDB [only supports](https://github.com/cockroachdb/cockroach/issues/49144) `equals` and `not` filtering on `Json` fields |
+
+## Type mapping between CockroachDB and the Prisma schema
+
+The CockroachDB connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma [data model](/orm/prisma-schema/data-model/models) as follows to native column types:
+
+> Alternatively, see the [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma type.
+
+### Native type mapping from Prisma to CockroachDB
+
+| Prisma | CockroachDB |
+| ---------- | ---------------- |
+| `String` | `STRING` |
+| `Boolean` | `BOOL` |
+| `Int` | `INT4` |
+| `BigInt` | `INT8` |
+| `Float` | `FLOAT8` |
+| `Decimal` | `DECIMAL(65,30)` |
+| `DateTime` | `TIMESTAMP(3)` |
+| `Json` | `JSONB` |
+| `Bytes` | `BYTES` |
+
+### Mapping from CockroachDB to Prisma types on Introspection
+
+When introspecting a CockroachDB database, the database types are mapped to Prisma according to the following table:
+
+| CockroachDB (Type \| Aliases) | Prisma | Supported | Native database type attribute | Notes |
+| -------------------------------------------- | ---------- | :-------: | :----------------------------- | :--------------------------------------------------------------------- |
+| `INT` \| `BIGINT`, `INTEGER` | `BigInt` | ✔️ | `@db.Int8` | |
+| `BOOL` \| `BOOLEAN` | `Bool` | ✔️ | `@db.Bool`\* | |
+| `TIMESTAMP` \| `TIMESTAMP WITHOUT TIME ZONE` | `DateTime` | ✔️ | `@db.Timestamp(x)` | |
+| `TIMESTAMPTZ` \| `TIMESTAMP WITH TIME ZONE` | `DateTime` | ✔️ | `@db.Timestamptz(x)` | |
+| `TIME` \| `TIME WITHOUT TIME ZONE` | `DateTime` | ✔️ | `@db.Time(x)` | |
+| `TIMETZ` \| `TIME WITH TIME ZONE` | `DateTime` | ✔️ | `@db.Timetz(x)` | |
+| `DECIMAL(p,s)` \| `NUMERIC(p,s)`, `DEC(p,s)` | `Decimal` | ✔️ | `@db.Decimal(x, y)` | |
+| `REAL` \| `FLOAT4`, `FLOAT` | `Float` | ✔️ | `@db.Float4` | |
+| `DOUBLE PRECISION` \| `FLOAT8` | `Float` | ✔️ | `@db.Float8` | |
+| `INT2` \| `SMALLINT` | `Int` | ✔️ | `@db.Int2` | |
+| `INT4` | `Int` | ✔️ | `@db.Int4` | |
+| `CHAR(n)` \| `CHARACTER(n)` | `String` | ✔️ | `@db.Char(x)` | |
+| `"char"` | `String` | ✔️ | `@db.CatalogSingleChar` | Internal type for CockroachDB catalog tables, not meant for end users. |
+| `STRING` \| `TEXT`, `VARCHAR` | `String` | ✔️ | `@db.String` | |
+| `DATE` | `DateTime` | ✔️ | `@db.Date` | |
+| `ENUM` | `enum` | ✔️ | N/A | |
+| `INET` | `String` | ✔️ | `@db.Inet` | |
+| `BIT(n)` | `String` | ✔️ | `@Bit(x)` | |
+| `VARBIT(n)` \| `BIT VARYING(n)` | `String` | ✔️ | `@VarBit` | |
+| `OID` | `Int` | ✔️ | `@db.Oid` | |
+| `UUID` | `String` | ✔️ | `@db.Uuid` | |
+| `JSONB` \| `JSON` | `Json` | ✔️ | `@db.JsonB` | |
+| Array types | `[]` | ✔️ | | |
+
+[Introspection](/orm/prisma-schema/introspection) adds native database types that are **not yet supported** as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) fields:
+
+```prisma file=schema.prisma
+model Device {
+ id BigInt @id @default(autoincrement())
+ interval Unsupported("INTERVAL")
+}
+```
+
+## More on using CockroachDB with Prisma
+
+The fastest way to start using CockroachDB with Prisma is to refer to our Getting Started documentation:
+
+- [Start from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-cockroachdb)
+- [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-cockroachdb)
+
+These tutorials will take you through the process of connecting to CockroachDB, migrating your schema, and using Prisma Client.
+
+Further reference information is available in the [CockroachDB connector documentation](/orm/overview/databases/cockroachdb).
diff --git a/docs/200-orm/050-overview/500-databases/880-supabase.mdx b/docs/200-orm/050-overview/500-databases/880-supabase.mdx
new file mode 100644
index 0000000000..c00f56e344
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/880-supabase.mdx
@@ -0,0 +1,72 @@
+---
+title: 'Supabase'
+metaTitle: 'Supabase'
+metaDescription: 'Guide to Supabase'
+tocDepth: 2
+toc: true
+---
+
+
+
+This guide discusses the concepts behind using Prisma and Supabase, explains the commonalities and differences between Supabase and other database providers, and leads you through the process for configuring your application to integrate with Supabase.
+
+
+
+## What is Supabase?
+
+[Supabase](https://supabase.com/) is a PostgreSQL hosting service and open source Firebase alternative providing all the backend features you need to build a product. Unlike Firebase, Supabase is backed by PostgreSQL which can be accessed directly using Prisma.
+
+To learn more about Supabase, you can check out their architecture [here](https://supabase.com/docs/guides/getting-started/architecture) and features [here](https://supabase.com/docs/guides/getting-started/features)
+
+## Commonalities with other database providers
+
+Many aspects of using Prisma with Supabase are just like using Prisma with any other relational database. You can still:
+
+- model your database with the [Prisma Schema Language](/orm/prisma-schema)
+- use Prisma's existing [`postgresql` database connector](/orm/overview/databases/postgresql) in your schema, along with the [connection string Supabase provides you](https://supabase.com/docs/guides/database/connecting-to-postgres#finding-your-connection-string)
+- use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a database schema in Supabase
+- use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) to push changes in your schema to Supabase
+- use [Prisma Client](/orm/prisma-client) in your application to talk to the database server at Supabase
+
+## Specific considerations
+
+If you'd like to use the [connection pooling feature](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooler) available with Supabase, you will need to use the connection pooling connection string available via your [Supabase database settings](https://supabase.com/dashboard/project/_/settings/database) with `?pgbouncer=true` appended to the end of your `DATABASE_URL` environment variable:
+
+```env file=.env
+# Connect to Supabase via connection pooling with Supavisor.
+DATABASE_URL="postgres://postgres.[your-supabase-project]:[password]@aws-0-eu-central-1.pooler.supabase.com:6543/postgres?pgbouncer=true"
+```
+
+If you would like to use the Prisma CLI in order to perform other actions on your database (e.g. migrations) you will need to add a `DIRECT_URL` environment variable to use in the `datasource.directUrl` property so that the CLI can bypass Supavisor:
+
+```env file=.env highlight=4-5;add
+# Connect to Supabase via connection pooling with Supavisor.
+DATABASE_URL="postgres://postgres.[your-supabase-project]:[password]@aws-0-eu-central-1.pooler.supabase.com:6543/postgres?pgbouncer=true"
+
+# Direct connection to the database. Used for migrations.
+DIRECT_URL="postgres://postgres:[password]@db.[your-supabase-project].supabase.co:5432/postgres"
+```
+
+You can then update your `schema.prisma` to use the new direct URL:
+
+```prisma file=schema.prisma highlight=4;add
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+```
+
+More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields).
+
+
+
+We strongly recommend using connection pooling with Supavisor in addition to `DIRECT_URL`. You will gain the great developer experience of the Prisma CLI while also allowing for connections to be pooled regardless of your deployment strategy. While this is not strictly necessary for every app, serverless solutions will inevitably require connection pooling.
+
+
+
+## Getting started with Supabase
+
+If you're interested in learning more, Supabase has a great guide for connecting a database provided by Supabase to your Prisma project available [here](https://supabase.com/docs/guides/integrations/prisma).
+
+If you're running into issues integrating with Supabase, check out these [specific troubleshooting tips](https://supabase.com/docs/guides/integrations/prisma#troubleshooting) or [Prisma's GitHub Discussions](https://github.com/prisma/prisma/discussions) for more help.
diff --git a/docs/200-orm/050-overview/500-databases/890-neon.mdx b/docs/200-orm/050-overview/500-databases/890-neon.mdx
new file mode 100644
index 0000000000..64e29e934e
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/890-neon.mdx
@@ -0,0 +1,183 @@
+---
+title: 'Neon'
+metaTitle: 'Neon'
+metaDescription: 'Guide to Neon'
+tocDepth: 2
+toc: true
+---
+
+
+
+This guide explains how to:
+
+- [Connect Prisma using Neon's connection pooling feature](#how-to-use-neons-connection-pooling)
+- [Resolve connection timeout issues](#resolving-connection-timeouts)
+- [Use Neon's serverless driver with Prisma](#how-to-use-neons-serverless-driver-with-prisma-preview)
+
+
+
+## What is Neon?
+
+
+
+[Neon](https://neon.tech/) is a fully managed serverless PostgreSQL with a generous free tier. Neon separates storage and compute, and offers modern developer features such as serverless, branching, bottomless storage, and more. Neon is open source and written in Rust.
+
+Learn more about Neon [here](https://neon.tech/docs).
+
+## Commonalities with other database providers
+
+Many aspects of using Prisma with Neon are just like using Prisma with any other PostgreSQL database. You can:
+
+- model your database with the [Prisma Schema Language](/orm/prisma-schema)
+- use Prisma's [`postgresql` database connector](/orm/overview/databases/postgresql) in your schema, along with the [connection string Neon provides you](https://neon.tech/docs/connect/connect-from-any-app)
+- use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a database schema on Neon
+- use [`prisma migrate dev`](/orm/prisma-migrate/workflows/development-and-production) to track schema migrations in your Neon database
+- use [`prisma db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) to push changes in your schema to Neon
+- use [Prisma Client](/orm/prisma-client) in your application to communicate with the database hosted by Neon
+
+## Differences to consider
+
+There are a few differences between Neon and PostgreSQL you should be aware of the following when deciding to use Neon with Prisma:
+
+- **Neon's serverless model** — By default, Neon scales a [compute](https://neon.tech/docs/introduction/compute-lifecycle) to zero after 5 minutes of inactivity. During this state, a compute instance is in _idle_ state. A characteristic of this feature is the concept of a "cold start". Activating a compute from an idle state takes from 500ms to a few seconds. Depending on how long it takes to connect to your database, your application may timeout. To learn more, see: [Connection latency and timeouts](https://neon.tech/docs/guides/prisma#connection-timeouts).
+- **Neon's connection pooler** — Neon offers connection pooling using PgBouncer, enabling up to 10,000 concurrent connections. To learn more, see: [Connection pooling](https://neon.tech/docs/connect/connection-pooling).
+
+## How to use Neon's connection pooling
+
+If you'd like to use the [connection pooling](https://neon.tech/blog/prisma-dx-improvements#providing-pooled-and-direct-connections-to-the-database) available in Neon, you will
+need to add `pgbouncer=true` to the end of the `DATABASE_URL` environment variable used in the `url` property of the `datasource` block of your Prisma schema:
+
+```env file=.env
+# Connect to Neon with PgBouncer.
+DATABASE_URL=postgres://daniel:@ep-mute-rain-952417-pooler.us-east-2.aws.neon.tech:5432/neondb?pgbouncer=true
+```
+
+If you would like to use Prisma CLI in order to perform other actions on your database (e.g. for migrations) you will need to add a `DIRECT_URL` environment variable to use in the `directUrl` property of the `datasource` block of your Prisma schema so that the CLI will use a direct connection string (without PgBouncer):
+
+```env file=.env highlight=4-5;add
+# Connect to Neon with PgBouncer.
+DATABASE_URL=postgres://daniel:@ep-mute-rain-952417-pooler.us-east-2.aws.neon.tech/neondb?pgbouncer=true
+
+# Direct connection to the database used by Prisma CLI for e.g. migrations.
+DIRECT_URL="postgres://daniel:@ep-mute-rain-952417.us-east-2.aws.neon.tech/neondb"
+```
+
+You can then update your `schema.prisma` to use the new direct URL:
+
+```prisma file=schema.prisma highlight=4;add
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+```
+
+More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields).
+
+
+
+We strongly recommend using the pooled connection string in your `DATABASE_URL` environment variable. You will gain the great developer experience of the Prisma CLI while also allowing for connections to be pooled regardless of deployment strategy. While this is not strictly necessary for every app, serverless solutions will inevitably require connection pooling.
+
+
+
+## Resolving connection timeouts
+
+A connection timeout that occurs when connecting from Prisma to Neon causes an error similar to the following:
+
+```text no-copy
+Error: P1001: Can't reach database server at `ep-white-thunder-826300.us-east-2.aws.neon.tech`:`5432`
+Please make sure your database server is running at `ep-white-thunder-826300.us-east-2.aws.neon.tech`:`5432`.
+```
+
+This error most likely means that the connection created by Prisma Client timed out before the Neon compute was activated.
+
+A Neon compute has two main states: _Active_ and _Idle_. Active means that the compute is currently running. If there is no query activity for 5 minutes, Neon places a compute into an idle state by default. Refer to Neon's docs to [learn more](https://neon.tech/docs/introduction/compute-lifecycle).
+
+When you connect to an idle compute from Prisma, Neon automatically activates it. Activation typically happens within a few seconds but added latency can result in a connection timeout. To address this issue, your can adjust your Neon connection string by adding a `connect_timeout` parameter. This parameter defines the maximum number of seconds to wait for a new connection to be opened. The default value is 5 seconds. A higher setting should provide the time required to avoid connection timeout issues. For example:
+
+```text wrap
+DATABASE_URL=postgres://daniel:@ep-mute-rain-952417.us-east-2.aws.neon.tech/neondb?connect_timeout=10
+```
+
+
+
+A `connect_timeout` setting of 0 means no timeout.
+
+
+
+Another possible cause of connection timeouts is Prisma's [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool), which has a default timeout of 10 seconds. This is typically enough time for Neon, but if you are still experiencing connection timeouts, you can try increasing this limit (in addition to the `connect_timeout` setting described above) by setting the `pool_timeout` parameter to a higher value. For example:
+
+```text wrap
+DATABASE_URL=postgres://daniel:@ep-mute-rain-952417.us-east-2.aws.neon.tech/neondb?connect_timeout=15&pool_timeout=15
+```
+
+## How to use Neon's serverless driver with Prisma (Preview)
+
+The [Neon serverless driver](https://github.com/neondatabase/serverless) is a low-latency Postgres driver for JavaScript and TypeScript that allows you to query data from serverless and edge environments over HTTP or WebSockets in place of TCP.
+
+You can use Prisma along with the Neon serverless driver using a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) . A driver adapter allows you to use a different database driver from the default Prisma provides to communicate with your database.
+
+
+
+This feature is available in Preview from Prisma versions 5.4.2 and later.
+
+
+
+To get started, enable the `driverAdapters` Preview feature flag:
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["driverAdapters"]
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+```
+
+Generate Prisma Client:
+
+```sh
+npx prisma generate
+```
+
+Install the Prisma adapter for Neon, Neon serverless driver and `ws` packages:
+
+```sh
+npm install @prisma/adapter-neon @neondatabase/serverless ws
+npm install --save-dev @types/ws
+```
+
+Update your Prisma Client instance:
+
+```ts
+import { Pool, neonConfig } from '@neondatabase/serverless'
+import { PrismaNeon } from '@prisma/adapter-neon'
+import { PrismaClient } from '@prisma/client'
+import dotenv from 'dotenv'
+import ws from 'ws'
+
+dotenv.config()
+neonConfig.webSocketConstructor = ws
+const connectionString = `${process.env.DATABASE_URL}`
+
+const pool = new Pool({ connectionString })
+const adapter = new PrismaNeon(pool)
+const prisma = new PrismaClient({ adapter })
+```
+
+You can then use Prisma Client as you normally would with full type-safety. Prisma Migrate, introspection, and Prisma Studio will continue working as before, using the connection string defined in the Prisma schema.
diff --git a/docs/200-orm/050-overview/500-databases/900-turso.mdx b/docs/200-orm/050-overview/500-databases/900-turso.mdx
new file mode 100644
index 0000000000..51c0aafe23
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/900-turso.mdx
@@ -0,0 +1,221 @@
+---
+title: 'Turso'
+metaTitle: 'Turso (Early Access)'
+metaDescription: 'Guide to Turso'
+tocDepth: 3
+---
+
+
+
+This guide discusses the concepts behind using Prisma and Turso, explains the commonalities and differences between Turso and other database providers, and leads you through the process for configuring your application to integrate with Turso.
+
+Prisma support for Turso is currently in [Early Access](/orm/more/releases#early-access). We would appreciate your feedback in this [GitHub discussion](https://github.com/prisma/prisma/discussions/21345).
+
+
+
+## What is Turso?
+
+
+
+[Turso](https://turso.tech/) is an edge-hosted, distributed database that's based on [libSQL](https://turso.tech/libsql), an open-source and open-contribution fork of [SQLite](https://sqlite.org/), enabling you to bring data closer to your application and minimize query latency. Turso can also be hosted on a remote server.
+
+
+
+Support for Turso is available in [Early Access](/orm/more/releases#early-access) from Prisma versions 5.4.2 and later.
+
+
+
+## Commonalities with other database providers
+
+libSQL is 100% compatible with SQLite. libSQL extends SQLite and adds the following features and capabilities:
+
+- Support for replication
+- Support for automated backups
+- Ability to embed Turso as part of other programs such as the Linux kernel
+- Supports user-defined functions
+- Support for asynchronous I/O
+
+> To learn more about the differences between libSQL and how it is different from SQLite, see [libSQL Manifesto](https://turso.tech/libsql-manifesto).
+
+Many aspects of using Prisma with Turso are just like using Prisma with any other relational database. You can still:
+
+- model your database with the [Prisma Schema Language](/orm/prisma-schema)
+- use Prisma's existing [`sqlite` database connector](/orm/overview/databases/sqlite) in your schema
+- use [Prisma Client](/orm/prisma-client) in your application to talk to the database server at Turso
+
+## Differences to consider
+
+There are a number of differences between Turso and SQLite to consider. You should be aware of the following when deciding to use Turso and Prisma:
+
+- **Remote and embedded SQLite databases**. libSQL uses HTTP to connect to the remote SQLite database. libSQL also supports remote database replicas and embedded replicas. Embedded replicas enable you to replicate your primary database inside your application.
+- **Making schema changes**. Since libSQL uses HTTP to connect to the remote database, this makes it incompatible with Prisma Migrate. However, you can use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to create a schema migration and then apply the changes to your database using [Turso's CLI](https://docs.turso.tech/reference/turso-cli).
+
+## How to connect and query a Turso database
+
+The subsequent section covers how you can create a Turso database, retrieve your database credentials and connect to your database.
+
+### How to provision a database and retrieve database credentials
+
+
+
+Ensure that you have the [Turso CLI](https://docs.turso.tech/reference/turso-cli) installed to manage your databases.
+
+
+
+If you don't have an existing database, you can provision a database by running the following command:
+
+```terminal
+turso db create turso-prisma-db
+```
+
+The above command will create a database in the closest region to your location.
+
+Run the following command to retrieve your database's connection string:
+
+```terminal
+turso db show turso-prisma-db
+```
+
+Next, create an authentication token that will allow you to connect to the database:
+
+```terminal
+turso db tokens create turso-prisma-db
+```
+
+Update your `.env` file with the authentication token and connection string:
+
+```text file=.env
+TURSO_AUTH_TOKEN="eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..."
+TURSO_DATABASE_URL="libsql://turso-prisma-db-user.turso.io"
+```
+
+### How to connect to a Turso database
+
+To get started, enable the `driverAdapters` Preview feature flag:
+
+```prisma highlight=3;add
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["driverAdapters"]
+}
+
+datasource db {
+ provider = "sqlite"
+ url = "file:./dev.db"
+}
+```
+
+Generate Prisma Client:
+
+```terminal
+npx prisma generate
+```
+
+Install the libSQL database client and Prisma driver adapter for libSQL packages:
+
+```terminal
+npm install @libsql/client @prisma/adapter-libsql
+```
+
+Update your Prisma Client instance:
+
+```ts
+import { PrismaClient } from '@prisma/client'
+import { PrismaLibSQL } from '@prisma/adapter-libsql'
+import { createClient } from '@libsql/client'
+
+const libsql = createClient({
+ url: `${process.env.TURSO_DATABASE_URL}`,
+ authToken: `${process.env.TURSO_AUTH_TOKEN}`,
+})
+
+const adapter = new PrismaLibSQL(libsql)
+const prisma = new PrismaClient({ adapter })
+```
+
+You can use Prisma Client as you normally would with full type-safety in your project.
+
+## How to manage schema changes
+
+Prisma Migrate and Introspection workflows are currently not supported when working with Turso. This is because Turso uses HTTP to connect to your database, which Prisma Migrate doesn't support.
+
+To update your database schema:
+
+1. Generate a migration file using `prisma migrate dev` against a local SQLite database:
+
+ ```terminal
+ npx prisma migrate dev --name init
+ ```
+
+2. Apply the migration using Turso's CLI:
+
+ ```terminal
+ turso db shell turso-prisma-db < ./prisma/migrations/20230922132717_init/migration.sql
+ ```
+
+
+
+ Replace `20230922132717_init` with the name of your migration.
+
+
+
+For subsequent migrations, repeat the above steps to apply changes to your database. This workflow does not support track the history of applied migrations to your remote database.
+
+## Embedded Turso database replicas
+
+Turso supports [embedded replicas](https://blog.turso.tech/introducing-embedded-replicas-deploy-turso-anywhere-2085aa0dc242). Turso's embedded replicas enable you to have a copy of your primary, remote database _inside_ your application. Embedded replicas behave similarly to a local SQLite database. Database queries are faster because your database is inside your application.
+
+### How embedded database replicas work
+
+When your app initially establishes a connection to your database, the primary database will fulfill the query:
+
+
+
+Turso will (1) create an embedded replica inside your application and (2) copy data from your primary database to the replica so it is locally available:
+
+
+
+The embedded replica will fulfill subsequent read queries. The libSQL client provides a [`sync()`]() method which you can invoke to ensure the embedded replica's data remains fresh.
+
+
+
+With embedded replicas, this setup guarantees a responsive application, because the data will be readily available locally and faster to access.
+
+Like a read replica setup you may be familiar with, write operations are forwarded to the primary remote database and executed before being propagated to all embedded replicas.
+
+
+
+1. Write operations propagation are forwarded to the database.
+1. Database responds to the server with the updates from 1.
+1. Write operations are propagated to the database replica.
+
+Your application's data needs will determine how often you should synchronize data between your remote database and embedded database replica. For example, you can use either middleware functions (e.g. Express and Fastify) or a cron job to synchronize the data.
+
+### How to synchronize data between your remote database and embedded replica
+
+To get started using embedded replicas with Prisma, add the `sync()` method from libSQL in your application. The example below shows how you can synchronize data using Express middleware.
+
+```ts highlight=5-8;add;
+import express from 'express'
+const app = express()
+
+// ... the rest of your application code
+app.use(async (req, res, next) => {
+ await libsql.sync()
+ next()
+})
+
+app.listen(3000, () => console.log(`Server ready at http://localhost:3000`))
+```
diff --git a/docs/200-orm/050-overview/500-databases/images/drivers/qe-query-engine-adapter.png b/docs/200-orm/050-overview/500-databases/images/drivers/qe-query-engine-adapter.png
new file mode 100644
index 0000000000..068f9c76c5
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/images/drivers/qe-query-engine-adapter.png differ
diff --git a/docs/200-orm/050-overview/500-databases/images/drivers/qe-query-execution-flow.png b/docs/200-orm/050-overview/500-databases/images/drivers/qe-query-execution-flow.png
new file mode 100644
index 0000000000..aca500b4fe
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/images/drivers/qe-query-execution-flow.png differ
diff --git a/docs/200-orm/050-overview/500-databases/images/embedded-replica-create-replica.png b/docs/200-orm/050-overview/500-databases/images/embedded-replica-create-replica.png
new file mode 100644
index 0000000000..830501d9c2
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/images/embedded-replica-create-replica.png differ
diff --git a/docs/200-orm/050-overview/500-databases/images/embedded-replica-read.png b/docs/200-orm/050-overview/500-databases/images/embedded-replica-read.png
new file mode 100644
index 0000000000..0edaebcf2e
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/images/embedded-replica-read.png differ
diff --git a/docs/200-orm/050-overview/500-databases/images/embedded-replica-remote-read.png b/docs/200-orm/050-overview/500-databases/images/embedded-replica-remote-read.png
new file mode 100644
index 0000000000..7762e8bfaa
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/images/embedded-replica-remote-read.png differ
diff --git a/docs/200-orm/050-overview/500-databases/images/embedded-replica-write-propagation.png b/docs/200-orm/050-overview/500-databases/images/embedded-replica-write-propagation.png
new file mode 100644
index 0000000000..fa36c87335
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/images/embedded-replica-write-propagation.png differ
diff --git a/docs/200-orm/050-overview/500-databases/index.mdx b/docs/200-orm/050-overview/500-databases/index.mdx
new file mode 100644
index 0000000000..81680e00f6
--- /dev/null
+++ b/docs/200-orm/050-overview/500-databases/index.mdx
@@ -0,0 +1,16 @@
+---
+title: 'Databases'
+metaTitle: 'Databases'
+metaDescription: 'Databases'
+toc: false
+---
+
+
+
+Learn about the different databases Prisma supports.
+
+
+
+## In this section
+
+
diff --git a/docs/200-orm/050-overview/500-databases/mongodb.png b/docs/200-orm/050-overview/500-databases/mongodb.png
new file mode 100644
index 0000000000..192f87b08d
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/mongodb.png differ
diff --git a/docs/200-orm/050-overview/500-databases/mysql-connection-string.png b/docs/200-orm/050-overview/500-databases/mysql-connection-string.png
new file mode 100644
index 0000000000..5ded2e0d6f
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/mysql-connection-string.png differ
diff --git a/docs/200-orm/050-overview/500-databases/postgresql-connection-string.png b/docs/200-orm/050-overview/500-databases/postgresql-connection-string.png
new file mode 100644
index 0000000000..56e7347da5
Binary files /dev/null and b/docs/200-orm/050-overview/500-databases/postgresql-connection-string.png differ
diff --git a/docs/200-orm/050-overview/index.mdx b/docs/200-orm/050-overview/index.mdx
new file mode 100644
index 0000000000..89077e1d99
--- /dev/null
+++ b/docs/200-orm/050-overview/index.mdx
@@ -0,0 +1,12 @@
+---
+title: 'Overview'
+metaTitle: 'Overview'
+metaDescription: 'Overview'
+staticLink: true
+toc: false
+---
+
+
+## In this section
+
+
diff --git a/docs/200-orm/100-prisma-schema/10-overview/02-data-sources.mdx b/docs/200-orm/100-prisma-schema/10-overview/02-data-sources.mdx
new file mode 100644
index 0000000000..7ff9a664d8
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/10-overview/02-data-sources.mdx
@@ -0,0 +1,42 @@
+---
+title: 'Data sources'
+metaTitle: 'Data sources (Reference)'
+metaDescription: 'Data sources enable Prisma to connect to your database. This page explains how to configure data sources in your Prisma schema.'
+---
+
+
+
+A data source determines how Prisma connects your database, and is represented by the [`datasource`](/orm/reference/prisma-schema-reference#datasource) block in the Prisma schema. The following data source uses the `postgresql` provider and includes a connection URL:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public"
+}
+```
+
+A Prisma schema can only have _one_ data source. However, you can:
+
+- [Programmatically override a data source `url` when creating your `PrismaClient`](/orm/reference/prisma-client-reference#programmatically-override-a-datasource-url)
+- [Specify a different URL for Prisma Migrate's shadow database if you are working with cloud-hosted development databases](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database#cloud-hosted-shadow-databases-must-be-created-manually)
+
+> **Note**: Multiple provider support was removed in 2.22.0. Please see [Deprecation of provider array notation](https://github.com/prisma/prisma/issues/3834) for more information.
+
+
+
+## Securing database connections
+
+Some data source `provider`s allow you to configure your connection with SSL/TLS, and provide parameters for the `url` to specify the location of certificates.
+
+- [Configuring an SSL connection with PostgreSQL](/orm/overview/databases/postgresql#configuring-an-ssl-connection)
+- [Configuring an SSL connection with MySQL](/orm/overview/databases/mysql#configuring-an-ssl-connection)
+- [Configure a TLS connection with Microsoft SQL Server](/orm/overview/databases/sql-server#connection-details)
+
+Prisma resolves SSL certificates relative to the `./prisma` directory. If your certificate files are located outside that directory, e.g. your project root directory, use relative paths for certificates:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public&sslmode=require&sslcert=../server-ca.pem&sslidentity=../client-identity.p12&sslpassword="
+}
+```
diff --git a/docs/200-orm/100-prisma-schema/10-overview/03-generators.mdx b/docs/200-orm/100-prisma-schema/10-overview/03-generators.mdx
new file mode 100644
index 0000000000..c7190aef04
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/10-overview/03-generators.mdx
@@ -0,0 +1,98 @@
+---
+title: 'Generators'
+metaTitle: 'Generators (Reference)'
+metaDescription: 'Generators in your Prisma schema specify what assets are generated when the `prisma generate` command is invoked. This page explains how to configure generators.'
+---
+
+
+
+A Prisma schema can have one or more generators, represented by the [`generator`](/orm/reference/prisma-schema-reference#generator) block:
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+ output = "./generated/prisma-client-js"
+}
+```
+
+A generator determines which assets are created when you run the `prisma generate` command. The main property `provider` defines which **Prisma Client (language specific)** is created - currently, only `prisma-client-js` is available. Alternatively you can define any npm package that follows our generator specification. Additionally and optionally you can define a custom output folder for the generated assets with `output`.
+
+
+
+## Prisma Client: `prisma-client-js`
+
+The generator for Prisma's JavaScript Client accepts multiple additional properties:
+
+- `previewFeatures`: [Preview features](/orm/reference/preview-features) to include
+- `binaryTargets`: Engine binary targets for `prisma-client-js` (for example, `debian-openssl-1.1.x` if you are deploying to Ubuntu 18+, or `native` if you are working locally)
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["sample-preview-feature"]
+ binaryTargets = ["linux-musl"]
+}
+```
+
+### Binary targets
+
+Prisma Client JS (`prisma-client-js`) uses several [engines](https://github.com/prisma/prisma-engines). Engines are implemented in Rust and are used by Prisma in the form of executable, platform dependent engine files. Depending on which platform you are executing your code on, you need the correct file. "Binary targets" are used to define which files should be present for the target platform(s).
+
+The correct file is particularly important when [deploying](/orm/prisma-client/deployment/deploy-prisma) your application to production, which often differs from your local development environment.
+
+#### The `native` binary target
+
+The `native` binary target is special. It doesn't map to a concrete operating system. Instead, when `native` is specified in `binaryTargets`, Prisma detects the _current_ operating system and automatically specifies the correct binary target for it.
+
+As an example, assume you're running **macOS** and you specify the following generator:
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+ binaryTargets = ["native"]
+}
+```
+
+In that case, Prisma detects your operating system and finds the right binary file for it based on the [list of supported operating systems](/orm/reference/prisma-schema-reference#binarytargets-options) .
+If you use macOS Intel x86 (`darwin`), then the binary file that was compiled for `darwin` will be selected.
+If you use macOS ARM64 (`darwin-arm64`), then the binary file that was compiled for `darwin-arm64` will be selected.
+
+> **Note**: The `native` binary target is the default. You can set it explicitly if you wish to include additional [binary targets](/orm/reference/prisma-schema-reference#binarytargets-options) for deployment to different environments.
+
+## Community generators
+
+The following is a list of community created generators. If you want to create your own generator, you can use the [`create-prisma-generator`](https://github.com/YassinEldeeb/create-prisma-generator) CLI built by our community member [Yassin Eldeep](https://github.com/YassinEldeeb).
+
+> **Note**: Community projects are not maintained or officially supported by Prisma and some features may be out of sync. Use at your own discretion. If you create a community generator, please use this naming convention: `prisma-generator-`.
+
+- [`prisma-dbml-generator`](https://notiz.dev/blog/prisma-dbml-generator): Transforms the Prisma schema into [Database Markup Language](https://www.dbml.org/home/) (DBML) which allows for an easy visual representation
+- [`prisma-docs-generator`](https://github.com/pantharshit00/prisma-docs-generator): Generates an individual API reference for Prisma Client
+- [`prisma-json-schema-generator`](https://github.com/valentinpalkovic/prisma-json-schema-generator): Transforms the Prisma schema in [JSON schema](https://json-schema.org/)
+- [`prisma-json-types-generator`](https://github.com/arthurfiorette/prisma-json-types-generator): Adds support for [Strongly Typed `Json`](https://github.com/arthurfiorette/prisma-json-types-generator#readme) fields for all databases. It goes on `prisma-client-js` output and changes the json fields to match the type you provide. Helping with code generators, intellisense and much more. All of that without affecting any runtime code.
+- [`typegraphql-prisma`](https://github.com/MichalLytek/typegraphql-prisma#readme): Generates [TypeGraphQL](https://typegraphql.com/) CRUD resolvers for Prisma models
+- [`typegraphql-prisma-nestjs`](https://github.com/EndyKaufman/typegraphql-prisma-nestjs#readme): Fork of [`typegraphql-prisma`](https://github.com/MichalLytek/typegraphql-prisma), which also generates CRUD resolvers for Prisma models but for NestJS
+- [`prisma-typegraphql-types-gen`](https://github.com/YassinEldeeb/prisma-tgql-types-gen): Generates [TypeGraphQL](https://typegraphql.com/) class types and enums from your prisma type definitions, the generated output can be edited without being overwritten by the next gen and has the ability to correct you when you mess up the types with your edits.
+- [`nexus-prisma`](https://github.com/prisma/nexus-prisma/): Allows to project Prisma models to GraphQL via [GraphQL Nexus](https://nexusjs.org/docs/)
+- [`prisma-nestjs-graphql`](https://github.com/unlight/prisma-nestjs-graphql): Generates object types, inputs, args, etc. from the Prisma schema file for usage with `@nestjs/graphql` module
+- [`prisma-appsync`](https://github.com/maoosi/prisma-appsync): Generates a full-blown GraphQL API for [AWS AppSync](https://aws.amazon.com/appsync/)
+- [`prisma-kysely`](https://github.com/valtyr/prisma-kysely): Generates type definitions for Kysely, a TypeScript SQL query builder. This can be useful to perform queries against your database from an edge runtime, or to write more complex SQL queries not possible in Prisma without dropping type safety.
+- [`prisma-generator-nestjs-dto`](https://github.com/vegardit/prisma-generator-nestjs-dto): Generates DTO and Entity classes with relation `connect` and `create` options for use with [NestJS Resources](https://docs.nestjs.com/recipes/crud-generator) and [@nestjs/swagger](https://www.npmjs.com/package/@nestjs/swagger)
+- [`prisma-erd-generator`](https://github.com/keonik/prisma-erd-generator): Generates an entity relationship diagram
+- [`prisma-class-generator`](https://github.com/kimjbstar/prisma-class-generator): Generates classes from your Prisma Schema that can be used as DTO, Swagger Response, TypeGraphQL and so on.
+- [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Creates Zod schemas from your Prisma models.
+- [`prisma-pothos-types`](https://github.com/hayes/pothos/tree/main/packages/plugin-prisma): Makes it easier to define Prisma-based object types, and helps solve n+1 queries for relations. It also has integrations for the Relay plugin to make defining nodes and connections easy and efficient.
+- [`prisma-generator-pothos-codegen`](https://github.com/Cauen/prisma-generator-pothos-codegen): Auto generate input types (for use as args) and auto generate decoupled type-safe base files makes it easy to create customizable objects, queries and mutations for [Pothos](https://pothos-graphql.dev/) from Prisma schema. Optionally generate all crud at once from the base files.
+- [`prisma-joi-generator`](https://github.com/omar-dulaimi/prisma-joi-generator): Generate full Joi schemas from your Prisma schema.
+- [`prisma-yup-generator`](https://github.com/omar-dulaimi/prisma-yup-generator): Generate full Yup schemas from your Prisma schema.
+- [`prisma-class-validator-generator`](https://github.com/omar-dulaimi/prisma-class-validator-generator): Emit TypeScript models from your Prisma schema with class validator validations ready.
+- [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Emit Zod schemas from your Prisma schema.
+- [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers.
+- [`prisma-json-server-generator`](https://github.com/omar-dulaimi/prisma-json-server-generator): Emit a JSON file that can be run with json-server.
+- [`prisma-trpc-shield-generator`](https://github.com/omar-dulaimi/prisma-trpc-shield-generator): Emit a tRPC shield from your Prisma schema.
+- [`prisma-custom-models-generator`](https://github.com/omar-dulaimi/prisma-custom-models-generator): Emit custom models from your Prisma schema, based on Prisma recommendations.
+- [`nestjs-prisma-graphql-crud-gen`](https://github.com/mk668a/nestjs-prisma-graphql-crud-gen): Generate CRUD resolvers from GraphQL schema with NestJS and Prisma.
+- [`prisma-generator-dart`](https://github.com/FredrikBorgstrom/abcx3/tree/master/libs/prisma-generator-dart): Generates Dart/Flutter class files with to- and fromJson methods.
+- [`prisma-generator-graphql-typedef`](https://github.com/mavvy22/prisma-generator-graphql-typedef): Generates graphql schema.
+- [`prisma-markdown`](https://github.com/samchon/prisma-markdown): Generates markdown document composed with ERD diagrams and their descriptions. Supports pagination of ERD diagrams through `@namespace` comment tag.
+- [`prisma-models-graph`](https://github.com/dangchinh25/prisma-models-graph): Generates a bi-directional models graph for schema without strict relationship defined in the schema, works via a custom schema annotation.
+- [`prisma-generator-fake-data`](https://github.com/luisrudge/prisma-generator-fake-data): Generates realistic-looking fake data for your Prisma models that can be used in unit/integration tests, demos, and more.
diff --git a/docs/200-orm/100-prisma-schema/10-overview/index.mdx b/docs/200-orm/100-prisma-schema/10-overview/index.mdx
new file mode 100644
index 0000000000..e70164eeb6
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/10-overview/index.mdx
@@ -0,0 +1,304 @@
+---
+title: 'Overview'
+metaTitle: 'Prisma Schema Overview'
+metaDescription: 'The Prisma schema is the main configuration file when using Prisma. It is typically called schema.prisma and contains your database connection and data model.'
+---
+
+
+
+The Prisma schema file (short: _schema file_, _Prisma schema_ or _schema_) is the main configuration file for your Prisma setup. It is typically called `schema.prisma` and consists of the following parts:
+
+- [**Data sources**](data-sources): Specify the details of the data sources Prisma should connect to (e.g. a PostgreSQL database)
+- [**Generators**](generators): Specifies what clients should be generated based on the data model (e.g. Prisma Client)
+- [**Data model definition**](/orm/prisma-schema/data-model): Specifies your application [models](/orm/prisma-schema/data-model/models#defining-models) (the shape of the data per data source) and their [relations](/orm/prisma-schema/data-model/relations)
+
+See the [Prisma schema API reference](/orm/reference/prisma-schema-reference) for detailed information about each section of the schema.
+
+Whenever a `prisma` command is invoked, the CLI typically reads some information from the schema file, e.g.:
+
+- `prisma generate`: Reads _all_ above mentioned information from the Prisma schema to generate the correct data source client code (e.g. Prisma Client).
+- `prisma migrate dev`: Reads the data sources and data model definition to create a new migration.
+
+You can also [use environment variables](#accessing-environment-variables-from-the-schema) inside the schema file to provide configuration options when a CLI command is invoked.
+
+
+
+## Example
+
+The following is an example of a Prisma schema file that specifies:
+
+- A data source (PostgreSQL or MongoDB)
+- A generator (Prisma Client)
+- A data model definition with two models (with one relation) and one `enum`
+- Several [native data type attributes](/orm/prisma-schema/data-model/models#native-types-mapping) (`@db.VarChar(255)`, `@db.ObjectId`)
+
+
+
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ email String @unique
+ name String?
+ role Role @default(USER)
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ published Boolean @default(false)
+ title String @db.VarChar(255)
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+```prisma
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+ email String @unique
+ name String?
+ role Role @default(USER)
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ published Boolean @default(false)
+ title String
+ author User? @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+## Naming
+
+The default name for the schema file is `schema.prisma`. When your schema file is named like this, the Prisma CLI will detect it automatically in the directory where you invoke the CLI command (or any of its subdirectories).
+
+If the file is named differently, you can provide the `--schema` argument to the Prisma CLI with the path to the schema file, e.g.:
+
+```
+prisma generate --schema ./database/myschema.prisma
+```
+
+## Syntax
+
+The schema file is written in Prisma Schema Language (PSL).
+
+### VS Code
+
+Syntax highlighting for PSL is available via a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) (which also lets you auto-format the contents of your Prisma schema and indicates syntax errors with red squiggly lines). Learn more about [setting up Prisma in your editor](/orm/more/development-environment/editor-setup).
+
+### GitHub
+
+PSL code snippets on GitHub can be rendered with syntax highlighting as well by using the `.prisma` file extension or annotating fenced code blocks in Markdown with `prisma`:
+
+````
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ email String @unique
+ name String?
+}
+```
+````
+
+## Prisma schema file location
+
+The Prisma CLI looks for the Prisma schema file in the following locations, in the following order:
+
+1. The location specified by the [`--schema` flag](/orm/reference/prisma-cli-reference), which is available when you `introspect`, `generate`, `migrate`, and `studio`:
+
+ ```terminal
+ prisma generate --schema=./alternative/schema.prisma
+ ```
+
+2. The location specified in the `package.json` file (version 2.7.0 and later):
+
+ ```json
+ "prisma": {
+ "schema": "db/schema.prisma"
+ }
+ ```
+
+3. Default locations:
+
+ - `./prisma/schema.prisma`
+ - `./schema.prisma`
+
+The Prisma CLI outputs the path of the schema file that will be used. The following example shows the terminal output for `prisma db pull`:
+
+```no-lines
+Environment variables loaded from .env
+|Prisma Schema loaded from prisma/schema.prisma
+
+Introspecting based on datasource defined in prisma/schema.prisma …
+
+✔ Introspected 4 models and wrote them into prisma/schema.prisma in 239ms
+
+Run prisma generate to generate Prisma Client.
+```
+
+## Accessing environment variables from the schema
+
+You can use environment variables to provide configuration options when a CLI command is invoked, or a Prisma Client query is run.
+
+Hardcoding URLs directly in your schema is possible but is discouraged because it poses a security risk. Using environment variables in the schema allows you to **keep secrets out of the schema file** which in turn **improves the portability of the schema** by allowing you to use it in different environments.
+
+Environment variables can be accessed using the `env()` function:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+```
+
+You can use the `env()` function in the following places:
+
+- A datasource url
+- Generator binary targets
+
+See [Environment variables](/orm/more/development-environment/environment-variables) for more information about how to use an `.env` file during development.
+
+## Comments
+
+There are two types of comments that are supported in the schema file:
+
+- `// comment`: This comment is for the reader's clarity and is not present in the abstract syntax tree (AST) of the schema file.
+- `/// comment`: These comments will show up in the abstract syntax tree (AST) of the schema file as descriptions to AST nodes. Tools can then use these comments to provide additional information. All comments are attached to the next available node - [free-floating comments](https://github.com/prisma/prisma/issues/3544) are not supported and are not included in the AST.
+
+Here are some different examples:
+
+```prisma
+/// This comment will get attached to the `User` node in the AST
+model User {
+ /// This comment will get attached to the `id` node in the AST
+ id Int @default(autoincrement())
+ // This comment is just for you
+ weight Float /// This comment gets attached to the `weight` node
+}
+
+// This comment is just for you. It will not
+// show up in the AST.
+
+/// This comment will get attached to the
+/// Customer node.
+model Customer {}
+```
+
+## Auto formatting
+
+Prisma supports formatting `.prisma` files automatically. There are two ways to format `.prisma` files:
+
+- Run the [`prisma format`](/orm/reference/prisma-cli-reference#format) command.
+- Install the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) and invoke the [VS Code format action](https://code.visualstudio.com/docs/editor/codebasics#_formatting) - manually or on save.
+
+There are no configuration options - [formatting rules](#formatting-rules) are fixed (similar to Golang's `gofmt` but unlike Javascript's `prettier`):
+
+### Formatting rules
+
+#### Configuration blocks are aligned by their `=` sign.
+
+```
+block _ {
+ key = "value"
+ key2 = 1
+ long_key = true
+}
+```
+
+A newline resets block alignment:
+
+```
+block _ {
+ key = "value"
+ key2 = 1
+ key10 = true
+
+ long_key = true
+ long_key_2 = true
+}
+```
+
+#### Field definitions are aligned into columns separated by 2 or more spaces
+
+```
+block _ {
+ id String @id
+ first_name LongNumeric @default
+}
+```
+
+#### Multiline field attributes are properly aligned with the rest of the field attributes
+
+```
+block _ {
+ id String @id
+ @default
+ first_name LongNumeric @default
+}
+```
+
+A newline resets formatting rules:
+
+```
+block _ {
+ id String @id
+ @default
+
+ first_name LongNumeric @default
+}
+
+```
+
+#### Block attributes are sorted to the end of the block
+
+```
+block _ {
+ key = "value"
+
+ @@attribute
+}
+```
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/10-models.mdx b/docs/200-orm/100-prisma-schema/20-data-model/10-models.mdx
new file mode 100644
index 0000000000..22b8aa92e9
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/10-models.mdx
@@ -0,0 +1,1186 @@
+---
+title: 'Models'
+metaTitle: 'Models'
+metaDescription: 'Learn about the concepts for building your data model with Prisma: Models, scalar types, enums, attributes, functions, IDs, default values and more.'
+tocDepth: 3
+---
+
+
+
+The data model definition part of the [Prisma schema](/orm/prisma-schema) defines your application models (also called **Prisma models**). Models:
+
+- Represent the **entities** of your application domain
+- Map to the **tables** (relational databases like PostgreSQL) or **collections** (MongoDB) in your database
+- Form the foundation of the **queries** available in the generated [Prisma Client API](/orm/prisma-client)
+- When used with TypeScript, Prisma Client provides generated **type definitions** for your models and any [variations](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types) of them to make database access entirely type safe.
+
+The following schema describes a blogging platform - the data model definition is highlighted:
+
+
+
+
+```prisma highlight=10-46;normal
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ role Role @default(USER)
+ posts Post[]
+ profile Profile?
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ bio String
+ user User @relation(fields: [userId], references: [id])
+ userId Int @unique
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ title String
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ categories Category[]
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ posts Post[]
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+```prisma highlight=10-45;normal
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique
+ name String?
+ role Role @default(USER)
+ posts Post[]
+ profile Profile?
+}
+
+model Profile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ bio String
+ user User @relation(fields: [userId], references: [id])
+ userId String @unique @db.ObjectId
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+ title String
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ categoryIDs String[] @db.ObjectId
+ categories Category[] @relation(fields: [categoryIDs], references: [id])
+}
+
+model Category {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ postIDs String[] @db.ObjectId
+ posts Post[] @relation(fields: [postIDs], references: [id])
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+The data model definition is made up of:
+
+- [Models](#defining-models) ([`model`](/orm/reference/prisma-schema-reference#model) primitives) that define a number of fields, including [relations between models](#relation-fields)
+- [Enums](#defining-enums) ([`enum`](/orm/reference/prisma-schema-reference#enum) primitives) (if your connector supports Enums)
+- [Attributes](#defining-attributes) and [functions](#using-functions) that change the behavior of fields and models
+
+The corresponding database looks like this:
+
+
+
+
+
+A model maps to the underlying structures of the data source.
+
+- In relational databases like PostgreSQL and MySQL, a `model` maps to a **table**
+- In MongoDB, a `model` maps to a **collection**
+
+> **Note**: In the future there might be connectors for non-relational databases and other data sources. For example, for a REST API it would map to a _resource_.
+
+
+
+The following query uses Prisma Client that's generated from this data model to create:
+
+- A `User` record
+- Two nested `Post` records
+- Three nested `Category` records
+
+
+
+
+
+```ts
+const user = await prisma.user.create({
+ data: {
+ email: 'ariadne@prisma.io',
+ name: 'Ariadne',
+ posts: {
+ create: [
+ {
+ title: 'My first day at Prisma',
+ categories: {
+ create: {
+ name: 'Office',
+ },
+ },
+ },
+ {
+ title: 'How to connect to a SQLite database',
+ categories: {
+ create: [{ name: 'Databases' }, { name: 'Tutorials' }],
+ },
+ },
+ ],
+ },
+ },
+})
+```
+
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient({})
+
+// A `main` function so that you can use async/await
+async function main() {
+ // Create user, posts, and categories
+ const user = await prisma.user.create({
+ data: {
+ email: 'ariadne@prisma.io',
+ name: 'Ariadne',
+ posts: {
+ create: [
+ {
+ title: 'My first day at Prisma',
+ categories: {
+ create: {
+ name: 'Office',
+ },
+ },
+ },
+ {
+ title: 'How to connect to a SQLite database',
+ categories: {
+ create: [{ name: 'Databases' }, { name: 'Tutorials' }],
+ },
+ },
+ ],
+ },
+ },
+ })
+
+ // Return user, and posts, and categories
+ const returnUser = await prisma.user.findUnique({
+ where: {
+ id: user.id,
+ },
+ include: {
+ posts: {
+ include: {
+ categories: true,
+ },
+ },
+ },
+ })
+
+ console.log(returnUser)
+}
+
+main()
+```
+
+
+
+
+
+Your data model reflects _your_ application domain. For example:
+
+- In an **ecommerce** application you probably have models like `Customer`, `Order`, `Item` and `Invoice`.
+- In a **social media** application you probably have models like `User`, `Post`, `Photo` and `Message`.
+
+
+
+## Introspection and migration
+
+There are two ways to define a data model:
+
+- **Write the data model manually and use Prisma Migrate**: You can write your data model manually and map it to your database using [Prisma Migrate](/orm/prisma-migrate). In this case, the data model is the single source of truth for the models of your application.
+- **Generate the data model via introspection**: When you have an existing database or prefer migrating your database schema with SQL, you generate the data model by [introspecting](/orm/prisma-schema/introspection) your database. In this case, the database schema is the single source of truth for the models of your application.
+
+## Defining models
+
+Models represent the entities of your application domain. Models are represented by [`model`](/orm/reference/prisma-schema-reference#model) blocks and define a number of [fields](/orm/reference/prisma-schema-reference#model-fields). In the example data model above, `User`, `Profile`, `Post` and `Category` are models.
+
+A blogging platform can be extended with the following models:
+
+```prisma
+model Comment {
+ // Fields
+}
+
+model Tag {
+ // Fields
+}
+```
+
+### Mapping model names to tables or collections
+
+Prisma model [naming conventions (singular form, PascalCase)](/orm/reference/prisma-schema-reference#naming-conventions) do not always match table names in the database. A common approach for naming tables/collections in databases is to use plural form and [snake_case](https://en.wikipedia.org/wiki/Snake_case) notation - for example: `comments`. When you introspect a database with a table named `comments`, the result Prisma model will look like this:
+
+```prisma
+model comments {
+ // Fields
+}
+```
+
+However, you can still adhere to the naming convention without renaming the underlying `comments` table in the database by using the [`@@map`](/orm/reference/prisma-schema-reference#map-1) attribute:
+
+```prisma
+model Comment {
+ // Fields
+
+ @@map("comments")
+}
+```
+
+With this model definition, Prisma automatically maps the `Comment` model to the `comments` table in the underlying database.
+
+> **Note**: You can also [`@map`](/orm/reference/prisma-schema-reference#map) a column name or enum value, and `@@map` an enum name.
+
+`@map` and `@@map` allow you to [tune the shape of your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names#using-map-and-map-to-rename-fields-and-models-in-the-prisma-client-api) by decoupling model and field names from table and column names in the underlying database.
+
+
+
+
+
+
+
+## Defining fields
+
+The properties of a model are called _fields_, which consist of:
+
+- A **[field name](/orm/reference/prisma-schema-reference#model-fields)**
+- A **[field type](/orm/reference/prisma-schema-reference#model-fields)**
+- Optional **[type modifiers](#type-modifiers)**
+- Optional **[attributes](#defining-attributes)**, including [native database type attributes](#native-types-mapping)
+
+A field's type determines its _structure_, and fits into one of two categories:
+
+- [Scalar types](#scalar-fields) (includes [enums](#defining-enums)) that map to columns (relational databases) or document fields (MongoDB) in the database - for example, [`String`](/orm/reference/prisma-schema-reference#string) or [`Int`](/orm/reference/prisma-schema-reference#int)
+- Model types (the field is then called [relation field](relations#relation-fields)) - for example `Post` or `Comment[]`.
+
+The following table describes `User` model's fields from the sample schema:
+
+
+
+Expand to see table
+
+| Name | Type | Scalar vs Relation | Type modifier | Attributes |
+| :-------- | :-------- | :---------------------------- | :------------ | :------------------------------------ |
+| `id` | `Int` | Scalar | - | `@id` and `@default(autoincrement())` |
+| `email` | `String` | Scalar | - | `@unique` |
+| `name` | `String` | Scalar | `?` | - |
+| `role` | `Role` | Scalar (`enum`) | - | `@default(USER)` |
+| `posts` | `Post` | Relation (Prisma-level field) | `[]` | - |
+| `profile` | `Profile` | Relation (Prisma-level field) | `?` | - |
+
+
+
+### Scalar fields
+
+The following example extends the `Comment` and `Tag` models with several scalar types. Some fields include [attributes](#defining-attributes):
+
+
+
+
+```prisma highlight=2-4,8;normal
+model Comment {
+ id Int @id @default(autoincrement())
+ title String
+ content String
+}
+
+model Tag {
+ name String @id
+}
+```
+
+
+
+
+```prisma highlight=2-4,8;normal
+model Comment {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ content String
+}
+
+model Tag {
+ name String @id @map("_id")
+}
+```
+
+
+
+
+See [complete list of scalar field types](/orm/reference/prisma-schema-reference#model-field-scalar-types) .
+
+### Relation fields
+
+A relation field's type is another model - for example, a post (`Post`) can have multiple comments (`Comment[]`):
+
+
+
+
+```prisma highlight=4,10;normal
+model Post {
+ id Int @id @default(autoincrement())
+ // Other fields
+ comments Comment[] // A post can have many comments
+}
+
+model Comment {
+ id Int
+ // Other fields
+ Post Post? @relation(fields: [postId], references: [id]) // A comment can have one post
+ postId Int?
+}
+```
+
+
+
+
+```prisma highlight=4,10;normal
+model Post {
+ id String @id @default(auto()) @map("_id") @db.Objectid
+ // Other fields
+ comments Comment[] // A post can have many comments
+}
+
+model Comment {
+ id String @id @default(auto()) @map("_id") @db.Objectid
+ // Other fields
+ Post Post? @relation(fields: [postId], references: [id]) // A comment can have one post
+ postId String? @db.ObjectId
+}
+```
+
+
+
+
+Refer to the [relations documentation](relations) for more examples and information about relationships between models.
+
+### Native types mapping
+
+Version [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and later support **native database type attributes** (type attributes) that describe the underlying database type:
+
+```prisma highlight=3;normal
+model Post {
+ id Int @id
+ title String @db.VarChar(200)
+ content String
+}
+```
+
+Type attributes are:
+
+- Specific to the underlying provider - for example, PostgreSQL uses `@db.Boolean` for `Boolean` whereas MySQL uses `@db.TinyInt(1)`
+- Written in PascalCase (for example, `VarChar` or `Text`)
+- Prefixed by `@db`, where `db` is the name of the `datasource` block in your schema
+
+Furthermore, during [Introspection](/orm/prisma-schema/introspection) type attributes are _only_ added to the schema if the underlying native type is **not the default type**. For example, if you are using the PostgreSQL provider, `String` fields where the underlying native type is `text` will not have a type attribute.
+
+See [complete list of native database type attributes per scalar type and provider](/orm/reference/prisma-schema-reference#model-field-scalar-types) .
+
+#### Benefits and workflows
+
+- Control **the exact native type** that [Prisma Migrate](/orm/prisma-migrate) creates in the database - for example, a `String` can be `@db.VarChar(200)` or `@db.Char(50)`
+- See an **enriched schema** when you introspect
+
+### Type modifiers
+
+The type of a field can be modified by appending either of two modifiers:
+
+- [`[]`](/orm/reference/prisma-schema-reference#-modifier) Make a field a list
+- [`?`](/orm/reference/prisma-schema-reference#-modifier-1) Make a field optional
+
+> **Note**: You **cannot** combine type modifiers - optional lists are not supported.
+
+#### Lists
+
+The following example includes a scalar list and a list of related models:
+
+
+
+
+```prisma highlight=4,5;normal
+model Post {
+ id Int @id @default(autoincrement())
+ // Other fields
+ comments Comment[] // A list of comments
+ keywords String[] // A scalar list
+}
+```
+
+
+
+
+```prisma highlight=4,5;normal
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ // Other fields
+ comments Comment[] // A list of comments
+ keywords String[] // A scalar list
+}
+```
+
+
+
+
+> **Note**: Scalar lists are **only** supported if the database connector supports scalar lists, either natively or at a Prisma level.
+
+#### Optional and mandatory fields
+
+
+
+
+```prisma highlight=4;normal
+model Comment {
+ id Int @id @default(autoincrement())
+ title String
+ content String?
+}
+
+model Tag {
+ name String @id
+}
+```
+
+
+
+
+```prisma highlight=4;normal
+model Comment {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ content String?
+}
+
+model Tag {
+ name String @id @map("_id")
+}
+```
+
+
+
+
+When **not** annotating a field with the `?` type modifier, the field will be _required_ on every record of the model. This has effects on two levels:
+
+- **Databases**
+ - **Relational databases**: Required fields are represented via `NOT NULL` constraints in the underlying database.
+ - **MongoDB**: Required fields are not a concept on a MongoDB database level.
+- **Prisma Client**: Prisma Client's generated [TypeScript types](#type-definitions) that represent the models in your application code will also define these fields as required to ensure they always carry values at runtime.
+
+> **Note**: The default value of an optional field is `null`.
+
+### Unsupported types
+
+When you introspect a relational database, unsupported data types are added as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) :
+
+```prisma
+location Unsupported("POLYGON")?
+```
+
+The `Unsupported` type allows you to define fields in the Prisma schema for database types that are not yet supported by Prisma. For example, MySQL's `POLYGON` type is not currently supported by Prisma, but can now be added to the Prisma schema using the `Unsupported("POLYGON")` type.
+
+Fields of type `Unsupported` are not available in the generated Prisma Client API, but you can still use Prisma's [raw database access](/orm/prisma-client/queries/raw-database-access/raw-queries) feature to query these fields.
+
+> **Note**: If a model has **mandatory `Unsupported` fields**, the generated client will not include `create` or `update` methods for that model.
+
+> **Note**: The MongoDB connector does not support nor require the `Unsupported` type because it supports all scalar types.
+
+## Defining attributes
+
+Attributes modify the behavior of fields or model blocks. The following example includes three field attributes ([`@id`](/orm/reference/prisma-schema-reference#id) , [`@default`](/orm/reference/prisma-schema-reference#default) , and [`@unique`](/orm/reference/prisma-schema-reference#unique) ) and one block attribute ([`@@unique`](/orm/reference/prisma-schema-reference#unique-1) ):
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ firstName String
+ lastName String
+ email String @unique
+ isAdmin Boolean @default(false)
+
+ @@unique([firstName, lastName])
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ firstName String
+ lastName String
+ email String @unique
+ isAdmin Boolean @default(false)
+
+ @@unique([firstName, lastName])
+}
+```
+
+
+
+
+Some attributes accept [arguments](/orm/reference/prisma-schema-reference#attribute-argument-types) - for example, `@default` accepts `true` or `false`:
+
+```prisma
+isAdmin Boolean @default(false) // short form of @default(value: false)
+```
+
+See [complete list of field and block attributes](/orm/reference/prisma-schema-reference#attributes)
+
+### Defining an ID field
+
+An ID uniquely identifies individual records of a model. A model can only have _one_ ID:
+
+- In **relational databases**, the ID can be a single field or based on multiple fields. If a model does not have an `@id` or an `@@id`, you must define a mandatory `@unique` field or `@@unique` block instead.
+- In **MongoDB**, an ID must be a single field that defines an `@id` attribute and a `@map("_id")` attribute.
+
+#### Defining IDs in relational databases
+
+In relational databases, an ID can be defined by a single field using the [`@id`](/orm/reference/prisma-schema-reference#id) attribute, or multiple fields using the [`@@id`](/orm/reference/prisma-schema-reference#id-1) attribute.
+
+##### Single field IDs
+
+In the following example, the `User` ID is represented by the `id` integer field:
+
+```prisma highlight=2;normal
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ role Role @default(USER)
+ posts Post[]
+ profile Profile?
+}
+```
+
+##### Composite IDs
+
+In the following example, the `User` ID is represented by a combination of the `firstName` and `lastName` fields:
+
+```prisma highlight=7;normal
+model User {
+ firstName String
+ lastName String
+ email String @unique
+ isAdmin Boolean @default(false)
+
+ @@id([firstName, lastName])
+}
+```
+
+By default, the name of this field in Prisma Client queries will be `firstName_lastName`.
+
+You can also provide your own name for the composite ID using the [`@@id`](/orm/reference/prisma-schema-reference#id-1) attribute's `name` field:
+
+```prisma highlight=7;normal
+model User {
+ firstName String
+ lastName String
+ email String @unique
+ isAdmin Boolean @default(false)
+
+ @@id(name: "fullName", fields: [firstName, lastName])
+}
+```
+
+The `firstName_lastName` field will now be named `fullName` instead.
+
+
+
+Refer to the documentation on [working with composite IDs](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints) to learn how to interact with a composite ID in Prisma Client.
+
+
+
+##### `@unique` fields as unique identifiers
+
+In the following example, users are uniquely identified by a `@unique` field. Because the `email` field functions as a unique identifier for the model (which is required by Prisma), it must be mandatory:
+
+```prisma highlight=2;normal
+model User {
+ email String @unique
+ name String?
+ role Role @default(USER)
+ posts Post[]
+ profile Profile?
+}
+```
+
+
+
+**Constraint names in relational databases**
+You can optionally define a [custom primary key constraint name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database.
+
+
+
+#### Defining IDs in MongoDB
+
+The MongoDB connector has [specific rules for defining an ID field](/orm/reference/prisma-schema-reference#mongodb) that differs from relational databases. An ID must be defined by a single field using the [`@id`](/orm/reference/prisma-schema-reference#id) attribute and must include `@map("_id")`.
+
+In the following example, the `User` ID is represented by the `id` string field that accepts an auto-generated `ObjectId`:
+
+```prisma highlight=2;normal
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique
+ name String?
+ role Role @default(USER)
+ posts Post[]
+ profile Profile?
+}
+```
+
+In the following example, the `User` ID is represented by the `id` string field that accepts something other than an `ObjectId` - for example, a unique username:
+
+```prisma highlight=2;normal
+model User {
+ id String @id @map("_id")
+ email String @unique
+ name String?
+ role Role @default(USER)
+ posts Post[]
+ profile Profile?
+}
+```
+
+
+
+**MongoDB does not support `@@id`**
+MongoDB does not support composite IDs, which means you cannot identify a model with a `@@id` block.
+
+
+
+### Defining a default value
+
+You can define default values for scalar fields of your models using the [`@default`](/orm/reference/prisma-schema-reference#default) attribute:
+
+
+
+
+```prisma highlight=3,5;normal
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ title String
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ categories Category[] @relation(references: [id])
+}
+```
+
+
+
+
+```prisma highlight=3,5;normal
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+ title String
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ categories Category[] @relation(references: [id])
+}
+```
+
+
+
+
+`@default` attributes either:
+
+- Represent `DEFAULT` values in the underlying database (relational databases only) _or_
+- Use a Prisma-level function. For example, `cuid()` and `uuid()` are provided by Prisma's [query engine](/orm/more/under-the-hood/engines) for all connectors.
+
+Default values can be:
+
+- Static values that correspond to the field type, such as `5` (`Int`), `Hello` (`String`), or `false` (`Boolean`)
+- [Lists](/orm/reference/prisma-schema-reference#-modifier) of static values, such as `[5, 6, 8]` (`Int[]`) or `["Hello", "Goodbye"]` (`String`[]). These are available in versions `4.0.0` and later, when using databases where Prisma supports them (PostgreSQL, CockroachDB and MongoDB)
+- [Functions](#using-functions), such as [`now()`](/orm/reference/prisma-schema-reference#now) or [`uuid()`](/orm/reference/prisma-schema-reference#uuid)
+
+
+
+Refer to the [attribute function reference documentation](/orm/reference/prisma-schema-reference#attribute-functions) for information about connector support for functions.
+
+
+
+### Defining a unique field
+
+You can add unique attributes to your models to be able to uniquely identify individual records of that model. Unique attributes can be defined on a single field using [`@unique`](/orm/reference/prisma-schema-reference#unique) attribute, or on multiple fields (also called composite or compound unique constraints) using the [`@@unique`](/orm/reference/prisma-schema-reference#unique-1) attribute.
+
+In the following example, the value of the `email` field must be unique:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique
+ name String?
+}
+```
+
+
+
+
+In the following example, a combination of `authorId` and `title` must be unique:
+
+
+
+
+```prisma highlight=10;normal
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ title String
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ categories Category[] @relation(references: [id])
+
+ @@unique([authorId, title])
+}
+```
+
+
+
+
+```prisma highlight=10;normal
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+ title String
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ categories Category[] @relation(references: [id])
+
+ @@unique([authorId, title])
+}
+```
+
+
+
+
+
+
+**Constraint names in relational databases**
+You can optionally define a [custom unique constraint name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database.
+
+
+
+By default, the name of this field in Prisma Client queries will be `authorId_title`.
+
+You can also provide your own name for the composite unique constraint using the [`@@unique`](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) attribute's `name` field:
+
+```prisma highlight=10;normal
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+ title String
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ categories Category[] @relation(references: [id])
+
+ @@unique(name: "authorTitle", [authorId, title])
+}
+```
+
+The `authorId_title` field will now be named `authorTitle` instead.
+
+
+
+Refer to the documentation on [working with composite unique identifiers](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints) to learn how to interact with a composite unique constraints in Prisma Client.
+
+
+
+#### Composite type unique constraints
+
+When using the MongoDB provider in version `3.12.0` and later, you can define a unique constraint on a field of a [composite type](#defining-composite-types) using the syntax `@@unique([compositeType.field])`. As with other fields, composite type fields can be used as part of a multi-column unique constraint.
+
+The following example defines a multi-column unique constraint based on the `email` field of the `User` model and the `number` field of the `Address` composite type which is used in `User.address`:
+
+```prisma file=schema.prisma
+type Address {
+ street String
+ number Int
+}
+
+model User {
+ id Int @id
+ email String
+ address Address
+
+ @@unique([email, address.number])
+}
+```
+
+This notation can be chained if there is more than one nested composite type:
+
+```prisma file=schema.prisma
+type City {
+ name String
+}
+
+type Address {
+ number Int
+ city City
+}
+
+model User {
+ id Int @id
+ address Address[]
+
+ @@unique([address.city.name])
+}
+```
+
+### Defining an index
+
+You can define indexes on one or multiple fields of your models via the [`@@index`](/orm/reference/prisma-schema-reference#index) on a model. The following example defines a multi-column index based on the `title` and `content` field:
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String?
+
+ @@index([title, content])
+}
+```
+
+
+
+**Index names in relational databases**
+You can optionally define a [custom index name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database.
+
+
+
+#### Defining composite type indexes
+
+When using the MongoDB provider in version `3.12.0` and later, you can define an index on a field of a [composite type](#defining-composite-types) using the syntax `@@index([compositeType.field])`. As with other fields, composite type fields can be used as part of a multi-column index.
+
+The following example defines a multi-column index based on the `email` field of the `User` model and the `number` field of the `Address` composite type:
+
+```prisma file=schema.prisma
+type Address {
+ street String
+ number Int
+}
+
+model User {
+ id Int @id
+ email String
+ address Address
+
+ @@index([email, address.number])
+}
+```
+
+This notation can be chained if there is more than one nested composite type:
+
+```prisma file=schema.prisma
+type City {
+ name String
+}
+
+type Address {
+ number Int
+ city City
+}
+
+model User {
+ id Int @id
+ address Address[]
+
+ @@index([address.city.name])
+}
+```
+
+## Defining enums
+
+You can define enums in your data model [if enums are supported for your database connector](/orm/reference/database-features#misc), either natively or at Prisma level.
+
+Enums are considered [scalar](#scalar-fields) types in the Prisma data model. They're therefore [by default](/orm/prisma-client/queries/select-fields#return-the-default-selection-set) included as return values in [Prisma Client queries](/orm/prisma-client/queries/crud).
+
+Enums are defined via the [`enum`](/orm/reference/prisma-schema-reference#enum) block. For example, a `User` has a `Role`:
+
+
+
+
+```prisma highlight=5,8-11;normal
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ role Role @default(USER)
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+```prisma highlight=5,8-11;normal
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique
+ name String?
+ role Role @default(USER)
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+## Defining composite types
+
+
+
+Composite types were added in version `3.10.0` under the `mongodb` Preview feature flag and are in General Availability since version `3.12.0`.
+
+
+
+
+
+Composite types are currently only available on MongoDB.
+
+
+
+Composite types (known as [embedded documents](https://docs.mongodb.com/manual/core/data-model-design/#std-label-data-modeling-embedding) in MongoDB) provide support for embedding records inside other records, by allowing you to define new object types. Composite types are structured and typed in a similar way to [models](#defining-models).
+
+To define a composite type, use the `type` block. As an example, take the following schema:
+
+```prisma file=schema.prisma
+model Product {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ photos Photo[]
+}
+
+type Photo {
+ height Int
+ width Int
+ url String
+}
+```
+
+In this case, the `Product` model has a list of `Photo` composite types stored in `photos`.
+
+### Considerations when using composite types
+
+Composite types only support a limited set of [attributes](/orm/reference/prisma-schema-reference#attributes). The following attributes are supported:
+
+- `@default`
+- `@map`
+- [Native types](/orm/reference/prisma-schema-reference#model-field-scalar-types), such as `@db.ObjectId`
+
+The following attributes are not supported inside composite types:
+
+- `@unique`
+- `@id`
+- `@relation`
+- `@ignore`
+- `@updatedAt`
+
+However, unique constraints can still be defined by using the `@@unique` attribute on the level of the model that uses the composite type. For more details, see [Composite type unique constraints](#composite-type-unique-constraints).
+
+Indexes can be defined by using the `@@index` attribute on the level of the model that uses the composite type. For more details, see [Composite type indexes](#defining-composite-type-indexes).
+
+## Using functions
+
+The Prisma schema supports a number of [functions](/orm/reference/prisma-schema-reference#attribute-functions) . These can be used to specify [default values](/orm/reference/prisma-schema-reference#default) on fields of a model.
+
+For example, the default value of `createdAt` is [`now()`](/orm/reference/prisma-schema-reference#now) :
+
+
+
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+}
+```
+
+
+
+
+```prisma
+model Post {
+ id String @default(auto()) @map("_id") @db.ObjectId
+ createdAt DateTime @default(now())
+}
+```
+
+
+
+
+[`cuid()`](/orm/reference/prisma-schema-reference#cuid) and [`uuid()`](/orm/reference/prisma-schema-reference#uuid) are implemented by Prisma and therefore are not "visible" in the underlying database schema. You can still use them when using [introspection](/orm/prisma-schema/introspection) by [manually changing your Prisma schema](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) and [generating Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client), in that case the values will be generated by Prisma's [query engine](/orm/more/under-the-hood/engines)
+
+Support for [`autoincrement()`](/orm/reference/prisma-schema-reference#autoincrement) , [`now()`](/orm/reference/prisma-schema-reference#now) and [`dbgenerated()`](/orm/reference/prisma-schema-reference#dbgenerated) differ between databases.
+
+**Relational database connectors** implement `autoincrement()`, `dbgenerated()`, and `now()` at database level. The **MongoDB connector** does not support `autoincrement()` or `dbgenerated()`, and `now()` is implemented at Prisma level. The [`auto()`](/orm/reference/prisma-schema-reference#auto) function is used to generate an `ObjectId`.
+
+## Relations
+
+Refer to the [relations documentation](relations) for more examples and information about relationships between models.
+
+## Models in Prisma Client
+
+### Queries (CRUD)
+
+Every model in the data model definition will result in a number of CRUD queries in the generated [Prisma Client API](/orm/prisma-client):
+
+- [`findMany`](/orm/reference/prisma-client-reference#findmany)
+- [`findFirst`](/orm/reference/prisma-client-reference#findfirst)
+- [`findFirstOrThrow`](/orm/reference/prisma-client-reference#findfirstorthrow)
+- [`findUnique`](/orm/reference/prisma-client-reference#findunique)
+- [`findUniqueOrThrow`](/orm/reference/prisma-client-reference#finduniqueorthrow)
+- [`create`](/orm/reference/prisma-client-reference#create)
+- [`update`](/orm/reference/prisma-client-reference#update)
+- [`upsert`](/orm/reference/prisma-client-reference#upsert)
+- [`delete`](/orm/reference/prisma-client-reference#delete)
+- [`createMany`](/orm/reference/prisma-client-reference#createmany)
+- [`updateMany`](/orm/reference/prisma-client-reference#updatemany)
+- [`deleteMany`](/orm/reference/prisma-client-reference#deletemany)
+
+The operations are accessible via a generated property on the Prisma Client instance. By default the name of the property is the lowercase form of the model name, e.g. `user` for a `User` model or `post` for a `Post` model.
+
+Here is an example illustrating the use of a `user` property from the Prisma Client API:
+
+```js
+const newUser = await prisma.user.create({
+ data: {
+ name: 'Alice',
+ },
+})
+const allUsers = await prisma.user.findMany()
+```
+
+### Type definitions
+
+Prisma Client also generates **type definitions** that reflect your model structures. These are part of the generated [`@prisma/client`](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package) node module.
+
+When using TypeScript, these type definitions ensure that all your database queries are entirely type safe and validated at compile-time (even partial queries using [`select`](/orm/reference/prisma-client-reference#select) or [`include`](/orm/reference/prisma-client-reference#include) ).
+
+Even when using plain JavaScript, the type definitions are still included in the `@prisma/client` node module, enabling features like [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense)/autocompletion in your editor.
+
+> **Note**: The actual types are stored in the `.prisma/client` folder. `@prisma/client/index.d.ts` exports the contents of this folder.
+
+For example, the type definition for the `User` model from above would look as follows:
+
+```ts
+export type User = {
+ id: number
+ email: string
+ name: string | null
+ role: string
+}
+```
+
+Note that the relation fields `posts` and `profile` are not included in the type definition by default. However, if you need variations of the `User` type you can still define them using some of [Prisma Client's generated helper types](/orm/prisma-client/setup-and-configuration/generating-prisma-client) (in this case, these helper types would be called `UserGetIncludePayload` and `UserGetSelectPayload`).
+
+## Limitations
+
+### Records must be uniquely identifiable
+
+Prisma currently only supports models that have at least one unique field or combination of fields. In practice, this means that every Prisma model must have either at least one of the following attributes:
+
+- `@id` or `@@id` for a single- or multi-field primary key constraint (max one per model)
+- `@unique` or `@@unique` for a single- or multi-field unique constraint
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/100-one-to-one-relations.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/100-one-to-one-relations.mdx
new file mode 100644
index 0000000000..4d1fe55b19
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/100-one-to-one-relations.mdx
@@ -0,0 +1,306 @@
+---
+title: One-to-one relations
+metaDescription: How to define and work with one-to-one relations in Prisma.
+tocDepth: 3
+---
+
+
+
+This page introduces one-to-one relations and explains how to use them in your Prisma schema.
+
+
+
+## Overview
+
+One-to-one (1-1) relations refer to relations where at most **one** record can be connected on both sides of the relation. In the example below, there is a one-to-one relation between `User` and `Profile`:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ profile Profile?
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userId], references: [id])
+ userId Int @unique // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ profile Profile?
+}
+
+model Profile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ user User @relation(fields: [userId], references: [id])
+ userId String @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+The `userId` relation scalar is a direct representation of the foreign key in the underlying database. This one-to-one relation expresses the following:
+
+- "a user can have zero profiles or one profile" (because the `profile` field is [optional](/orm/prisma-schema/data-model/models#type-modifiers) on `User`)
+- "a profile must always be connected to one user"
+
+In the previous example, the `user` relation field of the `Profile` model references the `id` field of the `User` model. You can also reference a different field. In this case, you need to mark the field with the `@unique` attribute, to guarantee that there is only a single `User` connected to each `Profile`. In the following example, the `user` field references an `email` field in the `User` model, which is marked with the `@unique` attribute:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique // <-- add unique attribute
+ profile Profile?
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userEmail], references: [email])
+ userEmail String @unique // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique // <-- add unique attribute
+ profile Profile?
+}
+
+model Profile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ user User @relation(fields: [userEmail], references: [email])
+ userEmail String @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+
+
+In MySQL, you can create a foreign key with only an index on the referenced side, and not a unique constraint. In Prisma versions 4.0.0 and later, if you introspect a relation of this type it will trigger a validation error. To fix this, you will need to add a `@unique` constraint to the referenced field.
+
+
+
+## Multi-field relations in relational databases
+
+In **relational databases only**, you can also use [multi-field IDs](/orm/reference/prisma-schema-reference#id-1) to define a 1-1 relation:
+
+```prisma
+model User {
+ firstName String
+ lastName String
+ profile Profile?
+
+ @@id([firstName, lastName])
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userFirstName, userLastName], references: [firstName, lastName])
+ userFirstName String // relation scalar field (used in the `@relation` attribute above)
+ userLastName String // relation scalar field (used in the `@relation` attribute above)
+
+ @@unique([userFirstName, userLastName])
+}
+```
+
+## 1-1 relations in the database
+
+### Relational databases
+
+The following example demonstrates how to create a 1-1 relation in SQL:
+
+```sql
+CREATE TABLE "User" (
+ id SERIAL PRIMARY KEY
+);
+CREATE TABLE "Profile" (
+ id SERIAL PRIMARY KEY,
+ "userId" INTEGER NOT NULL UNIQUE,
+ FOREIGN KEY ("userId") REFERENCES "User"(id)
+);
+```
+
+Notice that there is a `UNIQUE` constraint on the foreign key `userId`. If this `UNIQUE` constraint was missing, the relation would be considered a [1-n relation](one-to-many-relations).
+
+The following example demonstrates how to create a 1-1 relation in SQL using a composite key (`firstName` and `lastName`):
+
+```sql
+CREATE TABLE "User" (
+ firstName TEXT,
+ lastName TEXT,
+ PRIMARY KEY ("firstName","lastName")
+);
+CREATE TABLE "Profile" (
+ id SERIAL PRIMARY KEY,
+ "userFirstName" TEXT NOT NULL,
+ "userLastName" TEXT NOT NULL,
+ UNIQUE ("userFirstName", "userLastName")
+ FOREIGN KEY ("userFirstName", "userLastName") REFERENCES "User"("firstName", "lastName")
+);
+```
+
+### MongoDB
+
+For MongoDB, Prisma currently uses a [normalized data model design](https://docs.mongodb.com/manual/core/data-model-design/), which means that documents reference each other by ID in a similar way to relational databases.
+
+The following MongoDB document represents a `User`:
+
+```json
+{ "_id": { "$oid": "60d58e130011041800d209e1" }, "name": "Bob" }
+```
+
+The following MongoDB document represents a `Profile` - notice the `userId` field, which references the `User` document's `$oid`:
+
+```json
+{
+ "_id": { "$oid": "60d58e140011041800d209e2" },
+ "bio": "I'm Bob, and I like drawing.",
+ "userId": { "$oid": "60d58e130011041800d209e1" }
+}
+```
+
+## Required and optional 1-1 relation fields
+
+In a one-to-one relation, the side of the relation _without_ a relation scalar (the field representing the foreign key in the database) _must_ be optional:
+
+```prisma highlight=3;normal
+model User {
+ id Int @id @default(autoincrement())
+ profile Profile? // No relation scalar - must be optional
+}
+```
+
+This restriction was introduced in 2.12.0.
+
+However, you can choose if the side of the relation _with_ a relation scalar should be optional or mandatory.
+
+### Mandatory 1-1 relation
+
+In the following example, `profile` and `profileId` are mandatory. This means that you cannot create a `User` without connecting or creating a `Profile`:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ profile Profile @relation(fields: [profileId], references: [id]) // references `id` of `Profile`
+ profileId Int @unique // relation scalar field (used in the `@relation` attribute above)
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user User?
+}
+```
+
+### Optional 1-1 relation
+
+In the following example, `profile` and `profileId` are optional. This means that you can create a user without connecting or creating a `Profile`:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ profile Profile? @relation(fields: [profileId], references: [id]) // references `id` of `Profile`
+ profileId Int? @unique // relation scalar field (used in the `@relation` attribute above)
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user User?
+}
+```
+
+## Choosing which side should store the foreign key in a 1-1 relation
+
+In **1-1 relations**, you can decide yourself which side of the relation you want to annotate with the `@relation` attribute (and therefore holds the foreign key).
+
+In the following example, the relation field on the `Profile` model is annotated with the `@relation` attribute. `userId` is a direct representation of the foreign key in the underlying database:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ profile Profile?
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userId], references: [id])
+ userId Int @unique // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ profile Profile?
+}
+
+model Profile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ user User @relation(fields: [userId], references: [id])
+ userId String @unique @db.ObjectId
+}
+```
+
+
+
+
+You can also annotate the other side of the relation with the `@relation` attribute. The following example annotates the relation field on the `User` model. `profileId` is a direct representation of the foreign key in the underlying database:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ profile Profile? @relation(fields: [profileId], references: [id])
+ profileId Int? @unique // relation scalar field (used in the `@relation` attribute above)
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user User?
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ profile Profile? @relation(fields: [profileId], references: [id])
+ profileId String? @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
+}
+
+model Profile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ user User?
+}
+```
+
+
+
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/200-one-to-many-relations.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/200-one-to-many-relations.mdx
new file mode 100644
index 0000000000..7c5fea1548
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/200-one-to-many-relations.mdx
@@ -0,0 +1,280 @@
+---
+title: One-to-many relations
+metaDescription: How to define and work with one-to-many relations in Prisma.
+tocDepth: 3
+---
+
+
+
+This page introduces one-to-many relations and explains how to use them in your Prisma schema.
+
+
+
+## Overview
+
+One-to-many (1-n) relations refer to relations where one record on one side of the relation can be connected to zero or more records on the other side. In the following example, there is one one-to-many relation between the `User` and `Post` models:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+}
+```
+
+
+
+
+> **Note** The `posts` field does not "manifest" in the underlying database schema. On the other side of the relation, the [annotated relation field](/orm/prisma-schema/data-model/relations#relation-fields) `author` and its relation scalar `authorId` represent the side of the relation that stores the foreign key in the underlying database.
+
+This one-to-many relation expresses the following:
+
+- "a user can have zero or more posts"
+- "a post must always have an author"
+
+In the previous example, the `author` relation field of the `Post` model references the `id` field of the `User` model. You can also reference a different field. In this case, you need to mark the field with the `@unique` attribute, to guarantee that there is only a single `User` connected to each `Post`. In the following example, the `author` field references an `email` field in the `User` model, which is marked with the `@unique` attribute:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique // <-- add unique attribute
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ authorEmail String
+ author User @relation(fields: [authorEmail], references: [email])
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique // <-- add unique attribute
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ authorEmail String
+ author User @relation(fields: [authorEmail], references: [email])
+}
+```
+
+
+
+
+
+
+In MySQL, you can create a foreign key with only an index on the referenced side, and not a unique constraint. In Prisma versions 4.0.0 and later, if you introspect a relation of this type it will trigger a validation error. To fix this, you will need to add a `@unique` constraint to the referenced field.
+
+
+
+## Multi-field relations in relational databases
+
+In **relational databases only**, you can also define this relation using [multi-field IDs](/orm/reference/prisma-schema-reference#id-1)/composite key:
+
+```prisma
+model User {
+ firstName String
+ lastName String
+ post Post[]
+
+ @@id([firstName, lastName])
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ author User @relation(fields: [authorFirstName, authorLastName], references: [firstName, lastName])
+ authorFirstName String // relation scalar field (used in the `@relation` attribute above)
+ authorLastName String // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+## 1-n relations in the database
+
+### Relational databases
+
+The following example demonstrates how to create a 1-n relation in SQL:
+
+```sql
+CREATE TABLE "User" (
+ id SERIAL PRIMARY KEY
+);
+CREATE TABLE "Post" (
+ id SERIAL PRIMARY KEY,
+ "authorId" integer NOT NULL,
+ FOREIGN KEY ("authorId") REFERENCES "User"(id)
+);
+```
+
+Since there's no `UNIQUE` constraint on the `authorId` column (the foreign key), you can create **multiple `Post` records that point to the same `User` record**. This makes the relation a one-to-many rather than a one-to-one.
+
+The following example demonstrates how to create a 1-n relation in SQL using a composite key (`firstName` and `lastName`):
+
+```sql
+CREATE TABLE "User" (
+ firstName TEXT,
+ lastName TEXT,
+ PRIMARY KEY ("firstName","lastName")
+);
+CREATE TABLE "Post" (
+ id SERIAL PRIMARY KEY,
+ "authorFirstName" TEXT NOT NULL,
+ "authorLastName" TEXT NOT NULL,
+ FOREIGN KEY ("authorFirstName", "authorLastName") REFERENCES "User"("firstName", "lastName")
+);
+```
+
+#### Comparing one-to-one and one-to-many relations
+
+In relational databases, the main difference between a 1-1 and a 1-n-relation is that in a 1-1-relation the foreign key must have a `UNIQUE` constraint defined on it.
+
+### MongoDB
+
+For MongoDB, Prisma currently uses a [normalized data model design](https://docs.mongodb.com/manual/core/data-model-design/), which means that documents reference each other by ID in a similar way to relational databases.
+
+The following MongoDB document represents a `User`:
+
+```json
+{ "_id": { "$oid": "60d5922d00581b8f0062e3a8" }, "name": "Ella" }
+```
+
+Each of the following `Post` MongoDB documents has an `authorId` field which references the same user:
+
+```json
+[
+ {
+ "_id": { "$oid": "60d5922e00581b8f0062e3a9" },
+ "title": "How to make sushi",
+ "authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
+ },
+ {
+ "_id": { "$oid": "60d5922e00581b8f0062e3aa" },
+ "title": "How to re-install Windows",
+ "authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
+ }
+]
+```
+
+#### Comparing one-to-one and one-to-many relations
+
+In MongoDB, the only difference between a 1-1 and a 1-n is the number of documents referencing another document in the database - there are no constraints.
+
+## Required and optional relation fields in one-to-many relations
+
+A 1-n-relation always has two relation fields:
+
+- a [list](/orm/prisma-schema/data-model/models#type-modifiers) relation field which is _not_ annotated with `@relation`
+- the [annotated relation field](/orm/prisma-schema/data-model/relations#annotated-relation-fields) (including its relation scalar)
+
+The annotated relation field and relation scalar of a 1-n relation can either _both_ be optional, or _both_ be mandatory. On the other side of the relation, the list is **always mandatory**.
+
+### Optional one-to-many relation
+
+In the following example, you can create a `Post` without assigning a `User`:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ author User? @relation(fields: [authorId], references: [id])
+ authorId String? @db.ObjectId
+}
+```
+
+
+
+
+### Mandatory one-to-many relation
+
+In the following example, you must assign a `User` when you create a `Post`:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+}
+```
+
+
+
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/300-many-to-many-relations.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/300-many-to-many-relations.mdx
new file mode 100644
index 0000000000..5c8761f826
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/300-many-to-many-relations.mdx
@@ -0,0 +1,549 @@
+---
+title: Many-to-many relations
+metaDescription: How to define and work with many-to-many relations in Prisma.
+tocDepth: 3
+---
+
+
+
+Many-to-many (m-n) relations refer to relations where zero or more records on one side of the relation can be connected to zero or more records on the other side.
+
+Prisma schema syntax and the implementation in the underlying database differs between [relational databases](#relational-databases) and [MongoDB](#mongodb).
+
+
+
+## Relational databases
+
+In relational databases, m-n-relations are typically modelled via [relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables). m-n-relations can be either [explicit](#explicit-many-to-many-relations) or [implicit](#implicit-many-to-many-relations) in the Prisma schema. We recommend using [implicit](#implicit-many-to-many-relations) m-n-relations if you do not need to store any additional meta-data in the relation table itself. You can always migrate to an [explicit](#explicit-many-to-many-relations) m-n-relation later if needed.
+
+### Explicit many-to-many relations
+
+In an explicit m-n relation, the **relation table is represented as a model in the Prisma schema** and can be used in queries. Explicit m-n relations define three models:
+
+- Two models with m-n relation, such as `Category` and `Post`.
+- One model that represents the [relation table](#relation-tables), such as `CategoriesOnPosts` (also sometimes called _JOIN_, _link_ or _pivot_ table) in the underlying database. The fields of a relation table model are both annotated relation fields (`post` and `category`) with a corresponding relation scalar field (`postId` and `categoryId`).
+
+The relation table `CategoriesOnPosts` connects related `Post` and `Category` records. In this example, the model representing the relation table also **defines additional fields** that describe the `Post`/`Category` relationship - who assigned the category (`assignedBy`), and when the category was assigned (`assignedAt`):
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ categories CategoriesOnPosts[]
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ posts CategoriesOnPosts[]
+}
+
+model CategoriesOnPosts {
+ post Post @relation(fields: [postId], references: [id])
+ postId Int // relation scalar field (used in the `@relation` attribute above)
+ category Category @relation(fields: [categoryId], references: [id])
+ categoryId Int // relation scalar field (used in the `@relation` attribute above)
+ assignedAt DateTime @default(now())
+ assignedBy String
+
+ @@id([postId, categoryId])
+}
+```
+
+The underlying SQL looks like this:
+
+```sql
+CREATE TABLE "Post" (
+ "id" SERIAL NOT NULL,
+ "title" TEXT NOT NULL,
+
+ CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
+);
+
+CREATE TABLE "Category" (
+ "id" SERIAL NOT NULL,
+ "name" TEXT NOT NULL,
+
+ CONSTRAINT "Category_pkey" PRIMARY KEY ("id")
+);
+
+
+-- Relation table + indexes --
+
+CREATE TABLE "CategoriesOnPosts" (
+ "postId" INTEGER NOT NULL,
+ "categoryId" INTEGER NOT NULL,
+ "assignedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+ CONSTRAINT "CategoriesOnPosts_pkey" PRIMARY KEY ("postId","categoryId")
+);
+
+ALTER TABLE "CategoriesOnPosts" ADD CONSTRAINT "CategoriesOnPosts_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+ALTER TABLE "CategoriesOnPosts" ADD CONSTRAINT "CategoriesOnPosts_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "Category"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+```
+
+Note that the same rules as for [1-n relations](one-to-many-relations) apply (because `Post`↔ `CategoriesOnPosts` and `Category` ↔ `CategoriesOnPosts` are both in fact 1-n relations), which means one side of the relation needs to be annotated with the `@relation` attribute.
+
+When you don't need to attach additional information to the relation, you can model m-n-relations as [implicit m-n-relations](#implicit-many-to-many-relations). If you're not using Prisma Migrate but obtain your data model from [introspection](/orm/prisma-schema/introspection), you can still make use of implicit m-n-relations by following Prisma's [conventions for relation tables](#conventions-for-relation-tables-in-implicit-m-n-relations).
+
+#### Querying an explicit many-to-many
+
+The following section demonstrates how to query an explicit m-n-relation. You can query the relation model directly (`prisma.categoriesOnPosts(...)`), or use nested queries to go from `Post` -> `CategoriesOnPosts` -> `Category` or the other way.
+
+The following query does three things:
+
+1. Creates a `Post`
+2. Creates a new record in the relation table `CategoriesOnPosts`
+3. Creates a new `Category` that is associated with the newly created `Post` record
+
+```ts
+const createCategory = await prisma.post.create({
+ data: {
+ title: 'How to be Bob',
+ categories: {
+ create: [
+ {
+ assignedBy: 'Bob',
+ assignedAt: new Date(),
+ category: {
+ create: {
+ name: 'New category',
+ },
+ },
+ },
+ ],
+ },
+ },
+})
+```
+
+The following query:
+
+- Creates a new `Post`
+- Creates a new record in the relation table `CategoriesOnPosts`
+- Connects the category assignment to existing categories (with IDs `9` and `22`)
+
+```ts
+const assignCategories = await prisma.post.create({
+ data: {
+ title: 'How to be Bob',
+ categories: {
+ create: [
+ {
+ assignedBy: 'Bob',
+ assignedAt: new Date(),
+ category: {
+ connect: {
+ id: 9,
+ },
+ },
+ },
+ {
+ assignedBy: 'Bob',
+ assignedAt: new Date(),
+ category: {
+ connect: {
+ id: 22,
+ },
+ },
+ },
+ ],
+ },
+ },
+})
+```
+
+Sometimes you might not know if a `Category` record exists. If the `Category` record exists, you want to connect a new `Post` record to that category. If the `Category` record does not exist, you want to create the record first and then connect it to the new `Post` record. The following query:
+
+1. Creates a new `Post`
+2. Creates a new record in the relation table `CategoriesOnPosts`
+3. Connects the category assignment to an existing category (with ID `9`), or creates a new category first if it does not exist
+
+```ts
+const assignCategories = await prisma.post.create({
+ data: {
+ title: 'How to be Bob',
+ categories: {
+ create: [
+ {
+ assignedBy: 'Bob',
+ assignedAt: new Date(),
+ category: {
+ connectOrCreate: {
+ where: {
+ id: 9,
+ },
+ create: {
+ name: 'New Category',
+ id: 9,
+ },
+ },
+ },
+ },
+ ],
+ },
+ },
+})
+```
+
+The following query returns all `Post` records where at least one (`some`) category assignment (`categories`) refers to a category named `"New category"`:
+
+```ts
+const getPosts = await prisma.post.findMany({
+ where: {
+ categories: {
+ some: {
+ category: {
+ name: 'New Category',
+ },
+ },
+ },
+ },
+})
+```
+
+The following query returns all categories where at least one (`some`) related `Post` record titles contain the words `"Cool stuff"` _and_ the category was assigned by Bob.
+
+```ts
+const getAssignments = await prisma.category.findMany({
+ where: {
+ posts: {
+ some: {
+ assignedBy: 'Bob',
+ post: {
+ title: {
+ contains: 'Cool stuff',
+ },
+ },
+ },
+ },
+ },
+})
+```
+
+The following query gets all category assignments (`CategoriesOnPosts`) records that were assigned by `"Bob"` to one of 5 posts:
+
+```ts
+const getAssignments = await prisma.categoriesOnPosts.findMany({
+ where: {
+ assignedBy: 'Bob',
+ post: {
+ id: {
+ in: [9, 4, 10, 12, 22],
+ },
+ },
+ },
+})
+```
+
+### Implicit many-to-many relations
+
+Implicit m-n relations define relation fields as lists on both sides of the relation. Although the relation table exists in the underlying database, **it is managed by Prisma and does not manifest in the Prisma schema**. Implicit relation tables follow a [specific convention](#conventions-for-relation-tables-in-implicit-m-n-relations).
+
+Implicit m-n-relations makes the [Prisma Client API](/orm/prisma-client) for m-n-relations a bit simpler (since you have one fewer level of nesting inside of [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes)).
+
+In the example below, there's one _implicit_ m-n-relation between `Post` and `Category`:
+
+
+
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ categories Category[]
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ posts Post[]
+}
+```
+
+
+
+
+```sql
+CREATE TABLE "Category" (
+ id SERIAL PRIMARY KEY,
+ name TEXT NOT NULL
+);
+CREATE TABLE "Post" (
+ id SERIAL PRIMARY KEY,
+ title TEXT NOT NULL
+);
+-- Relation table + indexes -------------------------------------------------------
+CREATE TABLE "_CategoryToPost" (
+ "A" integer NOT NULL REFERENCES "Category"(id),
+ "B" integer NOT NULL REFERENCES "Post"(id)
+);
+CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON "_CategoryToPost"("A" int4_ops,"B" int4_ops);
+CREATE INDEX "_CategoryToPost_B_index" ON "_CategoryToPost"("B" int4_ops);
+```
+
+
+
+
+#### Querying an implicit many-to-many
+
+The following section demonstrates how to query an [implicit m-n](#implicit-many-to-many-relations) relation. The queries require less nesting than [explicit m-n queries](#querying-an-explicit-many-to-many).
+
+The following query creates a single `Post` and multiple `Category` records:
+
+```ts
+const createPostAndCategory = await prisma.post.create({
+ data: {
+ title: 'How to become a butterfly',
+ categories: {
+ create: [{ name: 'Magic' }, { name: 'Butterflies' }],
+ },
+ },
+})
+```
+
+The following query creates a single `Category` and multiple `Post` records:
+
+```ts
+const createCategoryAndPosts = await prisma.category.create({
+ data: {
+ name: 'Stories',
+ posts: {
+ create: [
+ { title: 'That one time with the stuff' },
+ { title: 'The story of planet Earth' },
+ ],
+ },
+ },
+})
+```
+
+The following query returns all `Post` records with a list of that post's assigned categories:
+
+```ts
+const getPostsAndCategories = await prisma.post.findMany({
+ include: {
+ categories: true,
+ },
+})
+```
+
+#### Rules for defining an implicit m-n relation
+
+Implicit m-n relations:
+
+- Use a specific [convention for relation tables](#conventions-for-relation-tables-in-implicit-m-n-relations)
+- Do **not** require the `@relation` attribute unless you need to [disambiguate relations](/orm/prisma-schema/data-model/relations#disambiguating-relations) with a name, e.g. `@relation("MyRelation")` or `@relation(name: "MyRelation")`.
+- If you do use the `@relation` attribute, you cannot use the `references`, `fields`, `onUpdate` or `onDelete` arguments. This is because these take a fixed value for implicit m-n-relations and cannot be changed.
+- Require both models to have a single `@id`. Be aware that:
+
+ - You cannot use a [multi-field ID](/orm/reference/prisma-schema-reference#id-1)
+ - You cannot use a `@unique` in place of an `@id`
+
+
+
+ To use either of these features, you must use an [explicit m-n instead](#explicit-many-to-many-relations).
+
+
+
+#### Conventions for relation tables in implicit m-n relations
+
+If you obtain your data model from [introspection](/orm/prisma-schema/introspection), you can still use implicit m-n-relations by following Prisma's [conventions for relation tables](#conventions-for-relation-tables-in-implicit-m-n-relations). The following example assumes you want to create a relation table to get an implicit m-n-relation for two models called `Post` and `Category`.
+
+##### Relation table
+
+If you want a relation table to be picked up by introspection as an implicit m-n-relation, the name must follow this exact structure:
+
+- It must start with an underscore `_`
+- Then the name of the first model in alphabetical order (in this case `Category`)
+- Then the relationship (in this case `To`)
+- Then the name of the second model in alphabetical order (in this case `Post`)
+
+In the example, the correct table name is `_CategoryToPost`.
+
+When creating an implicit m-n-relation yourself in the Prisma schema file, you can [configure the relation](#configuring-the-name-of-the-relation-table-in-implicit-many-to-many-relations) to have a different name. This will change the name given to the relation table in the database. For example, for a relation named `"MyRelation"` the corresponding table will be called `_MyRelation`.
+
+###### Multi-schema
+
+If your implicit many-to-many relationship spans multiple database schemas (using the [`multiSchema` preview feature](/orm/prisma-schema/data-model/multi-schema)), the relation table (with the name defined directly above, in the example `_CategoryToPost`) must be present in the same database schema as the first model in alphabetical order (in this case `Category`).
+
+##### Columns
+
+A relation table for an implicit m-n-relation must have exactly two columns:
+
+- A foreign key column that points to `Category` called `A`
+- A foreign key column that points to `Post` called `B`
+
+The columns must be called `A` and `B` where `A` points to the model that comes first in the alphabet and `B` points to the model which comes last in the alphabet.
+
+##### Indexes
+
+There further must be:
+
+- A unique index defined on both foreign key columns:
+
+ ```sql
+ CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON "_CategoryToPost"("A" int4_ops,"B" int4_ops);
+ ```
+
+- A non-unique index defined on B:
+
+ ```sql
+ CREATE INDEX "_CategoryToPost_B_index" ON "_CategoryToPost"("B" int4_ops);
+ ```
+
+##### Example
+
+This is a sample SQL statement that would create the three tables including indexes (in PostgreSQL dialect) that are picked up as a implicit m-n-relation by Prisma Introspection:
+
+```sql
+CREATE TABLE "_CategoryToPost" (
+ "A" integer NOT NULL REFERENCES "Category"(id) ,
+ "B" integer NOT NULL REFERENCES "Post"(id)
+);
+CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON "_CategoryToPost"("A" int4_ops,"B" int4_ops);
+CREATE INDEX "_CategoryToPost_B_index" ON "_CategoryToPost"("B" int4_ops);
+
+CREATE TABLE "Category" (
+ id integer SERIAL PRIMARY KEY
+);
+
+CREATE TABLE "Post" (
+ id integer SERIAL PRIMARY KEY
+);
+```
+
+And you can define multiple many-to-many relations between two tables by using the different relationship name. This example shows how the Prisma introspection works under such case:
+
+```sql
+CREATE TABLE IF NOT EXISTS "User" (
+ "id" SERIAL PRIMARY KEY
+);
+CREATE TABLE IF NOT EXISTS "Video" (
+ "id" SERIAL PRIMARY KEY
+);
+CREATE TABLE IF NOT EXISTS "_UserLikedVideos" (
+ "A" SERIAL NOT NULL,
+ "B" SERIAL NOT NULL,
+ CONSTRAINT "_UserLikedVideos_A_fkey" FOREIGN KEY ("A") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "_UserLikedVideos_B_fkey" FOREIGN KEY ("B") REFERENCES "Video" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+CREATE TABLE IF NOT EXISTS "_UserDislikedVideos" (
+ "A" SERIAL NOT NULL,
+ "B" SERIAL NOT NULL,
+ CONSTRAINT "_UserDislikedVideos_A_fkey" FOREIGN KEY ("A") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "_UserDislikedVideos_B_fkey" FOREIGN KEY ("B") REFERENCES "Video" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+CREATE UNIQUE INDEX "_UserLikedVideos_AB_unique" ON "_UserLikedVideos"("A", "B");
+CREATE INDEX "_UserLikedVideos_B_index" ON "_UserLikedVideos"("B");
+CREATE UNIQUE INDEX "_UserDislikedVideos_AB_unique" ON "_UserDislikedVideos"("A", "B");
+CREATE INDEX "_UserDislikedVideos_B_index" ON "_UserDislikedVideos"("B");
+```
+
+If you run `prisma db pull` on this database, the Prisma CLI will generate the following schema through introspection:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ Video_UserDislikedVideos Video[] @relation("UserDislikedVideos")
+ Video_UserLikedVideos Video[] @relation("UserLikedVideos")
+}
+
+model Video {
+ id Int @id @default(autoincrement())
+ User_UserDislikedVideos User[] @relation("UserDislikedVideos")
+ User_UserLikedVideos User[] @relation("UserLikedVideos")
+}
+```
+
+#### Configuring the name of the relation table in implicit many-to-many relations
+
+When using Prisma Migrate, you can configure the name of the relation table that's managed by Prisma using the `@relation` attribute. For example, if you want the relation table to be called `_MyRelationTable` instead of the default name `_CategoryToPost`, you can specify it as follows:
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ categories Category[] @relation("MyRelationTable")
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ posts Post[] @relation("MyRelationTable")
+}
+```
+
+### Relation tables
+
+A relation table (also sometimes called a _JOIN_, _link_ or _pivot_ table) connects two or more other tables and therefore creates a _relation_ between them. Creating relation tables is a common data modelling practice in SQL to represent relationships between different entities. In essence it means that "one m-n relation is modeled as two 1-n relations in the database".
+
+We recommend using [implicit](#implicit-many-to-many-relations) m-n-relations, where Prisma automatically generates the relation table in the underlying database. [Explicit](#explicit-many-to-many-relations) m-n-relations should be used when you need to store additional data in the relations, such as the date the relation was created.
+
+## MongoDB
+
+In MongoDB, m-n-relations are represented by:
+
+- relation fields on both sides, that each have a `@relation` attribute, with mandatory `fields` and `references` arguments
+- a scalar list of referenced IDs on each side, with a type that matches the ID field on the other side
+
+The following example demonstrates a m-n-relation between posts and categories:
+
+```prisma
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ categoryIDs String[] @db.ObjectId
+ categories Category[] @relation(fields: [categoryIDs], references: [id])
+}
+
+model Category {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ postIDs String[] @db.ObjectId
+ posts Post[] @relation(fields: [postIDs], references: [id])
+}
+```
+
+Prisma validates m-n-relations in MongoDB with the following rules:
+
+- The fields on both sides of the relation must have a list type (in the example above, `categories` have a type of `Category[]` and `posts` have a type of `Post[]`)
+- The `@relation` attribute must define `fields` and `references` arguments on both sides
+- The `fields` argument must have only one scalar field defined, which must be of a list type
+- The `references` argument must have only one scalar field defined. This scalar field must exist on the referenced model and must be of the same type as the scalar field in the `fields` argument, but singular (no list)
+- The scalar field to which `references` points must have the `@id` attribute
+- No [referential actions](/orm/prisma-schema/data-model/relations/referential-actions) are allowed in `@relation`
+
+The implicit m-n-relations [used in relational databases](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) are not supported on MongoDB.
+
+### Querying MongoDB many-to-many relations
+
+This section demonstrates how to query m-n-relations in MongoDB, using the example schema above.
+
+The following query finds posts with specific matching category IDs:
+
+```ts
+const newId1 = new ObjectId()
+const newId2 = new ObjectId()
+
+const posts = await prisma.post.findMany({
+ where: {
+ categoryIDs: {
+ hasSome: [newId1.toHexString(), newId2.toHexString()],
+ },
+ },
+})
+```
+
+The following query finds posts where the category name contains the string `'Servers'`:
+
+```ts
+const posts = await prisma.post.findMany({
+ where: {
+ categories: {
+ some: {
+ name: {
+ contains: 'Servers',
+ },
+ },
+ },
+ },
+})
+```
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/400-self-relations.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/400-self-relations.mdx
new file mode 100644
index 0000000000..c1d39811e7
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/400-self-relations.mdx
@@ -0,0 +1,434 @@
+---
+title: Self-relations
+metaDescription: How to define and work with self-relations in Prisma.
+---
+
+
+
+A relation field can also reference its own model, in this case the relation is called a _self-relation_. Self-relations can be of any cardinality, 1-1, 1-n and m-n.
+
+Note that self-relations always require the `@relation` attribute.
+
+
+
+## One-to-one self-relations
+
+The following example models a one-to-one self-relation:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ successorId Int? @unique
+ successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id])
+ predecessor User? @relation("BlogOwnerHistory")
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ successorId String? @unique @db.ObjectId
+ successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id])
+ predecessor User? @relation("BlogOwnerHistory")
+}
+```
+
+
+
+
+This relation expresses the following:
+
+- "a user can have one or zero predecessors" (for example, Sarah is Mary's predecessor as blog owner)
+- "a user can have one or zero successors" (for example, Mary is Sarah's successor as blog owner)
+
+> **Note**: One-to-one self-relations cannot be made required on both sides. One or both sides must be optional, otherwise it becomes impossible to create the first `User` record.
+
+To create a one-to-one self-relation:
+
+- Both sides of the relation must define a `@relation` attribute that share the same name - in this case, **BlogOwnerHistory**.
+- One relation field must be a [fully annotated](/orm/prisma-schema/data-model/relations#relation-fields). In this example, the `successor` field defines both the `field` and `references` arguments.
+- One relation field must be backed by a foreign key. The `successor` field is backed by the `successorId` foreign key, which references a value in the `id` field. The `successorId` scalar relation field also requires a `@unique` attribute to guarantee a one-to-one relation.
+
+> **Note**: One-to-one self relations require two sides even if both sides are equal in the relationship. For example, to model a 'best friends' relation, you would need to create two relation fields: `bestfriend1` and a `bestfriend2`.
+
+Either side of the relation can be backed by a foreign key. In the previous example, repeated below, `successor` is backed by `successorId`:
+
+
+
+
+```prisma highlight=4;normal
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ successorId Int? @unique
+ successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id])
+ predecessor User? @relation("BlogOwnerHistory")
+}
+```
+
+
+
+
+```prisma highlight=4;normal
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ successorId String? @unique @db.ObjectId
+ successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id])
+ predecessor User? @relation("BlogOwnerHistory")
+}
+```
+
+
+
+
+Alternatively, you could rewrite this so that `predecessor` is backed by `predecessorId`:
+
+
+
+
+```prisma highlight=5,6;normal
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ successor User? @relation("BlogOwnerHistory")
+ predecessorId Int? @unique
+ predecessor User? @relation("BlogOwnerHistory", fields: [predecessorId], references: [id])
+}
+```
+
+
+
+
+```prisma highlight=5,6;normal
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ successor User? @relation("BlogOwnerHistory")
+ predecessorId String? @unique @db.ObjectId
+ predecessor User? @relation("BlogOwnerHistory", fields: [predecessorId], references: [id])
+}
+```
+
+
+
+
+No matter which side is backed by a foreign key, Prisma Client surfaces both the `predecessor` and `successor` fields:
+
+```ts line-number
+const x = await prisma.user.create({
+ data: {
+ name: "Bob McBob",
+| successor: {
+ connect: {
+ id: 2,
+ },
+ },
+| predecessor: {
+ connect: {
+ id: 4,
+ },
+ },
+ },
+});
+```
+
+### One-to-one self relations in the database
+
+### Relational databases
+
+In **relational databases only**, a one-to-one self-relation is represented by the following SQL:
+
+```sql
+CREATE TABLE "User" (
+ id SERIAL PRIMARY KEY,
+ "name" TEXT,
+ "successorId" INTEGER
+);
+
+ALTER TABLE "User" ADD CONSTRAINT fk_successor_user FOREIGN KEY ("successorId") REFERENCES "User" (id);
+
+ALTER TABLE "User" ADD CONSTRAINT successor_unique UNIQUE ("successorId");
+```
+
+### MongoDB
+
+For MongoDB, Prisma currently uses a [normalized data model design](https://docs.mongodb.com/manual/core/data-model-design/), which means that documents reference each other by ID in a similar way to relational databases.
+
+The following MongoDB documents represent a one-to-one self-relation between two users:
+
+```json
+{ "_id": { "$oid": "60d97df70080618f000e3ca9" }, "name": "Elsa the Elder" }
+```
+
+```json
+{
+ "_id": { "$oid": "60d97df70080618f000e3caa" },
+ "name": "Elsa",
+ "successorId": { "$oid": "60d97df70080618f000e3ca9" }
+}
+```
+
+## One-to-many self relations
+
+A one-to-many self-relation looks as follows:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ teacherId Int?
+ teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id])
+ students User[] @relation("TeacherStudents")
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ teacherId String? @db.ObjectId
+ teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id])
+ students User[] @relation("TeacherStudents")
+}
+```
+
+
+
+
+This relation expresses the following:
+
+- "a user has zero or one _teachers_ "
+- "a user can have zero or more _students_"
+
+Note that you can also require each user to have a teacher by making the `teacher` field [required](/orm/prisma-schema/data-model/models#optional-and-mandatory-fields).
+
+### One-to-many self-relations in the database
+
+### Relational databases
+
+In relational databases, a one-to-many self-relation is represented by the following SQL:
+
+```sql
+CREATE TABLE "User" (
+ id SERIAL PRIMARY KEY,
+ "name" TEXT,
+ "teacherId" INTEGER
+);
+
+ALTER TABLE "User" ADD CONSTRAINT fk_teacherid_user FOREIGN KEY ("teacherId") REFERENCES "User" (id);
+```
+
+Notice the lack of `UNIQUE` constraint on `teacherId` - multiple students can have the same teacher.
+
+### MongoDB
+
+For MongoDB, Prisma currently uses a [normalized data model design](https://docs.mongodb.com/manual/core/data-model-design/), which means that documents reference each other by ID in a similar way to relational databases.
+
+The following MongoDB documents represent a one-to-many self-relation between three users - one teacher and two students with the same `teacherId`:
+
+```json
+{
+ "_id": { "$oid": "60d9b9e600fe3d470079d6f9" },
+ "name": "Ms. Roberts"
+}
+```
+
+```json
+{
+ "_id": { "$oid": "60d9b9e600fe3d470079d6fa" },
+ "name": "Student 8",
+ "teacherId": { "$oid": "60d9b9e600fe3d470079d6f9" }
+}
+```
+
+```json
+{
+ "_id": { "$oid": "60d9b9e600fe3d470079d6fb" },
+ "name": "Student 9",
+ "teacherId": { "$oid": "60d9b9e600fe3d470079d6f9" }
+}
+```
+
+## Many-to-many self relations
+
+A many-to-many self-relation looks as follows:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ followedBy User[] @relation("UserFollows")
+ following User[] @relation("UserFollows")
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ followedBy User[] @relation("UserFollows", fields: [followedByIDs], references: [id])
+ followedByIDs String[] @db.ObjectId
+ following User[] @relation("UserFollows", fields: [followingIDs], references: [id])
+ followingIDs String[] @db.ObjectId
+}
+```
+
+
+
+
+This relation expresses the following:
+
+- "a user can be followed by zero or more users"
+- "a user can follow zero or more users"
+
+Note that for relational databases, this many-to-many-relation is [implicit](many-to-many-relations#implicit-many-to-many-relations). This means Prisma maintains a [relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) for it in the underlying database.
+
+If you need the relation to hold other fields, you can create an [explicit](many-to-many-relations#explicit-many-to-many-relations) many-to-many self relation as well. The explicit version of the self relation shown previously is as follows:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ followedBy Follows[] @relation("followedBy")
+ following Follows[] @relation("following")
+}
+
+model Follows {
+ followedBy User @relation("followedBy", fields: [followedById], references: [id])
+ followedById Int
+ following User @relation("following", fields: [followingId], references: [id])
+ followingId Int
+
+ @@id([followingId, followedById])
+}
+```
+
+### Many-to-many self-relations in the database
+
+### Relational databases
+
+In relational databases, a many-to-many self-relation (implicit) is represented by the following SQL:
+
+```sql
+CREATE TABLE "User" (
+ id integer DEFAULT nextval('"User_id_seq"'::regclass) PRIMARY KEY,
+ name text
+);
+CREATE TABLE "_UserFollows" (
+ "A" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE,
+ "B" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE
+);
+```
+
+### MongoDB
+
+For MongoDB, Prisma currently uses a [normalized data model design](https://docs.mongodb.com/manual/core/data-model-design/), which means that documents reference each other by ID in a similar way to relational databases.
+
+The following MongoDB documents represent a many-to-many self-relation between five users - two users that follow `"Bob"`, and two users that follow him:
+
+```json
+{
+ "_id": { "$oid": "60d9866f00a3e930009a6cdd" },
+ "name": "Bob",
+ "followedByIDs": [
+ { "$oid": "60d9866f00a3e930009a6cde" },
+ { "$oid": "60d9867000a3e930009a6cdf" }
+ ],
+ "followingIDs": [
+ { "$oid": "60d9867000a3e930009a6ce0" },
+ { "$oid": "60d9867000a3e930009a6ce1" }
+ ]
+}
+```
+
+```json
+{
+ "_id": { "$oid": "60d9866f00a3e930009a6cde" },
+ "name": "Follower1",
+ "followingIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }]
+}
+```
+
+```json
+{
+ "_id": { "$oid": "60d9867000a3e930009a6cdf" },
+ "name": "Follower2",
+ "followingIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }]
+}
+```
+
+```json
+{
+ "_id": { "$oid": "60d9867000a3e930009a6ce0" },
+ "name": "CoolPerson1",
+ "followedByIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }]
+}
+```
+
+```json
+{
+ "_id": { "$oid": "60d9867000a3e930009a6ce1" },
+ "name": "CoolPerson2",
+ "followedByIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }]
+}
+```
+
+## Defining multiple self-relations on the same model
+
+You can also define multiple self-relations on the same model at once. Taking all relations from the previous sections as example, you could define a `User` model as follows:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ teacherId Int?
+ teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id])
+ students User[] @relation("TeacherStudents")
+ followedBy User[] @relation("UserFollows")
+ following User[] @relation("UserFollows")
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ teacherId String? @db.ObjectId
+ teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id])
+ students User[] @relation("TeacherStudents")
+ followedBy User[] @relation("UserFollows", fields: [followedByIDs])
+ followedByIDs String[] @db.ObjectId
+ following User[] @relation("UserFollows", fields: [followingIDs])
+ followingIDs String[] @db.ObjectId
+}
+```
+
+
+
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/100-special-rules-for-referential-actions.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/100-special-rules-for-referential-actions.mdx
new file mode 100644
index 0000000000..64174bd2c9
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/100-special-rules-for-referential-actions.mdx
@@ -0,0 +1,241 @@
+---
+title: 'Special rules for referential actions in SQL Server and MongoDB'
+metaTitle: 'Special rules for referential actions in SQL Server and MongoDB'
+metaDescription: 'Circular references or multiple cascade paths can cause validation errors on Microsoft SQL Server and MongoDB. Since the database does not handle these situations out of the box, learn how to solve this problem.'
+tocDepth: 3
+---
+
+
+
+Some databases have specific requirements that you should consider if you are using referential actions.
+
+- Microsoft SQL Server doesn't allow cascading referential actions on a foreign key, if the relation chain causes a cycle or multiple cascade paths. If the referential actions on the foreign key are set to something other than `NO ACTION` (or `NoAction` if Prisma is managing referential integrity), the server will check for cycles or multiple cascade paths and return an error when executing the SQL.
+
+- With MongoDB, using referential actions in Prisma requires that for any data model with self-referential relations or cycles between three models, you must set the referential action of `NoAction` to prevent the referential action emulations from looping infinitely. Be aware that by default, the `relationMode = "prisma"` mode is used for MongoDB, which means that Prisma manages [referential integrity](/orm/prisma-schema/data-model/relations/relation-mode).
+
+Given the SQL:
+
+```sql
+CREATE TABLE [dbo].[Employee] (
+ [id] INT NOT NULL IDENTITY(1,1),
+ [managerId] INT,
+ CONSTRAINT [PK__Employee__id] PRIMARY KEY ([id])
+);
+
+ALTER TABLE [dbo].[Employee]
+ ADD CONSTRAINT [FK__Employee__managerId]
+ FOREIGN KEY ([managerId]) REFERENCES [dbo].[Employee]([id])
+ ON DELETE CASCADE ON UPDATE CASCADE;
+```
+
+When the SQL is run, the database would throw the following error:
+
+```terminal wrap
+Introducing FOREIGN KEY constraint 'FK__Employee__managerId' on table 'Employee' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
+```
+
+In more complicated data models, finding the cascade paths can get complex. Therefore in Prisma, the data model is validated _before_ generating any SQL to be run during any migrations, highlighting relations that are part of the paths. This makes it much easier to find and break these action chains.
+
+
+
+## Self-relation (SQL Server and MongoDB)
+
+The following model describes a self-relation where an `Employee` can have a manager and managees, referencing entries of the same model.
+
+```prisma
+model Employee {
+ id Int @id @default(autoincrement())
+ manager Employee? @relation(name: "management", fields: [managerId], references: [id])
+ managees Employee[] @relation(name: "management")
+ managerId Int?
+}
+```
+
+This will result in the following error:
+
+```terminal wrap
+Error parsing attribute "@relation": A self-relation must have `onDelete` and `onUpdate` referential actions set to `NoAction` in one of the @relation attributes. (Implicit default `onDelete`: `SetNull`, and `onUpdate`: `Cascade`)
+```
+
+By not defining any actions, Prisma will use the following default values depending if the underlying [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields) are set to be optional or required.
+
+| Clause | All of the scalar fields are optional | At least one scalar field is required |
+| :--------- | :------------------------------------ | :------------------------------------ |
+| `onDelete` | `SetNull` | `NoAction` |
+| `onUpdate` | `Cascade` | `Cascade` |
+
+Since the default referential action for `onUpdate` in the above relation would be `Cascade` and for `onDelete` it would be `SetNull`, it creates a cycle and the solution is to explicitly set the `onUpdate` and `onDelete` values to `NoAction`.
+
+```prisma highlight=3;delete|4;add
+model Employee {
+ id Int @id @default(autoincrement())
+ manager Employee @relation(name: "management", fields: [managerId], references: [id])
+ manager Employee @relation(name: "management", fields: [managerId], references: [id], onDelete: NoAction, onUpdate: NoAction)
+ managees Employee[] @relation(name: "management")
+ managerId Int
+}
+```
+
+## Cyclic relation between three tables (SQL Server and MongoDB)
+
+The following models describe a cyclic relation between a `Chicken`, an `Egg` and a `Fox`, where each model references the other.
+
+```prisma
+model Chicken {
+ id Int @id @default(autoincrement())
+ egg Egg @relation(fields: [eggId], references: [id])
+ eggId Int
+ predators Fox[]
+}
+
+model Egg {
+ id Int @id @default(autoincrement())
+ predator Fox @relation(fields: [predatorId], references: [id])
+ predatorId Int
+ parents Chicken[]
+}
+
+model Fox {
+ id Int @id @default(autoincrement())
+ meal Chicken @relation(fields: [mealId], references: [id])
+ mealId Int
+ foodStore Egg[]
+}
+```
+
+This will result in three validation errors in every relation field that is part of the cycle.
+
+The first one is in the relation `egg` in the `Chicken` model:
+
+```terminal wrap
+Error parsing attribute "@relation": Reference causes a cycle. One of the @relation attributes in this cycle must have `onDelete` and `onUpdate` referential actions set to `NoAction`. Cycle path: Chicken.egg → Egg.predator → Fox.meal. (Implicit default `onUpdate`: `Cascade`)
+```
+
+The second one is in the relation `predator` in the `Egg` model:
+
+```terminal wrap
+Error parsing attribute "@relation": Reference causes a cycle. One of the @relation attributes in this cycle must have `onDelete` and `onUpdate` referential actions set to `NoAction`. Cycle path: Egg.predator → Fox.meal → Chicken.egg. (Implicit default `onUpdate`: `Cascade`)
+```
+
+And the third one is in the relation `meal` in the `Fox` model:
+
+```terminal wrap
+Error parsing attribute "@relation": Reference causes a cycle. One of the @relation attributes in this cycle must have `onDelete` and `onUpdate` referential actions set to `NoAction`. Cycle path: Fox.meal → Chicken.egg → Egg.predator. (Implicit default `onUpdate`: `Cascade`)
+```
+
+As the relation fields are required, the default referential action for `onDelete` is `NoAction` but for `onUpdate` it is `Cascade`, which causes a referential action cycle. The solution is to set the `onUpdate` value to `NoAction` in any one of the relations.
+
+```prisma highlight=3;delete|4;add
+model Chicken {
+ id Int @id @default(autoincrement())
+ egg Egg @relation(fields: [eggId], references: [id])
+ egg Egg @relation(fields: [eggId], references: [id], onUpdate: NoAction)
+ eggId Int
+ predators Fox[]
+}
+```
+
+or
+
+```prisma highlight=3;delete|4;add
+model Egg {
+ id Int @id @default(autoincrement())
+ predator Fox @relation(fields: [predatorId], references: [id])
+ predator Fox @relation(fields: [predatorId], references: [id], onUpdate: NoAction)
+ predatorId Int
+ parents Chicken[]
+}
+```
+
+or
+
+```prisma highlight=3;delete|4;add
+model Fox {
+ id Int @id @default(autoincrement())
+ meal Chicken @relation(fields: [mealId], references: [id])
+ meal Chicken @relation(fields: [mealId], references: [id], onUpdate: NoAction)
+ mealId Int
+ foodStore Egg[]
+}
+```
+
+## Multiple cascade paths between two models (SQL Server only)
+
+The data model describes two different paths between same models, with both relations triggering cascading referential actions.
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ comments Comment[]
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ authorId Int
+ author User @relation(fields: [authorId], references: [id])
+ comments Comment[]
+}
+
+model Comment {
+ id Int @id @default(autoincrement())
+ writtenById Int
+ postId Int
+ writtenBy User @relation(fields: [writtenById], references: [id])
+ post Post @relation(fields: [postId], references: [id])
+}
+```
+
+The problem in this data model is how there are two paths from `Comment` to the `User`, and how the default `onUpdate` action in both relations is `Cascade`. This leads into two validation errors:
+
+The first one is in the relation `writtenBy`:
+
+```terminal wrap
+Error parsing attribute "@relation": When any of the records in model `User` is updated or deleted, the referential actions on the relations cascade to model `Comment` through multiple paths. Please break one of these paths by setting the `onUpdate` and `onDelete` to `NoAction`. (Implicit default `onUpdate`: `Cascade`)
+```
+
+The second one is in the relation `post`:
+
+```terminal wrap
+Error parsing attribute "@relation": When any of the records in model `User` is updated or deleted, the referential actions on the relations cascade to model `Comment` through multiple paths. Please break one of these paths by setting the `onUpdate` and `onDelete` to `NoAction`. (Implicit default `onUpdate`: `Cascade`)
+```
+
+The error means that by updating a primary key in a record in the `User` model, the update will cascade once between the `Comment` and `User` through the `writtenBy` relation, and again through the `Post` model from the `post` relation due to `Post` being related with the `Comment` model.
+
+The fix is to set the `onUpdate` referential action to `NoAction` in the `writtenBy` or `post` relation fields, or from the `Post` model by changing the actions in the `author` relation:
+
+```prisma highlight=5;delete|6;add
+model Comment {
+ id Int @id @default(autoincrement())
+ writtenById Int
+ postId Int
+ writtenBy User @relation(fields: [writtenById], references: [id])
+ writtenBy User @relation(fields: [writtenById], references: [id], onUpdate: NoAction)
+ post Post @relation(fields: [postId], references: [id])
+}
+```
+
+or
+
+```prisma highlight=6;delete|7;add
+model Comment {
+ id Int @id @default(autoincrement())
+ writtenById Int
+ postId Int
+ writtenBy User @relation(fields: [writtenById], references: [id])
+ post Post @relation(fields: [postId], references: [id])
+ post Post @relation(fields: [postId], references: [id], onUpdate: NoAction)
+}
+```
+
+or
+
+```prisma highlight=4;delete|5;add
+model Post {
+ id Int @id @default(autoincrement())
+ authorId Int
+ author User @relation(fields: [authorId], references: [id])
+ author User @relation(fields: [authorId], references: [id], onUpdate: NoAction)
+ comments Comment[]
+}
+```
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/index.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/index.mdx
new file mode 100644
index 0000000000..d0ee27729a
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/410-referential-actions/index.mdx
@@ -0,0 +1,508 @@
+---
+title: 'Referential actions'
+metaTitle: 'Referential actions'
+metaDescription: 'Referential actions let you define the update and delete behavior of related models on the database level'
+tocDepth: 3
+---
+
+
+
+Referential actions determine what happens to a record when your application deletes or updates a related record.
+
+From version 2.26.0, you can define referential actions on the relation fields in your Prisma schema. This allows you to define referential actions like cascading deletes and cascading updates at a Prisma level.
+
+
+
+**Version differences**
+
+- If you use version 3.0.1 or later, you can use referential actions as described on this page.
+- If you use a version between 2.26.0 and 3.0.0, you can use referential actions as described on this page, but you must [enable the preview feature flag](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `referentialActions`.
+- If you use version 2.25.0 or earlier, you can configure cascading deletes manually in your database.
+
+
+
+In the following example, adding `onDelete: Cascade` to the `author` field on the `Post` model means that deleting the `User` record will also delete all related `Post` records.
+
+```prisma file=schema.prisma highlight=4;normal
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
+ authorId Int
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+If you do not specify a referential action, Prisma [uses a default](#referential-action-defaults).
+
+
+
+
+
+If you upgrade from a version earlier than 2.26.0:
+It is extremely important that you check the [upgrade paths for referential actions](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/referential-actions) section. Prisma support of referential actions **removes the safety net in Prisma Client that prevents cascading deletes at runtime**. If you use the feature _without upgrading your database_, the [old default action](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/referential-actions#prisma-2x-default-referential-actions) - `ON DELETE CASCADE` - becomes active. This might result in cascading deletes that you did not expect.
+
+
+
+## What are referential actions?
+
+Referential actions are policies that define how a referenced record is handled by the database when you run an [`update`](/orm/prisma-client/queries/crud#update) or [`delete`](/orm/prisma-client/queries/crud#delete) query.
+
+
+
+Referential actions on the database level
+
+Referential actions are features of foreign key constraints that exist to preserve referential integrity in your database.
+
+When you define relationships between data models in your Prisma schema, you use [relation fields](/orm/prisma-schema/data-model/relations#relation-fields), **which do not exist on the database**, and [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields), **which do exist on the database**. These foreign keys connect the models on the database level.
+
+Referential integrity states that these foreign keys must reference an existing primary key value in the related database table. In your Prisma schema, this is generally represented by the `id` field on the related model.
+
+By default a database will reject any operation that violates the referential integrity, for example, by deleting referenced records.
+
+
+
+### How to use referential actions
+
+Referential actions are defined in the [`@relation`](/orm/reference/prisma-schema-reference#relation) attribute and map to the actions on the **foreign key constraint** in the underlying database. If you do not specify a referential action, [Prisma falls back to a default](#referential-action-defaults).
+
+The following model defines a one-to-many relation between `User` and `Post` and a many-to-many relation between `Post` and `Tag`, with explicitly defined referential actions:
+
+```prisma file=schema.prisma highlight=10,16-17;normal
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ tags TagOnPosts[]
+ User User? @relation(fields: [userId], references: [id], onDelete: SetNull, onUpdate: Cascade)
+ userId Int?
+}
+
+model TagOnPosts {
+ id Int @id @default(autoincrement())
+ post Post? @relation(fields: [postId], references: [id], onUpdate: Cascade, onDelete: Cascade)
+ tag Tag? @relation(fields: [tagId], references: [id], onUpdate: Cascade, onDelete: Cascade)
+ postId Int?
+ tagId Int?
+}
+
+model Tag {
+ id Int @id @default(autoincrement())
+ name String @unique
+ posts TagOnPosts[]
+}
+```
+
+This model explicitly defines the following referential actions:
+
+- If you delete a `Tag`, the corresponding tag assignment is also deleted in `TagOnPosts`, using the `Cascade` referential action
+- If you delete a `User`, the author is removed from all posts by setting the field value to `Null`, because of the `SetNull` referential action. To allow this, `User` and `userId` must be optional fields in `Post`.
+
+Prisma supports the following referential actions:
+
+- [`Cascade`](#cascade)
+- [`Restrict`](#restrict)
+- [`NoAction`](#noaction)
+- [`SetNull`](#setnull)
+- [`SetDefault`](#setdefault)
+
+### Referential action defaults
+
+If you do not specify a referential action, Prisma uses the following defaults:
+
+| Clause | Optional relations | Mandatory relations |
+| :--------- | :----------------- | :------------------ |
+| `onDelete` | `SetNull` | `Restrict` |
+| `onUpdate` | `Cascade` | `Cascade` |
+
+For example, in the following schema all `Post` records must be connected to a `User` via the `author` relation:
+
+```prisma highlight=4;normal
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+The schema does not explicitly define referential actions on the mandatory `author` relation field, which means that the default referential actions of `Restrict` for `onDelete` and `Cascade` for `onUpdate` apply.
+
+## Caveats
+
+The following caveats apply:
+
+- Referential actions are **not** supported on [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations). To use referential actions, you must define an explicit many-to-many relation and define your referential actions on the [join table](/orm/prisma-schema/data-model/relations/troubleshooting-relations#how-to-use-a-relation-table-with-a-many-to-many-relationship).
+- Certain combinations of referential actions and required/optional relations are incompatible. For example, using `SetNull` on a required relation will lead to database errors when deleting referenced records because the non-nullable constraint would be violated. See [this GitHub issue](https://github.com/prisma/prisma/issues/7909) for more information.
+
+## Types of referential actions
+
+The following table shows which referential action each database supports.
+
+| Database | Cascade | Restrict | NoAction | SetNull | SetDefault |
+| :---------- | :------ | :------- | :------- | :------ | :--------- |
+| PostgreSQL | ✔️ | ✔️ | ✔️ | ✔️⌘ | ✔️ |
+| MySQL | ✔️ | ✔️ | ✔️ | ✔️ | ❌ (✔️†) |
+| SQLite | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
+| SQL Server | ✔️ | ❌‡ | ✔️ | ✔️ | ✔️ |
+| CockroachDB | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
+| MongoDB†† | ✔️ | ✔️ | ✔️ | ✔️ | ❌ |
+
+- † See [special cases for MySQL](#mysql).
+- ⌘ See [special cases for PostgreSQL](#postgresql).
+- ‡ See [special cases for SQL Server](#sql-server).
+- †† Referential actions for MongoDB are available in Prisma versions 3.7.0 and later.
+
+### Special cases for referential actions
+
+Referential actions are part of the ANSI SQL standard. However, there are special cases where some relational databases diverge from the standard.
+
+#### MySQL
+
+MySQL, and the underlying InnoDB storage engine, does not support `SetDefault`. The exact behavior depends on the database version:
+
+- In MySQL versions 8 and later, and MariaDB versions 10.5 and later, `SetDefault` effectively acts as an alias for `NoAction`. You can define tables using the `SET DEFAULT` referential action, but a foreign key constraint error is triggered at runtime.
+- In MySQL versions 5.6 and later, and MariaDB versions before 10.5, attempting to create a table definition with the `SET DEFAULT` referential action fails with a syntax error.
+
+For this reason, when you set `mysql` as the database provider, Prisma warns users to replace `SetDefault` referential actions in the Prisma schema with another action.
+
+#### PostgreSQL
+
+PostgreSQL is the only database supported by Prisma that allows you to define a `SetNull` referential action that refers to a non-nullable field. However, this raises a foreign key constraint error when the action is triggered at runtime.
+
+For this reason, when you set `postgres` as the database provider in the (default) `foreignKeys` relation mode, Prisma warns users to mark as optional any fields that are included in a `@relation` attribute with a `SetNull` referential action. For all other database providers, Prisma rejects the schema with a validation error.
+
+#### SQL Server
+
+[`Restrict`](#restrict) is not available for SQL Server databases, but you can use [`NoAction`](#noaction) instead.
+
+### `Cascade`
+
+- `onDelete: Cascade` Deleting a referenced record will trigger the deletion of referencing record.
+- `onUpdate: Cascade` Updates the relation scalar fields if the referenced scalar fields of the dependent record are updated.
+
+#### Example usage
+
+```prisma file=schema.prisma highlight=4;add
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)
+ authorId Int
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+##### Result of using `Cascade`
+
+If a `User` record is deleted, then their posts are deleted too. If the user's `id` is updated, then the corresponding `authorId` is also updated.
+
+##### How to use cascading deletes
+
+
+
+
+
+### `Restrict`
+
+- `onDelete: Restrict` Prevents the deletion if any referencing records exist.
+- `onUpdate: Restrict` Prevents the identifier of a referenced record from being changed.
+
+#### Example usage
+
+```prisma file=schema.prisma highlight=4;add
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id], onDelete: Restrict, onUpdate: Restrict)
+ authorId Int
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+##### Result of using `Restrict`
+
+`User`s with posts **cannot** be deleted. The `User`'s `id` **cannot** be changed.
+
+
+
+The `Restrict` action is **not** available on [Microsoft SQL Server](/orm/overview/databases/sql-server) and triggers a schema validation error. Instead, you can use [`NoAction`](#noaction), which produces the same result and is compatible with SQL Server.
+
+
+
+### `NoAction`
+
+The `NoAction` action is similar to `Restrict`, the difference between the two is dependent on the database being used:
+
+- **PostgreSQL**: `NoAction` allows the check (if a referenced row on the table exists) to be deferred until later in the transaction. See [the PostgreSQL docs](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-FK) for more information.
+- **MySQL**: `NoAction` behaves exactly the same as `Restrict`. See [the MySQL docs](https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html#foreign-key-referential-actions) for more information.
+- **SQLite**: When a related primary key is modified or deleted, no action is taken. See [the SQLite docs](https://www.sqlite.org/foreignkeys.html#fk_actions) for more information.
+- **SQL Server**: When a referenced record is deleted or modified, an error is raised. See [the SQL Server docs](https://docs.microsoft.com/en-us/sql/relational-databases/tables/graph-edge-constraints?view=sql-server-ver15#on-delete-referential-actions-on-edge-constraints) for more information.
+- **MongoDB** (in preview from version 3.6.0): When a record is modified or deleted, nothing is done to any related records.
+
+
+
+If you are [managing relations in Prisma Client](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-with-the-prisma-relation-mode) rather than using foreign keys in the database, you should be aware that currently Prisma only implements the referential actions. Foreign keys also create constraints, which make it impossible to manipulate data in a way that would violate these constraints: instead of executing the query, the database responds with an error. These constraints will not be created if you emulate referential integrity in Prisma Client, so if you set the referential action to `NoAction` there will be no checks to prevent you from breaking the referential integrity.
+
+
+
+#### Example usage
+
+```prisma file=schema.prisma highlight=4;add
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
+ authorId Int
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+##### Result of using `NoAction`
+
+`User`'s with posts **cannot** be deleted. The `User`'s `id` **cannot** be changed.
+
+### `SetNull`
+
+- `onDelete: SetNull` The scalar field of the referencing object will be set to `NULL`.
+
+- `onUpdate: SetNull` When updating the identifier of a referenced object, the scalar fields of the referencing objects will be set to `NULL`.
+
+`SetNull` will only work on optional relations. On required relations, a runtime error will be thrown since the scalar fields cannot be null.
+
+```prisma file=schema.prisma highlight=4;add
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User? @relation(fields: [authorId], references: [id], onDelete: SetNull, onUpdate: SetNull)
+ authorId Int?
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+##### Result of using `SetNull`
+
+When deleting a `User`, the `authorId` will be set to `NULL` for all its authored posts.
+
+When changing a `User`'s `id`, the `authorId` will be set to `NULL` for all its authored posts.
+
+### `SetDefault`
+
+- `onDelete: SetDefault` The scalar field of the referencing object will be set to the fields default value.
+
+- `onUpdate: SetDefault` The scalar field of the referencing object will be set to the fields default value.
+
+These require setting a default for the relation scalar field with [`@default`](/orm/reference/prisma-schema-reference#default). If no defaults are provided for any of the scalar fields, a runtime error will be thrown.
+
+```prisma file=schema.prisma highlight=4,5;add
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ authorUsername String? @default("anonymous")
+ author User? @relation(fields: [authorUsername], references: [username], onDelete: SetDefault, onUpdate: SetDefault)
+}
+
+model User {
+ username String @id
+ posts Post[]
+}
+```
+
+##### Result of using `SetDefault`
+
+When deleting a `User`, its existing posts' `authorUsername` field values will be set to 'anonymous'.
+
+When the `username` of a `User` changes, its existing posts' `authorUsername` field values will be set to 'anonymous'.
+
+### Database-specific requirements
+
+MongoDB and SQL Server have specific requirements for referential actions if you have [self-relations](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions#self-relation-sql-server-and-mongodb) or [cyclic relations](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions#cyclic-relation-between-three-tables-sql-server-and-mongodb) in your data model. SQL Server also has specific requirements if you have relations with [multiple cascade paths](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions#multiple-cascade-paths-between-two-models-sql-server-only).
+
+## Upgrade paths from versions 2.25.0 and earlier
+
+There are a couple of paths you can take when upgrading which will give different results depending on the desired outcome.
+
+If you currently use the migration workflow, you can run an introspection to check how the defaults are reflected in your schema. You can then manually update your database if you need to.
+
+You can also decide to skip checking the defaults and run a migration to update your database with the [new default values](#referential-action-defaults).
+
+The following assumes you have upgraded to 2.26.0 or newer and enabled the preview feature flag, or upgraded to 3.0.0 or newer:
+
+### Using Introspection
+
+If you [Introspect](/orm/prisma-schema/introspection) your database, the referential actions configured at the database level will be reflected in your Prisma Schema. If you have been using Prisma Migrate or `prisma db push` to manage the database schema, these are likely to be the [default values](#referential-action-defaults) from 2.25.0 and earlier.
+
+When you run an Introspection, Prisma compares all the foreign keys in the database with the schema, if the SQL statements `ON DELETE` and `ON UPDATE` do **not** match the default values, they will be explicitly set in the schema file.
+
+After introspecting, you can review the non-default clauses in your schema. The most important clause to review is `onDelete`, which defaults to `Cascade` in 2.25.0 and earlier.
+
+
+
+If you are using either the [`delete()`](/orm/prisma-client/queries/crud#delete-a-single-record) or [`deleteMany()`](/orm/prisma-client/queries/crud#delete-all-records) methods, **[cascading deletes](#how-to-use-cascading-deletes) will now be performed** as the `referentialActions` preview feature **removed the safety net in Prisma Client that previously prevented cascading deletes at runtime**. Be sure to check your code and make any adjustments accordingly.
+
+
+
+Make sure you are happy with every case of `onDelete: Cascade` in your schema. If not, either:
+
+- Modify your Prisma schema and `db push` or `dev migrate` to change the database
+
+_or_
+
+- Manually update the underlying database if you use an introspection-only workflow
+
+The following example would result in a cascading delete, if the `User` is deleted then all of their `Post`'s will be deleted too.
+
+#### A blog schema example
+
+```prisma highlight=4;add
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
+ authorId Int
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+### Using Migration
+
+When running a [Migration](/orm/prisma-migrate) (or the [`prisma db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) command) the [new defaults](#referential-action-defaults) will be applied to your database.
+
+
+
+Unlike when you run an Introspect for the first time, the new referential actions clause and property, will **not** automatically be added to your prisma schema by the Prisma VSCode extension.
+You will have to manually add them if you wish to use anything other than the new defaults.
+
+
+
+Explicitly defining referential actions in your Prisma schema is optional. If you do not explicitly define a referential action for a relation, Prisma uses the [new defaults](#referential-action-defaults).
+
+Note that referential actions can be added on a case by case basis. This means that you can add them to one single relation and leave the rest set to the defaults by not manually specifying anything.
+
+### Checking for errors
+
+**Before** upgrading to 2.26.0 and enabling the referential actions **preview feature**, Prisma prevented the deletion of records while using `delete()` or `deleteMany()` to preserve referential integrity. A custom runtime error would be thrown by Prisma Client with the error code `P2014`.
+
+**After** upgrading and enabling the referential actions **preview feature**, Prisma no longer performs runtime checks. You can instead specify a custom referential action to preserve the referential integrity between relations.
+
+When you use [`NoAction`](#noaction) or [`Restrict`](#restrict) to prevent the deletion of records, the error messages will be different post 2.26.0 compared to pre 2.26.0. This is because they are now triggered by the database and **not** Prisma Client. The new error code that can be expected is `P2003`.
+
+To make sure you catch these new errors you can adjust your code accordingly.
+
+#### Example of catching errors
+
+The following example uses the below blog schema with a one-to-many relationship between `Post` and `User` and sets a [`Restrict`](#restrict) referential actions on the `author` field.
+
+This means that if a user has a post, that user (and their posts) **cannot** be deleted.
+
+```prisma file=schema.prisma
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id], onDelete: Restrict)
+ authorId String
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+Prior to upgrading and enabling the referential actions **preview feature**, the error code you would receive when trying to delete a user which has posts would be `P2014` and it's message:
+
+> "The change you are trying to make would violate the required relation '\{relation_name}' between the \{model_a_name\} and \{model_b_name\} models."
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ try {
+ await prisma.user.delete({
+ where: {
+ id: 'some-long-id',
+ },
+ })
+ } catch (error) {
+ if (error instanceof Prisma.PrismaClientKnownRequestError) {
+ if (error.code === 'P2014') {
+ console.log(error.message)
+ }
+ }
+ }
+}
+
+main()
+```
+
+To make sure you are checking for the correct errors in your code, modify your check to look for `P2003`, which will deliver the message:
+
+> "Foreign key constraint failed on the field: \{field_name\}"
+
+```ts highlight=14;delete|15;add
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ try {
+ await prisma.user.delete({
+ where: {
+ id: 'some-long-id'
+ }
+ })
+ } catch (error) {
+ if (error instanceof Prisma.PrismaClientKnownRequestError) {
+ if (error.code === 'P2014') {
+ if (error.code === 'P2003') {
+ console.log(error.message)
+ }
+ }
+ }
+}
+
+main()
+```
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/420-relation-mode.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/420-relation-mode.mdx
new file mode 100644
index 0000000000..6bebf42a7c
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/420-relation-mode.mdx
@@ -0,0 +1,257 @@
+---
+title: 'Relation mode'
+metaTitle: 'Manage relations between records with relation modes in Prisma'
+metaDescription: 'Manage relations between records with relation modes in Prisma'
+tocDepth: 3
+---
+
+
+
+In Prisma, relations between records are defined with the [`@relation`](/orm/reference/prisma-schema-reference#relation) attribute. For example, in the following schema there is a one-to-many relation between the `User` and `Post` models:
+
+```prisma file=schema.prisma highlight=4,5,10;normal
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade)
+ authorId Int
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+Prisma has two _relation modes_, `foreignKeys` and `prisma`, that specify how relations between records are enforced.
+
+If you use Prisma with a relational database, then by default Prisma uses the [`foreignKeys` relation mode](#handle-relations-in-your-relational-database-with-the-foreignkeys-relation-mode), which enforces relations between records at the database level with foreign keys. A foreign key is a column or group of columns in one table that take values based on the primary key in another table. Foreign keys allow you to:
+
+- set constraints that prevent you from making changes that break references
+- set [referential actions](/orm/prisma-schema/data-model/relations/referential-actions) that define how changes to records are handled
+
+Together these constraints and referential actions guarantee the _referential integrity_ of the data.
+
+For the example schema above, Prisma Migrate will generate the following SQL by default if you use the PostgreSQL connector:
+
+```sql highlight=19-22;normal
+
+-- CreateTable
+CREATE TABLE "Post" (
+ "id" SERIAL NOT NULL,
+ "title" TEXT NOT NULL,
+ "authorId" INTEGER NOT NULL,
+
+ CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "User" (
+ "id" SERIAL NOT NULL,
+
+ CONSTRAINT "User_pkey" PRIMARY KEY ("id")
+);
+
+-- AddForeignKey
+ALTER TABLE "Post"
+ ADD CONSTRAINT "Post_authorId_fkey"
+ FOREIGN KEY ("authorId")
+ REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+```
+
+In this case, the foreign key constraint on the `authorId` column of the `Post` table references the `id` column of the `User` table, and guarantees that a post must have an author that exists. If you update or delete a user then the `ON DELETE` and `ON UPDATE` referential actions specify the `CASCADE` option, which will also delete or update all posts belonging to the user.
+
+Some databases, such as MongoDB or [PlanetScale](/orm/overview/databases/planetscale#differences-to-consider), do not support foreign keys. Additionally, in some cases developers may prefer not to use foreign keys in their relational database that usually does support foreign keys. For these situations, Prisma offers [the `prisma` relation mode](#emulate-relations-in-prisma-with-the-prisma-relation-mode), which emulates some properties of relations in relational databases. When you use Prisma Client with the `prisma` relation mode enabled, the behavior of queries is identical or similar, but referential actions and some constraints are handled by the Prisma engine rather than in the database.
+
+
+ There are performance implications to emulation of referential integrity and
+ referential actions in Prisma Client. In cases where the underlying database
+ supports foreign keys, it is usually the preferred choice.
+
+
+
+
+## How to set the relation mode in your Prisma schema
+
+To set the relation mode, add the `relationMode` field in the `datasource` block:
+
+```prisma file=schema.prisma highlight=4,9;add
+datasource db {
+ provider = "mysql"
+ url = env("DATABASE_URL")
+ relationMode = "prisma"
+}
+```
+
+
+
+The ability to set the relation mode was introduced as part of the `referentialIntegrity` preview feature in Prisma version 3.1.1, and is generally available in Prisma versions 4.8.0 and later.
The `relationMode` field was renamed in Prisma version 4.5.0, and was previously named `referentialIntegrity`.
+
+
+
+For relational databases, the available options are:
+
+- `foreignKeys`: this handles relations in the database with foreign keys. This is the default option for all relational database connectors and is active if no `relationMode` is explicitly set in the `datasource` block.
+- `prisma`: this emulates relations in Prisma Client. You should also [enable this option](/orm/overview/databases/planetscale#how-to-emulate-relations-in-prisma-client) when you use the MySQL connector with a PlanetScale database.
+
+For MongoDB, the only available option is the `prisma` relation mode. This mode is also active if no `relationMode` is explicitly set in the `datasource` block.
+
+
+
+If you switch between relation modes, Prisma will add or remove foreign keys to your database next time you apply changes to your schema with Prisma Migrate or `db push`. See [Switch between relation modes](#switch-between-relation-modes) for more information.
+
+
+
+## Handle relations in your relational database with the `foreignKeys` relation mode
+
+The `foreignKeys` relation mode handles relations in your relational database with foreign keys. This is the default option when you use a relational database connector (PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB).
+
+The `foreignKeys` relation mode is not available when you use the MongoDB connector. Some relational databases, [such as PlanetScale](/orm/overview/databases/planetscale#how-to-emulate-relations-in-prisma-client), also forbid the use of foreign keys. In these cases, you should instead [emulate relations in Prisma with the `prisma` relation mode](#emulate-relations-in-prisma-with-the-prisma-relation-mode).
+
+### Referential integrity
+
+The `foreignKeys` relation mode maintains referential integrity at the database level with foreign key constraints and referential actions.
+
+#### Foreign key constraints
+
+When you _create_ or _update_ a record with a relation to another record, the related record needs to exist. Foreign key constraints enforce this behavior in the database. If the record does not exist, the database will return an error message.
+
+#### Referential actions
+
+When you _update_ or _delete_ a record with a relation to another record, referential actions are triggered in the database. To maintain referential integrity in related records, referential actions prevent changes that would break referential integrity, cascade changes through to related records, or set the value of fields that reference the updated or deleted records to a `null` or default value.
+
+For more information, see the [referential actions](/orm/prisma-schema/data-model/relations/referential-actions) page.
+
+### Introspection
+
+When you introspect a relational database with the `db pull` command with the `foreignKeys` relation mode enabled, a `@relation` attribute will be added to your Prisma schema for relations where foreign keys exist.
+
+### Prisma Migrate and `db push`
+
+When you apply changes to your Prisma schema with Prisma Migrate or `db push` with the `foreignKeys` relation mode enabled, foreign keys will be created in your database for all `@relation` attributes in your schema.
+
+## Emulate relations in Prisma with the `prisma` relation mode
+
+The `prisma` relation mode emulates some foreign key constraints and referential actions for each Prisma Client query to maintain referential integrity, using some additional database queries and logic.
+
+The `prisma` relation mode is the default option for the MongoDB connector. It should also be set if you use a relational database that does not support foreign keys. For example, [if you use PlanetScale](/orm/overview/databases/planetscale#how-to-emulate-relations-in-prisma-client) you should use the `prisma` relation mode.
+
+
+ There are performance implications to emulation of referential integrity in
+ Prisma Client, because it uses additional database queries to maintain
+ referential integrity. In cases where the underlying database can handle
+ referential integrity with foreign keys, it is usually the preferred choice.
+
+
+Emulation of relations is only available for Prisma Client queries and does not apply to raw queries.
+
+### Which foreign key constraints are emulated?
+
+When you _update_ a record, Prisma will emulate foreign key constraints. This means that when you update a record with a relation to another record, the related record needs to exist. If the record does not exist, Prisma Client will return an error message.
+
+However, when you _create_ a record, Prisma does not emulate any foreign key constraints. You will be able to create invalid data.
+
+### Which referential actions are emulated?
+
+When you _update_ or _delete_ a record with related records, Prisma will emulate referential actions.
+
+The following table shows which emulated referential actions are available for each database connector:
+
+| Database | Cascade | Restrict | NoAction | SetNull | SetDefault |
+| :---------- | :------ | :------- | :------- | :------ | :--------- |
+| PostgreSQL | **✔️** | **✔️** | **❌**‡ | **✔️** | **❌**† |
+| MySQL | **✔️** | **✔️** | **✔️** | **✔️** | **❌**† |
+| SQLite | **✔️** | **✔️** | **❌**‡ | **✔️** | **❌**† |
+| SQL Server | **✔️** | **✔️** | **✔️** | **✔️** | **❌**† |
+| CockroachDB | **✔️** | **✔️** | **✔️** | **✔️** | **❌**† |
+| MongoDB | **✔️** | **✔️** | **✔️** | **✔️** | **❌**† |
+
+- † The `SetDefault` referential action is not supported in the `prisma` relation mode.
+- ‡ The `NoAction` referential action is not supported in the `prisma` relation mode for PostgreSQL and SQLite. Instead, use the `Restrict` action.
+
+### Error messages
+
+Error messages returned by emulated constraints and referential actions in the `prisma` relation mode are generated by Prisma Client and differ slightly from the error messages in the `foreignKeys` relation mode:
+
+```jsx
+Example:
+// foreignKeys:
+... Foreign key constraint failed on the field: `ProfileOneToOne_userId_fkey (index)`
+// prisma:
+... The change you are trying to make would violate the required relation 'ProfileOneToOneToUserOneToOne' between the `ProfileOneToOne` and `UserOneToOne` models.
+```
+
+### Introspection
+
+When you introspect a database with the `db pull` command with the `prisma` relation mode enabled, relations will not be automatically added to your schema. You will instead need to add any relations manually with the `@relation` attribute. This only needs to be done once – next time you introspect your database, Prisma will keep your added `@relation` attributes.
+
+### Prisma Migrate and `db push`
+
+When you apply changes to your Prisma schema with Prisma Migrate or `db push` with the `prisma` relation mode enabled, Prisma will not use foreign keys in your database.
+
+### Indexes
+
+In relational databases that use foreign key constraints, the database usually also implicitly creates an index for the foreign key columns. For example, [MySQL will create an index on all foreign key columns](https://dev.mysql.com/doc/refman/8.0/en/constraint-foreign-key.html#:~:text=MySQL%20requires%20that%20foreign%20key%20columns%20be%20indexed%3B%20if%20you%20create%20a%20table%20with%20a%20foreign%20key%20constraint%20but%20no%20index%20on%20a%20given%20column%2C%20an%20index%20is%20created.). This is to allow foreign key checks to run fast and not require a table scan.
+
+The `prisma` relation mode does not use foreign keys, so no indexes are created when you use Prisma Migrate or `db push` to apply changes to your database. You instead need to manually add an index on your relation scalar fields with the [`@@index`](/orm/reference/prisma-schema-reference#index) attribute (or the [`@unique`](/orm/reference/prisma-schema-reference#unique), [`@@unique`](/orm/reference/prisma-schema-reference#unique-1) or [`@@id`](/orm/reference/prisma-schema-reference#id-1) attributes, if applicable).
+
+#### Index validation
+
+If you do not add the index manually, queries might require full table scans. This can be slow, and also expensive on database providers that bill per accessed row. To help avoid this, Prisma warns you when your schema contains fields that are used in a `@relation` that does not have an index defined. For example, take the following schema with a relation between the `User` and `Post` models:
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "mysql"
+ url = env("DATABASE_URL")
+ relationMode = "prisma"
+}
+
+model User {
+ id Int @id
+ posts Post[]
+}
+
+model Post {
+ id Int @id
+ userId Int
+ user User @relation(fields: [userId], references: [id])
+}
+```
+
+Prisma displays the following warning when you run `prisma format` or `prisma validate`:
+
+```terminal wrap
+With `relationMode = "prisma"`, no foreign keys are used, so relation fields will not benefit from the index usually created by the relational database under the hood. This can lead to poor performance when querying these fields. We recommend adding an index manually.
+```
+
+To fix this, add an index to your `Post` model:
+
+```prisma file=schema.prisma highlight=6;add
+model Post {
+ id Int @id
+ userId Int
+ user User @relation(fields: [userId], references: [id])
+
+ @@index([userId])
+}
+```
+
+If you use the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) (or our [language server in another editor](/orm/more/development-environment/editor-setup)), the warning is augmented with a Quick Fix that adds the required index for you:
+
+
+
+## Switch between relation modes
+
+It is only possible to switch between relation modes when you use a relational database connector (PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB).
+
+### Switch from `foreignKeys` to `prisma`
+
+The default relation mode if you use a relational database and do not include the `relationMode` field in your `datasource` block is `foreignKeys`. To switch to the `prisma` relation mode, add the `relationMode` field with a value of `prisma`, or update the `relationMode` field value to `prisma` if it already exists.
+
+When you switch the relation mode from `foreignKeys` to `prisma`, after you first apply changes to your schema with Prisma Migrate or `db push` Prisma will remove all previously created foreign keys in the next migration.
+
+If you keep the same database, you can then continue to work as normal. If you switch to a database that does not support foreign keys at all, your existing migration history contains SQL DDL that creates foreign keys, which might trigger errors if you ever have to rerun these migrations. In this case, we recommend that you delete the `migrations` directory. (If you use PlanetScale, which does not support foreign keys, we generally recommend that you [use `db push` rather than Prisma Migrate](/orm/overview/databases/planetscale#differences-to-consider).)
+
+### Switch from `prisma` to `foreignKeys`
+
+To switch from the `prisma` relation mode to the `foreignKeys` relation mode, update the `relationMode` field value from `prisma` to `foreignKeys`. To do this, the database must support foreign keys. When you apply changes to your schema with Prisma Migrate or `db push` for the first time after you switch relation modes, Prisma will create foreign keys for all relations in the next migration.
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/500-troubleshooting-relations.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/500-troubleshooting-relations.mdx
new file mode 100644
index 0000000000..1e6d09215a
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/500-troubleshooting-relations.mdx
@@ -0,0 +1,271 @@
+---
+title: Troubleshooting relations
+metaDescriptions: Common problems and solutions when defining relations in the Prisma schema.
+---
+
+
+
+Modelling your schema can sometimes offer up some unexpected results. This section aims to cover the most prominent of those.
+
+
+
+## Implicit many-to-many self-relations return incorrect data if order of relation fields change
+
+### Problem
+
+In the following implicit many-to-many self-relation, the lexicographic order of relation fields in `a_eats` (1) and `b_eatenBy` (2):
+
+```prisma highlight=4,5;normal
+model Animal {
+ id Int @id @default(autoincrement())
+ name String
+ a_eats Animal[] @relation(name: "FoodChain")
+ b_eatenBy Animal[] @relation(name: "FoodChain")
+}
+```
+
+The resulting relation table in SQL looks as follows, where `A` represents prey (`a_eats`) and `B` represents predators (`b_eatenBy`):
+
+| A | B |
+| :----------- | :--------- |
+| 8 (Plankton) | 7 (Salmon) |
+| 7 (Salmon) | 9 (Bear) |
+
+The following query returns a salmon's prey and predators:
+
+
+
+
+```ts
+const getAnimals = await prisma.animal.findMany({
+ where: {
+ name: 'Salmon',
+ },
+ include: {
+ b_eats: true,
+ a_eatenBy: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 7,
+ "name": "Salmon",
+ "b_eats": [
+ {
+ "id": 8,
+ "name": "Plankton"
+ }
+ ],
+ "a_eatenBy": [
+ {
+ "id": 9,
+ "name": "Bear"
+ }
+ ]
+}
+```
+
+
+
+
+Now change the order of the relation fields:
+
+```prisma highlight=4,5;normal
+model Animal {
+ id Int @id @default(autoincrement())
+ name String
+ b_eats Animal[] @relation(name: "FoodChain")
+ a_eatenBy Animal[] @relation(name: "FoodChain")
+}
+```
+
+Migrate your changes and re-generate Prisma Client. When you run the same query with the updated field names, Prisma Client returns incorrect data (salmon now eats bears and gets eaten by plankton):
+
+
+
+
+```ts
+const getAnimals = await prisma.animal.findMany({
+ where: {
+ name: 'Salmon',
+ },
+ include: {
+ b_eats: true,
+ a_eatenBy: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 1,
+ "name": "Salmon",
+ "b_eats": [
+ {
+ "id": 3,
+ "name": "Bear"
+ }
+ ],
+ "a_eatenBy": [
+ {
+ "id": 2,
+ "name": "Plankton"
+ }
+ ]
+}
+```
+
+
+
+
+Although the lexicographic order of the relation fields in the Prisma schema changed, columns `A` and `B` in the database **did not change** (they were not renamed and data was not moved). Therefore, `A` now represents predators (`a_eatenBy`) and `B` represents prey (`b_eats`):
+
+| A | B |
+| :----------- | :--------- |
+| 8 (Plankton) | 7 (Salmon) |
+| 7 (Salmon) | 9 (Bear) |
+
+### Solution
+
+If you rename relation fields in an implicit many-to-many self-relations, make sure that you maintain the alphabetic order of the fields - for example, by prefixing with `a_` and `_b`.
+
+## How to use a relation table with a many-to-many relationship
+
+There are a couple of ways to define a m-n relationship, implicitly or explicitly. Implicitly means letting Prisma handle the relation table (JOIN table) under the hood, all you have to do is define an array/list for the non scalar types on each model, see [implicit many-to-many relations](many-to-many-relations#implicit-many-to-many-relations).
+
+Where you might run into trouble is when creating an [explicit m-n relationship](many-to-many-relations#explicit-many-to-many-relations), that is, to create and handle the relation table yourself. **It can be overlooked that Prisma requires both sides of the relation to be present**.
+
+Take the following example, here a relation table is created to act as the JOIN between the `Post` and `Category` tables. This will not work however as the relation table (`PostCategories`) must form a 1-to-many relationship with the other two models respectively.
+
+The back relation fields are missing from the `Post` to `PostCategories` and `Category` to `PostCategories` models.
+
+
+```prisma
+// This example schema shows how NOT to define an explicit m-n relation
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ categories Category[] // This should refer to PostCategories
+}
+
+model PostCategories {
+ post Post @relation(fields: [postId], references: [id])
+ postId Int
+ category Category @relation(fields: [categoryId], references: [id])
+ categoryId Int
+ @@id([postId, categoryId])
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ posts Post[] // This should refer to PostCategories
+}
+```
+
+
+To fix this the `Post` model needs to have a many relation field defined with the relation table `PostCategories`. The same applies to the `Category` model.
+
+This is because the relation model forms a 1-to-many relationship with the other two models its joining.
+
+```prisma highlight=5,21;add|4,20;delete
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ categories Category[]
+ postCategories PostCategories[]
+}
+
+model PostCategories {
+ post Post @relation(fields: [postId], references: [id])
+ postId Int
+ category Category @relation(fields: [categoryId], references: [id])
+ categoryId Int
+
+ @@id([postId, categoryId])
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ posts Post[]
+ postCategories PostCategories[]
+}
+```
+
+## Using the `@relation` attribute with a many-to-many relationship
+
+It might seem logical to add a `@relation("Post")` annotation to a relation field on your model when composing an implicit many-to-many relationship.
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ categories Category[] @relation("Category")
+ Category Category? @relation("Post", fields: [categoryId], references: [id])
+ categoryId Int?
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ posts Post[] @relation("Post")
+ Post Post? @relation("Category", fields: [postId], references: [id])
+ postId Int?
+}
+```
+
+This however tells Prisma to expect **two** separate one-to-many relationships. See [disambiguating relations](/orm/prisma-schema/data-model/relations#disambiguating-relations) for more information on using the `@relation` attribute.
+
+The following example is the correct way to define an implicit many-to-many relationship.
+
+```prisma highlight=4,11;delete|5,12;add
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ categories Category[] @relation("Category")
+ categories Category[]
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ posts Post[] @relation("Post")
+ posts Post[]
+}
+```
+
+The `@relation` annotation can also be used to [name the underlying relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#configuring-the-name-of-the-relation-table-in-implicit-many-to-many-relations) created on a implicit many-to-many relationship.
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ categories Category[] @relation("CategoryPostRelation")
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ posts Post[] @relation("CategoryPostRelation")
+}
+```
+
+## Using m-n relations in databases with enforced primary keys
+
+### Problem
+
+Some cloud providers enforce the existence of primary keys in all tables. However, any relation tables (JOIN tables) created by Prisma (expressed via `@relation`) for many-to-many relations using implicit syntax do not have primary keys.
+
+### Solution
+
+You need to use [explicit relation syntax](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations), manually create the join model, and verify that this join model has a primary key.
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/index.mdx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/index.mdx
new file mode 100644
index 0000000000..7ade8e95f3
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/index.mdx
@@ -0,0 +1,579 @@
+---
+title: 'Relations'
+metaTitle: 'Relations (Reference)'
+metaDescription: 'A relation is a connection between two models in the Prisma schema. This page explains how you can define one-to-one, one-to-many and many-to-many relations in Prisma.'
+tocDepth: 3
+---
+
+
+
+A relation is a _connection_ between two models in the Prisma schema. For example, there is a one-to-many relation between `User` and `Post` because one user can have many blog posts.
+
+
+
+The following Prisma schema defines a one-to-many relation between the `User` and `Post` models. The fields involved in defining the relation are highlighted:
+
+
+
+
+```prisma highlight=3,8,9;normal
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+```prisma highlight=3,8,9;normal
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+At a Prisma level, the `User` / `Post` relation is made up of:
+
+- Two [relation fields](#relation-fields): `author` and `posts`. Relation fields define connections between models at the Prisma level and **do not exist in the database**. These fields are used to generate Prisma Client.
+- The scalar `authorId` field, which is referenced by the `@relation` attribute. This field **does exist in the database** - it is the foreign key that connects `Post` and `User`.
+
+At a Prisma level, a connection between two models is **always** represented by a [relation field](#relation-fields) on **each side** of the relation.
+
+
+
+
+
+
+
+## Relations in the database
+
+### Relational databases
+
+The following entity relationship diagram defines the same one-to-many relation between the `User` and `Post` tables in a **relational database**:
+
+
+
+In SQL, you use a _foreign key_ to create a relation between two tables. Foreign keys are stored on **one side** of the relation. Our example is made up of:
+
+- A foreign key column in the `Post` table named `authorId`.
+- A primary key column in the `User` table named `id`. The `authorId` column in the `Post` table references the `id` column in the `User` table.
+
+In the Prisma schema, the foreign key / primary key relationship is represented by the `@relation` attribute on the `author` field:
+
+```prisma
+author User @relation(fields: [authorId], references: [id])
+```
+
+> **Note**: Relations in the Prisma schema represent relationships that exist between tables in the database. If the relationship does not exist in the database, it does not exist in the Prisma schema.
+
+### MongoDB
+
+For MongoDB, Prisma currently uses a [normalized data model design](https://docs.mongodb.com/manual/core/data-model-design/), which means that documents reference each other by ID in a similar way to relational databases.
+
+The following document represents a `User` (in the `User` collection):
+
+```json
+{ "_id": { "$oid": "60d5922d00581b8f0062e3a8" }, "name": "Ella" }
+```
+
+The following list of `Post` documents (in the `Post` collection) each have a `authorId` field which reference the same user:
+
+```json
+[
+ {
+ "_id": { "$oid": "60d5922e00581b8f0062e3a9" },
+ "title": "How to make sushi",
+ "authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
+ },
+ {
+ "_id": { "$oid": "60d5922e00581b8f0062e3aa" },
+ "title": "How to re-install Windows",
+ "authorId": { "$oid": "60d5922d00581b8f0062e3a8" }
+ }
+]
+```
+
+This data structure represents a one-to-many relation because multiple `Post` documents refer to the same `User` document.
+
+#### `@db.ObjectId` on IDs and relation scalar fields
+
+If your model's ID is an `ObjectId` (represented by a `String` field), you must add `@db.ObjectId` to the model's ID _and_ the relation scalar field on the other side of the relation:
+
+```prisma highlight=3,9;normal
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+## Relations in Prisma Client
+
+Prisma Client is generated from the Prisma schema. The following examples demonstrate how relations manifest when you use Prisma Client to get, create, and update records.
+
+### Create a record and nested records
+
+The following query creates a `User` record and two connected `Post` records:
+
+```ts
+const userAndPosts = await prisma.user.create({
+ data: {
+ posts: {
+ create: [
+ { title: 'Prisma Day 2020' }, // Populates authorId with user's id
+ { title: 'How to write a Prisma schema' }, // Populates authorId with user's id
+ ],
+ },
+ },
+})
+```
+
+In the underlying database, this query:
+
+1. Creates a `User` with an auto-generated `id` (for example, `20`)
+2. Creates two new `Post` records and sets the `authorId` of both records to `20`
+
+### Retrieve a record and include related records
+
+The following query retrieves a `User` by `id` and includes any related `Post` records:
+
+```ts
+const getAuthor = await prisma.user.findUnique({
+ where: {
+ id: "20",
+ },
+ include: {
+| posts: true, // All posts where authorId == 20
+ },
+});
+```
+
+In the underlying database, this query:
+
+1. Retrieves the `User` record with an `id` of `20`
+2. Retrieves all `Post` records with an `authorId` of `20`
+
+### Associate an existing record to another existing record
+
+The following query associates an existing `Post` record with an existing `User` record:
+
+```ts
+const updateAuthor = await prisma.user.update({
+ where: {
+ id: 20,
+ },
+ data: {
+ posts: {
+ connect: {
+ id: 4,
+ },
+ },
+ },
+})
+```
+
+In the underlying database, this query uses a [nested `connect` query](/orm/reference/prisma-client-reference#connect) to link the post with an `id` of 4 to the user with an `id` of 20. The query does this with the following steps:
+
+- The query first looks for the user with an `id` of `20`.
+- The query then sets the `authorID` foreign key to `20`. This links the post with an `id` of `4` to the user with an `id` of `20`.
+
+In this query, the current value of `authorID` does not matter. The query changes `authorID` to `20`, no matter its current value.
+
+## Types of relations
+
+There are three different types (or [cardinalities]()) of relations in Prisma:
+
+- [One-to-one](one-to-one-relations) (also called 1-1 relations)
+- [One-to-many](one-to-many-relations) (also called 1-n relations)
+- [Many-to-many](many-to-many-relations) (also called m-n relations)
+
+The following Prisma schema includes every type of relation:
+
+- one-to-one: `User` ↔ `Profile`
+- one-to-many: `User` ↔ `Post`
+- many-to-many: `Post` ↔ `Category`
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+ profile Profile?
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userId], references: [id])
+ userId Int @unique // relation scalar field (used in the `@relation` attribute above)
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int // relation scalar field (used in the `@relation` attribute above)
+ categories Category[]
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ posts Post[]
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ posts Post[]
+ profile Profile?
+}
+
+model Profile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ user User @relation(fields: [userId], references: [id])
+ userId String @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
+ categories Category[] @relation(fields: [categoryIds], references: [id])
+ categoryIds String[] @db.ObjectId
+}
+
+model Category {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ posts Post[] @relation(fields: [postIds], references: [id])
+ postIds String[] @db.ObjectId
+}
+```
+
+
+
+
+
+
+This schema is the same as the [example data model](/orm/prisma-schema/data-model/models) but has all [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields) removed (except for the required [relation scalars](/orm/prisma-schema/data-model/relations#relation-scalar-fields)) so you can focus on the [relation fields](#relation-fields).
+
+
+
+
+
+This example uses [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations). These relations do not require the `@relation` attribute unless you need to [disambiguate relations](#disambiguating-relations).
+
+
+
+Notice that the syntax is slightly different between relational databases and MongoDB - particularly for [many-to-many relations](many-to-many-relations).
+
+For relational databases, the following entity relationship diagram represents the database that corresponds to the sample Prisma schema:
+
+
+
+For MongoDB, Prisma uses a [normalized data model design](https://docs.mongodb.com/manual/core/data-model-design/), which means that documents reference each other by ID in a similar way to relational databases. See [the MongoDB section](#mongodb) for more details.
+
+### Implicit and explicit many-to-many relations
+
+Many-to-many relations in relational databases can be modelled in two ways:
+
+- [explicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations), where the relation table is represented as an explicit model in your Prisma schema
+- [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations), where Prisma manages the relation table and it does not appear in the Prisma schema.
+
+Implicit many-to-many relations require both models to have a single `@id`. Be aware of the following:
+
+- You cannot use a [multi-field ID](/orm/reference/prisma-schema-reference#id-1)
+- You cannot use a `@unique` in place of an `@id`
+
+To use either of these features, you must set up an explicit many-to-many instead.
+
+The implicit many-to-many relation still manifests in a relation table in the underlying database. However, Prisma manages this relation table.
+
+If you use an implicit many-to-many relation instead of an explicit one, it makes the [Prisma Client API](/orm/prisma-client) simpler (because, for example, you have one fewer level of nesting inside of [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes)).
+
+If you're not using Prisma Migrate but obtain your data model from [introspection](/orm/prisma-schema/introspection), you can still make use of implicit many-to-many relations by following Prisma's [conventions for relation tables](many-to-many-relations#conventions-for-relation-tables-in-implicit-m-n-relations).
+
+## Relation fields
+
+Relation [fields](/orm/prisma-schema/data-model/models#defining-fields) are fields on a Prisma [model](/orm/prisma-schema/data-model/models#defining-models) that do _not_ have a [scalar type](/orm/prisma-schema/data-model/models#scalar-fields). Instead, their type is another model.
+
+Every relation must have exactly two relation fields, one on each model. In the case of one-to-one and one-to-many relations, an additional _relation scalar field_ is required which gets linked by one of the two relation fields in the `@relation` attribute. This relation scalar is the direct representation of the _foreign key_ in the underlying database.
+
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ role Role @default(USER)
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique
+ role Role @default(USER)
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above)
+}
+```
+
+
+
+
+These models have the following fields:
+
+
+
+
+| Model | Field | Relational | Relation field |
+| :----- | :--------- | :--------- | :--------------------------- |
+| `User` | `id` | `Int` | No |
+| | `email` | `String` | No |
+| | `role` | `Role` | No |
+| | `posts` | `Post[]` | **Yes** (Prisma-level) |
+| `Post` | `id` | `Int` | No |
+| | `title` | `String` | No |
+| | `authorId` | `Int` | No (_relation scalar field_) |
+| | `author` | `User` | **Yes** (_annotated_) |
+
+
+
+
+| Model | Field | Relational | Relation field | Notes |
+| :----- | :--------- | :--------- | :--------------------------- | -------------------------------------- |
+| `User` | `id` | `String` | No | Underlying database type is `ObjectId` |
+| | `email` | `String` | No |
+| | `role` | `Role` | No |
+| | `posts` | `Post[]` | **Yes** (Prisma-level) |
+| `Post` | `id` | `String` | No |
+| | `title` | `String` | No |
+| | `authorId` | `String` | No (_relation scalar field_) | Underlying database type is `ObjectId` |
+| | `author` | `User` | **Yes** (_annotated_) |
+
+
+
+
+Both `posts` and `author` are relation fields because their types are not scalar types but other models.
+
+Also note that the annotated relation field `author` needs to link the relation scalar field `authorId` on the `Post` model inside the `@relation` attribute. The relation scalar represents the foreign key in the underlying database.
+
+The other relation field called `posts` is defined purely on a Prisma-level, it doesn't manifest in the database.
+
+### Annotated relation fields
+
+Relations that require one side of the relation to be _annotated_ with the `@relation` attribute are referred to as _annotated relation fields_. This includes:
+
+- one-to-one relations
+- one-to-many relations
+- many-to-many relations for MongoDB only
+
+The side of the relation which is annotated with the `@relation` attribute represents the side that **stores the foreign key in the underlying database**. The "actual" field that represents the foreign key is required on that side of the relation as well, it's called _relation scalar field_, and is referenced inside `@relation` attribute:
+
+
+
+
+```prisma
+author User @relation(fields: [authorId], references: [id])
+authorId Int
+```
+
+
+
+
+```prisma
+author User @relation(fields: [authorId], references: [id])
+authorId String @db.ObjectId
+```
+
+
+
+
+A scalar field _becomes_ a relation scalar field when it's used in the `fields` of a `@relation` attribute.
+
+### Relation scalar fields
+
+
+
+Relation scalar fields are read-only in the generated [Prisma Client API](/orm/prisma-client). If you want to update a relation in your code, you can do so using [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes).
+
+
+
+#### Relation scalar naming conventions
+
+Because a relation scalar field always _belongs_ to a relation field, the following naming convention is common:
+
+- Relation field: `author`
+- Relation scalar field: `authorId` (relation field name + `Id`)
+
+## The `@relation` attribute
+
+The [`@relation`](/orm/reference/prisma-schema-reference#relation) attribute can only be applied to the [relation fields](#relation-fields), not to [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields).
+
+The `@relation` attribute is required when:
+
+- you define a one-to-one or one-to-many relation, it is required on _one side_ of the relation (with the corresponding relation scalar field)
+- you need to disambiguate a relation (that's e.g. the case when you have two relations between the same models)
+- you define a [self-relation](self-relations)
+- you define [a many-to-many relation for MongoDB](many-to-many-relations#mongodb)
+- you need to control how the relation table is represented in the underlying database (e.g. use a specific name for a relation table)
+
+> **Note**: [Implicit many-to-many relations](many-to-many-relations#implicit-many-to-many-relations) in relational databases do not require the `@relation` attribute.
+
+## Disambiguating relations
+
+When you define two relations between the same two models, you need to add the `name` argument in the `@relation` attribute to disambiguate them. As an example for why that's needed, consider the following models:
+
+
+
+
+```prisma no-copy
+// NOTE: This schema is intentionally incorrect. See below for a working solution.
+
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ writtenPosts Post[]
+ pinnedPost Post?
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String?
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ pinnedBy User? @relation(fields: [pinnedById], references: [id])
+ pinnedById Int?
+}
+```
+
+
+
+
+```prisma no-copy
+// NOTE: This schema is intentionally incorrect. See below for a working solution.
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ writtenPosts Post[]
+ pinnedPost Post?
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String?
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ pinnedBy User? @relation(fields: [pinnedById], references: [id])
+ pinnedById String? @db.ObjectId
+}
+```
+
+
+
+
+In that case, the relations are ambiguous, there are four different ways to interpret them:
+
+- `User.writtenPosts` ↔ `Post.author` + `Post.authorId`
+- `User.writtenPosts` ↔ `Post.pinnedBy` + `Post.pinnedById`
+- `User.pinnedPost` ↔ `Post.author` + `Post.authorId`
+- `User.pinnedPost` ↔ `Post.pinnedBy` + `Post.pinnedById`
+
+To disambiguate these relations, you need to annotate the relation fields with the `@relation` attribute and provide the `name` argument. You can set any `name` (except for the empty string `""`), but it must be the same on both sides of the relation:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ writtenPosts Post[] @relation("WrittenPosts")
+ pinnedPost Post? @relation("PinnedPost")
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String?
+ author User @relation("WrittenPosts", fields: [authorId], references: [id])
+ authorId Int
+ pinnedBy User? @relation("PinnedPost", fields: [pinnedById], references: [id])
+ pinnedById Int? @unique
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ writtenPosts Post[] @relation("WrittenPosts")
+ pinnedPost Post? @relation("PinnedPost")
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String?
+ author User @relation("WrittenPosts", fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ pinnedBy User? @relation("PinnedPost", fields: [pinnedById], references: [id])
+ pinnedById String? @unique @db.ObjectId
+}
+```
+
+
+
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/one-to-many.png b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/one-to-many.png
new file mode 100644
index 0000000000..e0f44cd37a
Binary files /dev/null and b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/one-to-many.png differ
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/quick-fix-index.png b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/quick-fix-index.png
new file mode 100644
index 0000000000..c82ed1a7ac
Binary files /dev/null and b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/quick-fix-index.png differ
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/quick-fix-index.snagx b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/quick-fix-index.snagx
new file mode 100644
index 0000000000..c8ab225559
Binary files /dev/null and b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/quick-fix-index.snagx differ
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/relations-intro.png b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/relations-intro.png
new file mode 100644
index 0000000000..47bb895580
Binary files /dev/null and b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/relations-intro.png differ
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/20-relations/sample-schema.png b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/sample-schema.png
new file mode 100644
index 0000000000..c669b19721
Binary files /dev/null and b/docs/200-orm/100-prisma-schema/20-data-model/20-relations/sample-schema.png differ
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/30-indexes.mdx b/docs/200-orm/100-prisma-schema/20-data-model/30-indexes.mdx
new file mode 100644
index 0000000000..6c27d1487f
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/30-indexes.mdx
@@ -0,0 +1,534 @@
+---
+title: 'Indexes'
+metaDescription: 'How to configure index functionality and add full text indexes'
+hidePage: false
+tocDepth: 3
+---
+
+
+
+Prisma allows configuration of database indexes, unique constraints and primary key constraints. This is in General Availability in versions `4.0.0` and later. You can enable this with the `extendedIndexes` Preview feature in versions `3.5.0` and later.
+
+Version `3.6.0` also introduces support for introspection and migration of full text indexes in MySQL and MongoDB through a new `@@fulltext` attribute, available through the `fullTextIndex` Preview feature.
+
+
+
+If you are upgrading from a version earlier than 4.0.0, these changes to index configuration and full text indexes might be **breaking changes** if you have a database that already uses these features. See [Upgrading from previous versions](#upgrading-from-previous-versions) for more information on how to upgrade.
+
+
+
+
+
+## Index configuration
+
+You can configure indexes, unique constraints, and primary key constraints with the following attribute arguments:
+
+- The [`length` argument](#configuring-the-length-of-indexes-with-length-mysql) allows you to specify a maximum length for the subpart of the value to be indexed on `String` and `Bytes` types
+
+ - Available on the `@id`, `@@id`, `@unique`, `@@unique` and `@@index` attributes
+ - MySQL only
+
+- The [`sort` argument](#configuring-the-index-sort-order-with-sort) allows you to specify the order that the entries of the constraint or index are stored in the database
+
+ - Available on the `@unique`, `@@unique` and `@@index` attributes in all databases, and on the `@id` and `@@id` attributes in SQL Server
+
+- The [`type` argument](#configuring-the-access-type-of-indexes-with-type-postgresql) allows you to support index access methods other than PostgreSQL's default `BTree` access method
+
+ - Available on the `@@index` attribute
+ - PostgreSQL only
+ - Supported index access methods: `Hash`, `Gist`, `Gin`, `SpGist` and `Brin`
+
+- The [`clustered` argument](#configuring-if-indexes-are-clustered-or-non-clustered-with-clustered-sql-server) allows you to configure whether a constraint or index is clustered or non-clustered
+ - Available on the `@id`, `@@id`, `@unique`, `@@unique` and `@@index` attributes
+ - SQL Server only
+
+See the linked sections for details of which version each feature was first introduced in.
+
+### Configuring the length of indexes with `length` (MySQL)
+
+The `length` argument is specific to MySQL and allows you to define indexes and constraints on columns of `String` and `Byte` types. For these types, MySQL requires you to specify a maximum length for the subpart of the value to be indexed in cases where the full value would exceed MySQL's limits for index sizes. See [the MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html) for more details.
+
+The `length` argument is available on the `@id`, `@@id`, `@unique`, `@@unique` and `@@index` attributes. It is generally available in versions 4.0.0 and later, and available as part of the `extendedIndexes` preview feature in versions 3.5.0 and later.
+
+As an example, the following data model declares an `id` field with a maximum length of 3000 characters:
+
+```prisma file=schema.prisma
+model Id {
+ id String @id @db.VarChar(3000)
+}
+```
+
+This is not valid in MySQL because it exceeds MySQL's index storage limit and therefore Prisma rejects the data model. The generated SQL would be rejected by the database.
+
+```sql
+CREATE TABLE `Id` (
+ `id` VARCHAR(3000) PRIMARY KEY
+)
+```
+
+The `length` argument allows you to specify that only a subpart of the `id` value represents the primary key. In the example below, the first 100 characters are used:
+
+```prisma file=schema.prisma
+model Id {
+ id String @id(length: 100) @db.VarChar(3000)
+}
+```
+
+Prisma Migrate is able to create constraints and indexes with the `length` argument if specified in your data model. This means that you can create indexes and constraints on values of Prisma type `Byte` and `String`. If you don't specify the argument the index is treated as covering the full value as before.
+
+Introspection will fetch these limits where they are present in your existing database. This allows Prisma to support indexes and constraints that were previously suppressed and results in better support of existing MySQL databases that are making use of this feature.
+
+The `length` argument can also be used on compound primary keys, using the `@@id` attribute, as in the example below:
+
+```prisma file=schema.prisma
+model CompoundId {
+ id_1 String @db.VarChar(3000)
+ id_2 String @db.VarChar(3000)
+
+ @@id([id_1(length: 100), id_2(length: 10)])
+}
+```
+
+A similar syntax can be used for the `@@unique` and `@@index` attributes.
+
+### Configuring the index sort order with `sort`
+
+The `sort` argument is available for all databases supported by Prisma. It allows you to specify the order that the entries of the index or constraint are stored in the database. This can have an effect on whether the database is able to use an index for specific queries.
+
+The `sort` argument is available for all databases on `@unique`, `@@unique` and `@@index`. Additionally, SQL Server also allows it on `@id` and `@@id`. It is generally available in versions 4.0.0 and later, and available as part of the `extendedIndexes` preview feature in versions 3.5.0 and later.
+
+As an example, the following table
+
+```sql
+CREATE TABLE `Unique` (
+ `unique` INT,
+ CONSTRAINT `Unique_unique_key` UNIQUE (`unique` DESC)
+)
+```
+
+is now introspected as
+
+```prisma file=schema.prisma
+model Unique {
+ unique Int @unique(sort: Desc)
+}
+```
+
+The `sort` argument can also be used on compound indexes:
+
+```prisma file=schema.prisma
+model CompoundUnique {
+ unique_1 Int
+ unique_2 Int
+
+ @@unique([unique_1(sort: Desc), unique_2])
+}
+```
+
+### Example: using `sort` and `length` together
+
+The following example demonstrates the use of the `sort` and `length` arguments to configure indexes and constraints for a `Post` model:
+
+```prisma file=schema.prisma
+model Post {
+ title String @db.VarChar(300)
+ abstract String @db.VarChar(3000)
+ slug String @unique(sort: Desc, length: 42) @db.VarChar(3000)
+ author String
+ created_at DateTime
+
+ @@id([title(length: 100, sort: Desc), abstract(length: 10)])
+ @@index([author, created_at(sort: Desc)])
+}
+```
+
+### Configuring the access type of indexes with `type` (PostgreSQL)
+
+The `type` argument is available for configuring the index type in PostgreSQL with the `@@index` attribute. The index access methods available are `Hash`, `Gist`, `Gin`, `SpGist` and `Brin`, as well as the default `BTree` index access method. The `type` argument is generally available in versions 4.0.0 and later. The `Hash` index access method is available as part of the `extendedIndexes` preview feature in versions 3.6.0 and later, and the `Gist`, `Gin`, `SpGist` and `Brin` index access methods are available in preview in versions 3.14.0 and later.
+
+#### Hash
+
+The `Hash` type will store the index data in a format that is much faster to search and insert, and that will use less disk space. However, only the `=` and `<>` comparisons can use the index, so other comparison operators such as `<` and `>` will be much slower with `Hash` than when using the default `BTree` type.
+
+As an example, the following model adds an index with a `type` of `Hash` to the `value` field:
+
+```prisma file=schema.prisma
+model Example {
+ id Int @id
+ value Int
+
+ @@index([value], type: Hash)
+}
+```
+
+This translates to the following SQL commands:
+
+```sql
+CREATE TABLE "Example" (
+ id INT PRIMARY KEY,
+ value INT NOT NULL
+);
+
+CREATE INDEX "Example_value_idx" ON "Example" USING HASH (value);
+```
+
+#### Generalized Inverted Index (GIN)
+
+The GIN index stores composite values, such as arrays or `JsonB` data. This is useful for speeding up querying whether one object is part of another object. It is commonly used for full-text searches.
+
+An indexed field can define the operator class, which defines the operators handled by the index.
+
+
+
+Indexes using a function (such as `to_tsvector`) to determine the indexed value are not yet supported by Prisma. Indexes defined in this way will not be visible with `prisma db pull`.
+
+
+
+As an example, the following model adds a `Gin` index to the `value` field, with `JsonbPathOps` as the class of operators allowed to use the index:
+
+```prisma file=schema.prisma
+model Example {
+ id Int @id
+ value Json
+ // ^ field type matching the operator class
+ // ^ operator class ^ index type
+
+ @@index([value(ops: JsonbPathOps)], type: Gin)
+}
+```
+
+This translates to the following SQL commands:
+
+```sql
+CREATE TABLE "Example" (
+ id INT PRIMARY KEY,
+ value JSONB NOT NULL
+);
+
+CREATE INDEX "Example_value_idx" ON "Example" USING GIN (value jsonb_path_ops);
+```
+
+As part of the `JsonbPathOps` the `@>` operator is handled by the index, speeding up queries such as `value @> '{"foo": 2}'`.
+
+##### Supported Operator Classes for GIN
+
+Prisma generally supports operator classes provided by PostgreSQL in versions 10 and later. If the operator class requires the field type to be of a type Prisma does not yet support, using the `raw` function with a string input allows you to use these operator classes without validation.
+
+The default operator class (marked with ✅) can be omitted from the index definition.
+
+| Operator class | Allowed field type (native types) | Default | Other |
+| -------------- | --------------------------------- | ------- | ----------------------------- |
+| `ArrayOps` | Any array | ✅ | Also available in CockroachDB |
+| `JsonbOps` | `Json` (`@db.JsonB`) | ✅ | Also available in CockroachDB |
+| `JsonbPathOps` | `Json` (`@db.JsonB`) | | |
+| `raw("other")` | | | |
+
+Read more about built-in operator classes in the [official PostgreSQL documentation](https://www.postgresql.org/docs/14/gin-builtin-opclasses.html).
+
+##### CockroachDB
+
+GIN and BTree are the only index types supported by CockroachDB. The operator classes marked to work with CockroachDB are the only ones allowed on that database and supported by Prisma. The operator class cannot be defined in the Prisma Schema Language: the `ops` argument is not necessary or allowed on CockroachDB.
+
+#### Generalized Search Tree (GiST)
+
+The GiST index type is used for implementing indexing schemes for user-defined types. By default there are not many direct uses for GiST indexes, but for example the B-Tree index type is built using a GiST index.
+
+As an example, the following model adds a `Gist` index to the `value` field with `InetOps` as the operators that will be using the index:
+
+```prisma file=schema.prisma
+model Example {
+ id Int @id
+ value String @db.Inet
+ // ^ native type matching the operator class
+ // ^ index type
+ // ^ operator class
+
+ @@index([value(ops: InetOps)], type: Gist)
+}
+```
+
+This translates to the following SQL commands:
+
+```sql
+CREATE TABLE "Example" (
+ id INT PRIMARY KEY,
+ value INET NOT NULL
+);
+
+CREATE INDEX "Example_value_idx" ON "Example" USING GIST (value inet_ops);
+```
+
+Queries comparing IP addresses, such as `value > '10.0.0.2'`, will use the index.
+
+##### Supported Operator Classes for GiST
+
+Prisma generally supports operator classes provided by PostgreSQL in versions 10 and later. If the operator class requires the field type to be of a type Prisma does not yet support, using the `raw` function with a string input allows you to use these operator classes without validation.
+
+| Operator class | Allowed field type (allowed native types) |
+| -------------- | ----------------------------------------- |
+| `InetOps` | `String` (`@db.Inet`) |
+| `raw("other")` | |
+
+Read more about built-in operator classes in the [official PostgreSQL documentation](https://www.postgresql.org/docs/14/gist-builtin-opclasses.html).
+
+#### Space-Partitioned GiST (SP-GiST)
+
+The SP-GiST index is a good choice for many different non-balanced data structures. If the query matches the partitioning rule, it can be very fast.
+
+As with GiST, SP-GiST is important as a building block for user-defined types, allowing implementation of custom search operators directly with the database.
+
+As an example, the following model adds a `SpGist` index to the `value` field with `TextOps` as the operators using the index:
+
+
+```prisma file=schema.prisma
+model Example {
+ id Int @id
+ value String
+ // ^ field type matching the operator class
+
+ @@index([value], type: SpGist)
+ // ^ index type
+ // ^ using the default ops: TextOps
+}
+```
+
+
+This translates to the following SQL commands:
+
+```sql
+CREATE TABLE "Example" (
+ id INT PRIMARY KEY,
+ value TEXT NOT NULL
+);
+
+CREATE INDEX "Example_value_idx" ON "Example" USING SPGIST (value);
+```
+
+Queries such as `value LIKE 'something%'` will be sped up by the index.
+
+##### Supported Operator Classes for SP-GiST
+
+Prisma generally supports operator classes provided by PostgreSQL in versions 10 and later. If the operator class requires the field type to be of a type Prisma does not yet support, using the `raw` function with a string input allows you to use these operator classes without validation.
+
+The default operator class (marked with ✅) can be omitted from the index definition.
+
+| Operator class | Allowed field type (native types) | Default | Supported PostgreSQL versions |
+| -------------- | ------------------------------------ | ------- | ----------------------------- |
+| `InetOps` | `String` (`@db.Inet`) | ✅ | 10+ |
+| `TextOps` | `String` (`@db.Text`, `@db.VarChar`) | ✅ | |
+| `raw("other")` | | | |
+
+Read more about built-in operator classes from [official PostgreSQL documentation](https://www.postgresql.org/docs/14/spgist-builtin-opclasses.html).
+
+#### Block Range Index (BRIN)
+
+The BRIN index type is useful if you have lots of data that does not change after it is inserted, such as date and time values. If your data is a good fit for the index, it can store large datasets in a minimal space.
+
+As an example, the following model adds a `Brin` index to the `value` field with `Int4BloomOps` as the operators that will be using the index:
+
+```prisma file=schema.prisma
+model Example {
+ id Int @id
+ value Int
+ // ^ field type matching the operator class
+ // ^ operator class ^ index type
+
+ @@index([value(ops: Int4BloomOps)], type: Brin)
+}
+```
+
+This translates to the following SQL commands:
+
+```sql
+CREATE TABLE "Example" (
+ id INT PRIMARY KEY,
+ value INT4 NOT NULL
+);
+
+CREATE INDEX "Example_value_idx" ON "Example" USING BRIN (value int4_bloom_ops);
+```
+
+Queries like `value = 2` will now use the index, which uses a fraction of the space used by the `BTree` or `Hash` indexes.
+
+##### Supported Operator Classes for BRIN
+
+Prisma generally supports operator classes provided by PostgreSQL in versions 10 and later, and some supported operators are only available from PostgreSQL versions 14 and later. If the operator class requires the field type to be of a type Prisma does not yet support, using the `raw` function with a string input allows you to use these operator classes without validation.
+
+The default operator class (marked with ✅) can be omitted from the index definition.
+
+| Operator class | Allowed field type (native types) | Default | Supported PostgreSQL versions |
+| --------------------------- | ------------------------------------ | ------- | ----------------------------- |
+| `BitMinMaxOps` | `String` (`@db.Bit`) | ✅ | |
+| `VarBitMinMaxOps` | `String` (`@db.VarBit`) | ✅ | |
+| `BpcharBloomOps` | `String` (`@db.Char`) | | 14+ |
+| `BpcharMinMaxOps` | `String` (`@db.Char`) | ✅ | |
+| `ByteaBloomOps` | `Bytes` (`@db.Bytea`) | | 14+ |
+| `ByteaMinMaxOps` | `Bytes` (`@db.Bytea`) | ✅ | |
+| `DateBloomOps` | `DateTime` (`@db.Date`) | | 14+ |
+| `DateMinMaxOps` | `DateTime` (`@db.Date`) | ✅ | |
+| `DateMinMaxMultiOps` | `DateTime` (`@db.Date`) | | 14+ |
+| `Float4BloomOps` | `Float` (`@db.Real`) | | 14+ |
+| `Float4MinMaxOps` | `Float` (`@db.Real`) | ✅ | |
+| `Float4MinMaxMultiOps` | `Float` (`@db.Real`) | | 14+ |
+| `Float8BloomOps` | `Float` (`@db.DoublePrecision`) | | 14+ |
+| `Float8MinMaxOps` | `Float` (`@db.DoublePrecision`) | ✅ | |
+| `Float8MinMaxMultiOps` | `Float` (`@db.DoublePrecision`) | | 14+ |
+| `InetInclusionOps` | `String` (`@db.Inet`) | ✅ | 14+ |
+| `InetBloomOps` | `String` (`@db.Inet`) | | 14+ |
+| `InetMinMaxOps` | `String` (`@db.Inet`) | | |
+| `InetMinMaxMultiOps` | `String` (`@db.Inet`) | | 14+ |
+| `Int2BloomOps` | `Int` (`@db.SmallInt`) | | 14+ |
+| `Int2MinMaxOps` | `Int` (`@db.SmallInt`) | ✅ | |
+| `Int2MinMaxMultiOps` | `Int` (`@db.SmallInt`) | | 14+ |
+| `Int4BloomOps` | `Int` (`@db.Integer`) | | 14+ |
+| `Int4MinMaxOps` | `Int` (`@db.Integer`) | ✅ | |
+| `Int4MinMaxMultiOps` | `Int` (`@db.Integer`) | | 14+ |
+| `Int8BloomOps` | `BigInt` (`@db.BigInt`) | | 14+ |
+| `Int8MinMaxOps` | `BigInt` (`@db.BigInt`) | ✅ | |
+| `Int8MinMaxMultiOps` | `BigInt` (`@db.BigInt`) | | 14+ |
+| `NumericBloomOps` | `Decimal` (`@db.Decimal`) | | 14+ |
+| `NumericMinMaxOps` | `Decimal` (`@db.Decimal`) | ✅ | |
+| `NumericMinMaxMultiOps` | `Decimal` (`@db.Decimal`) | | 14+ |
+| `OidBloomOps` | `Int` (`@db.Oid`) | | 14+ |
+| `OidMinMaxOps` | `Int` (`@db.Oid`) | ✅ | |
+| `OidMinMaxMultiOps` | `Int` (`@db.Oid`) | | 14+ |
+| `TextBloomOps` | `String` (`@db.Text`, `@db.VarChar`) | | 14+ |
+| `TextMinMaxOps` | `String` (`@db.Text`, `@db.VarChar`) | ✅ | |
+| `TextMinMaxMultiOps` | `String` (`@db.Text`, `@db.VarChar`) | | 14+ |
+| `TimestampBloomOps` | `DateTime` (`@db.Timestamp`) | | 14+ |
+| `TimestampMinMaxOps` | `DateTime` (`@db.Timestamp`) | ✅ | |
+| `TimestampMinMaxMultiOps` | `DateTime` (`@db.Timestamp`) | | 14+ |
+| `TimestampTzBloomOps` | `DateTime` (`@db.Timestamptz`) | | 14+ |
+| `TimestampTzMinMaxOps` | `DateTime` (`@db.Timestamptz`) | ✅ | |
+| `TimestampTzMinMaxMultiOps` | `DateTime` (`@db.Timestamptz`) | | 14+ |
+| `TimeBloomOps` | `DateTime` (`@db.Time`) | | 14+ |
+| `TimeMinMaxOps` | `DateTime` (`@db.Time`) | ✅ | |
+| `TimeMinMaxMultiOps` | `DateTime` (`@db.Time`) | | 14+ |
+| `TimeTzBloomOps` | `DateTime` (`@db.Timetz`) | | 14+ |
+| `TimeTzMinMaxOps` | `DateTime` (`@db.Timetz`) | ✅ | |
+| `TimeTzMinMaxMultiOps` | `DateTime` (`@db.Timetz`) | | 14+ |
+| `UuidBloomOps` | `String` (`@db.Uuid`) | | 14+ |
+| `UuidMinMaxOps` | `String` (`@db.Uuid`) | ✅ | |
+| `UuidMinMaxMultiOps` | `String` (`@db.Uuid`) | | 14+ |
+| `raw("other")` | | | |
+
+Read more about built-in operator classes in the [official PostgreSQL documentation](https://www.postgresql.org/docs/14/brin-builtin-opclasses.html).
+
+### Configuring if indexes are clustered or non-clustered with `clustered` (SQL Server)
+
+The `clustered` argument is available to configure (non)clustered indexes in SQL Server. It can be used on the `@id`, `@@id`, `@unique`, `@@unique` and `@@index` attributes. It is generally available in versions 4.0.0 and later, and available as part of the `extendedIndexes` preview feature in versions 3.13.0 and later.
+
+As an example, the following model configures the `@id` to be non-clustered (instead of the clustered default):
+
+```prisma file=schema.prisma
+model Example {
+ id Int @id(clustered: false)
+ value Int
+}
+```
+
+This translates to the following SQL commands:
+
+```sql
+CREATE TABLE [Example] (
+ id INT NOT NULL,
+ value INT,
+ CONSTRAINT [Example_pkey] PRIMARY KEY NONCLUSTERED (id)
+)
+```
+
+The default value of `clustered` for each attribute is as follows:
+
+| Attribute | Value |
+| ---------- | ------- |
+| `@id` | `true` |
+| `@@id` | `true` |
+| `@unique` | `false` |
+| `@@unique` | `false` |
+| `@@index` | `false` |
+
+A table can have at most one clustered index.
+
+### Upgrading from previous versions
+
+
+
+These index configuration changes can be **breaking changes** when activating the functionality for certain, existing Prisma schemas for existing databases. After enabling the preview features required to use them, run `prisma db pull` to introspect the existing database to update your Prisma schema before using Prisma Migrate again.
+
+
+
+A breaking change can occur in the following situations:
+
+- **Existing sort constraints and indexes:** earlier versions of Prisma will assume that the desired sort order is _ascending_ if no order is specified explicitly. This means that this is a breaking change if you have existing constraints or indexes that are using descending sort order and migrate your database without first specifying this in your data model.
+- **Existing length constraints and indexes:** in earlier versions of Prisma, indexes and constraints that were length constrained in MySQL could not be represented in the Prisma schema. Therefore `prisma db pull` was not fetching these and you could not manually specify them. When you ran `prisma db push` or `prisma migrate dev` they were ignored if already present in your database. Since you are now able to specify these, migrate commands will now drop them if they are missing from your data model but present in the database.
+- **Existing indexes other than `BTree` (PostgreSQL):** earlier versions of Prisma only supported the default `BTree` index type. Other supported indexes (`Hash`, `Gist`, `Gin`, `SpGist` and `Brin`) need to be added before migrating your database.
+- **Existing (non-)clustered indexes (SQL Server):** earlier versions of Prisma did not support configuring an index as clustered or non-clustered. For indexes that do not use the default, these need to be added before migrating your database.
+
+In each of the cases above unwanted changes to your database can be prevented by properly specifying these properties in your data model where necessary. **The easiest way to do this is to use `prisma db pull` to retrieve any existing constraints or configuration.** Alternatively, you could also add these arguments manually. This should be done before using `prisma db push` or `prisma migrate dev` the first time after the upgrade.
+
+## Full text indexes (MySQL and MongoDB)
+
+The `fullTextIndex` preview feature provides support for introspection and migration of full text indexes in MySQL and MongoDB in version 3.6.0 and later. This can be configured using the `@@fulltext` attribute. Existing full text indexes in the database are added to your Prisma schema after introspecting with `db pull`, and new full text indexes added in the Prisma schema are created in the database when using Prisma Migrate. This also prevents validation errors in some database schemas that were not working before.
+
+
+
+For now we do not enable the full text search commands in Prisma Client for MongoDB; the progress can be followed in the [MongoDB](https://github.com/prisma/prisma/issues/9413) issue.
+
+
+
+### Enabling the `fullTextIndex` preview feature
+
+To enable the `fullTextIndex` preview feature, add the `fullTextIndex` feature flag to the `generator` block of the `schema.prisma` file:
+
+```prisma file=schema.prisma
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["fullTextIndex"]
+}
+```
+
+### Examples
+
+The following example demonstrates adding a `@@fulltext` index to the `title` and `content` fields of a `Post` model:
+
+```prisma file=schema.prisma
+model Post {
+ id Int @id
+ title String @db.VarChar(255)
+ content String @db.Text
+
+ @@fulltext([title, content])
+}
+```
+
+On MongoDB, you can use the `@@fulltext` index attribute (via the `fullTextIndex` preview feature) with the `sort` argument to add fields to your full-text index in ascending or descending order. The following example adds a `@@fulltext` index to the `title` and `content` fields of the `Post` model, and sorts the `title` field in descending order:
+
+```prisma file=schema.prisma
+generator js {
+ provider = "prisma-client-js"
+ previewFeatures = ["fullTextIndex"]
+}
+
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+model Post {
+ id String @id @map("_id") @db.ObjectId
+ title String
+ content String
+
+ @@fulltext([title(sort: Desc), content])
+}
+```
+
+### Upgrading from previous versions
+
+
+
+This can be a **breaking change** when activating the functionality for certain, existing Prisma schemas for existing databases. After enabling the preview features required to use them, run `prisma db pull` to introspect the existing database to update your Prisma schema before using Prisma Migrate again.
+
+
+
+Earlier versions of Prisma converted full text indexes using the `@@index` attribute rather than the `@@fulltext` attribute. After enabling the `fullTextIndex` preview feature, run `prisma db pull` to convert these indexes to `@@fulltext` before migrating again with Prisma Migrate. If you do not do this, the existing indexes will be dropped instead and normal indexes will be created in their place.
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/40-views.mdx b/docs/200-orm/100-prisma-schema/20-data-model/40-views.mdx
new file mode 100644
index 0000000000..7cd1fe2083
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/40-views.mdx
@@ -0,0 +1,369 @@
+---
+title: 'Views'
+metaTitle: 'How to include views in your Prisma schema'
+metaDescription: 'How to include views in your Prisma schema'
+hidePage: false
+preview: true
+tocDepth: 3
+---
+
+
+
+
+
+Support for views is currently a very early [Preview](/orm/more/releases#preview) feature. You can add a view to your Prisma schema with the `view` keyword or introspect the views in your database schema with `db pull`. You cannot yet apply views in your schema to your database with Prisma Migrate and `db push` unless the changes are added manually to your migration file using the `--create-only` flag.
For updates on progress with this feature, follow [our GitHub issue](https://github.com/prisma/prisma/issues/17335).
+
+
+
+Database views allow you to name and store queries. In relational databases, views are [stored SQL queries](https://www.postgresql.org/docs/current/sql-createview.html) that might include columns in multiple tables, or calculated values such as aggregates. In MongoDB, views are queryable objects where the contents are defined by an [aggregation pipeline](https://www.mongodb.com/docs/manual/core/aggregation-pipeline) on other collections.
+
+The `views` preview feature allows you to represent views in your Prisma schema with the `view` keyword. To use views in Prisma, follow these steps:
+
+- [Enable the `views` preview feature](#enable-the-views-preview-feature)
+- [Create a view in the underlying database](#create-a-view-in-the-underlying-database), either directly or as a [manual addition to a Prisma Migrate migration file](#use-views-with-prisma-migrate-and-db-push), or use an existing view
+- [Represent the view in your Prisma schema](#add-views-to-your-prisma-schema)
+- [Query the view in Prisma Client](#query-views-in-prisma-client)
+
+
+
+## Enable the `views` preview feature
+
+Support for views is currently in an early preview. To enable the `views` preview feature, add the `views` feature flag to the `previewFeatures` field of the `generator` block in your Prisma schema file:
+
+```prisma file=schema.prisma highlight=3;add
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["views"]
+}
+```
+
+Please leave feedback about this preview feature in our dedicated [preview feature feedback issue for `views`](https://github.com/prisma/prisma/issues/17335).
+
+## Create a view in the underlying database
+
+Currently, you cannot apply views that you define in your Prisma schema to your database with Prisma Migrate and `db push`. Instead, you must first create the view in the underlying database, either manually or [as part of a migration](#use-views-with-prisma-migrate-and-db-push).
+
+For example, take the following Prisma schema with a `User` model and a related `Profile` model:
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ profile Profile?
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ bio String
+ user User @relation(fields: [userId], references: [id])
+ userId Int @unique
+}
+```
+
+
+
+
+```prisma
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique
+ name String?
+ profile Profile?
+}
+
+model Profile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ bio String
+ User User @relation(fields: [userId], references: [id])
+ userId String @unique @db.ObjectId
+}
+```
+
+
+
+
+Next, take a `UserInfo` view in the underlying database that combines the `email` and `name` fields from the `User` model and the `bio` field from the `Profile` model.
+
+For a relational database, the SQL statement to create this view is:
+
+```sql
+CREATE VIEW "UserInfo" AS
+ SELECT u.id, email, name, bio
+ FROM "User" u
+ LEFT JOIN "Profile" p ON u.id = p."userId";
+```
+
+For MongoDB, you can [create a view](https://www.mongodb.com/docs/manual/core/views/join-collections-with-view/) with the following command:
+
+```ts
+db.createView('UserInfo', 'User', [
+ {
+ $lookup: {
+ from: 'Profile',
+ localField: '_id',
+ foreignField: 'userId',
+ as: 'ProfileData',
+ },
+ },
+ {
+ $project: {
+ _id: 1,
+ email: 1,
+ name: 1,
+ bio: '$ProfileData.bio',
+ },
+ },
+ { $unwind: '$bio' },
+])
+```
+
+## Use views with Prisma Migrate and `db push`
+
+If you apply changes to your Prisma schema with Prisma Migrate or `db push`, Prisma does not create or run any SQL related to views.
+
+To include views in a migration, run `migrate dev --create-only` and then manually add the SQL for views to your migration file. Alternatively, you can create views manually in the database.
+
+## Add views to your Prisma schema
+
+To add a view to your Prisma schema, use the `view` keyword.
+
+You can represent the `UserInfo` view from the example above in your Prisma schema as follows:
+
+
+
+
+
+
+```prisma
+view UserInfo {
+ id Int @unique
+ email String
+ name String
+ bio String
+}
+```
+
+
+
+
+```prisma
+view UserInfo {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String
+ name String
+ bio String
+}
+```
+
+
+
+
+
+
+### Write by hand
+
+A `view` block is comprised of two main pieces:
+
+- The `view` block definition
+- The view's field definitions
+
+These two pieces allow you to define the name of your view in the generated Prisma Client and the columns present in your view's query results.
+
+#### Define a `view` block
+
+To define the `UserInfo` view from the example above, begin by using the `view` keyword to define a `view` block in your schema named `UserInfo`:
+
+
+```prisma
+view UserInfo {
+ // Fields
+}
+```
+
+#### Define fields
+
+The properties of a view are called _fields_, which consist of:
+
+- A field name
+- A field type
+
+The fields of the `UserInfo` example view can be defined as follows:
+
+
+
+
+
+```prisma highlight=2-5;normal
+view UserInfo {
+ id Int @unique
+ email String
+ name String
+ bio String
+}
+```
+
+
+
+
+
+```prisma highlight=2-5;normal
+view UserInfo {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String
+ name String
+ bio String
+}
+```
+
+
+
+
+Each _field_ of a `view` block represents a column in the query results of the view in the underlying database.
+
+### Use introspection
+
+
+ Currently only available for PostgreSQL, MySQL, SQL Server and CockroachDB.
+
+
+If you have an existing view or views defined in your database, [introspection](/orm/prisma-schema/introspection) will automatically generate `view` blocks in your Prisma schema that represent those views.
+
+Assuming the example `UserInfo` view exists in your underlying database, running the following command will generate a `view` block in your Prisma schema representing that view:
+
+```terminal copy
+npx prisma db pull
+```
+
+The resulting `view` block will be defined as follows:
+
+
+```prisma
+/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
+view UserInfo {
+ id Int?
+ email String?
+ name String?
+ bio String?
+
+ @@ignore
+}
+```
+
+The `view` block is generated initially with a `@@ignore` attribute because [there is no unique identifier defined](#unique-identifier) (which is currently a [limitation](#unique-identifier) of the views preview feature).
+
+
+
+Please note for now `db pull` will only introspect views in your schema when using PostgreSQL, MySQL, SQL Server or CockroachDB. Support for this workflow will be extended to other database providers.
+
+
+
+#### Adding a unique identifier to an introspected view
+
+To be able to use the introspected view in Prisma Client, you will need to select and define one or multiple of the fields as the unique identifier.
+
+In the above view's case, the `id` column refers to a uniquely identifiable field in the underlying `User` table so that field can also be used as the uniquely identifiable field in the `view` block.
+
+In order to make this `view` block valid you will need to:
+
+- Remove the _optional_ flag `?` from the `id` field
+- Add the `@unique` attribute to the `id` field
+- Remove the `@@ignore` attribute
+- Remove the comment Prisma generated warning about an invalid view
+
+
+```prisma highlight=4;add|1,3,8,9;delete
+/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
+view UserInfo {
+ id Int?
+ id Int @unique
+ email String?
+ name String?
+ bio String?
+
+ @@ignore
+}
+```
+
+When re-introspecting your database, any custom changes to your view definitions will be preserved.
+
+#### The `views` directory
+
+Introspection of a database with one or more existing views will also create a new `views` directory within your `prisma` directory (starting with Prisma version 4.12.0). This directory will contain a subdirectory named after your database's schema which contains a `.sql` file for each view that was introspected in that schema. Each file will be named after an individual view and will contain the query the related view defines.
+
+For example, after introspecting a database with the default `public` schema using the model used above you will find a `prisma/views/public/UserInfo.sql` file was created with the following contents:
+
+```sql
+SELECT
+ u.id,
+ u.email,
+ u.name,
+ p.bio
+FROM
+ (
+ "User" u
+ LEFT JOIN "Profile" p ON ((u.id = p."userId"))
+ );
+```
+
+### Limitations
+
+#### Unique Identifier
+
+Currently, Prisma treats views in the same way as models. This means that a view needs to have at least one _unique identifier_, which can be represented by any of the following:
+
+- A unique constraint denoted with [`@unique`](/orm/prisma-schema/data-model/models#defining-a-unique-field)
+- A composite unique constraint denoted with [`@@unique`](/orm/prisma-schema/data-model/models#defining-a-unique-field)
+- An [`@id`](/orm/prisma-schema/data-model/models#defining-an-id-field) field
+- A composite identifier denoted with [`@@id`](/orm/prisma-schema/data-model/models#composite-ids)
+
+In relational databases, a view's unique identifier can be defined as a `@unique` attribute on one field, or a `@@unique` attribute on multiple fields. When possible, it is preferable to use a `@unique` or `@@unique` constraint over an `@id` or `@@id` field.
+
+In MongoDB, however, the unique identifier must be an `@id` attribute that maps to the `_id` field in the underlying database with `@map("_id")`.
+
+In the example above, the `id` field has a `@unique` attribute. If another column in the underlying `User` table had been defined as uniquely identifiable and made available in the view's query results, that column could have been used as the unique identifier instead.
+
+#### Introspection
+
+Currently, introspection of views is only available for PostgreSQL, MySQL, SQL Server and CockroachDB. If you are using another database provider, your views must be added manually.
+
+This is a temporary limitation and support for introspection will be extended to the other supported datasource providers.
+
+## Query views in Prisma Client
+
+You can query views in Prisma Client in the same way that you query models. For example, the following query finds all users with a `name` of `'Alice'` in the `UserInfo` view defined above.
+
+```ts
+const userinfo = await prisma.userInfo.findMany({
+ where: {
+ name: 'Alice',
+ },
+})
+```
+
+Currently, Prisma Client allows you to update a view if the underlying database allows it, without any additional validation.
+
+## Special types of views
+
+This section describes how to use Prisma with updatable and materialized views in your database.
+
+### Updatable views
+
+Some databases support updatable views (e.g. [PostgreSQL](https://www.postgresql.org/docs/current/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS), [MySQL](https://dev.mysql.com/doc/refman/8.0/en/view-updatability.html) and [SQL Server](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql?view=sql-server-ver16#updatable-views)). Updatable views allow you to create, update or delete entries.
+
+Currently Prisma treats all `view`s as updatable views. If the underlying database supports this functionality for the view, the operation should succeed. If the view is not marked as updatable, the database will return an error, and Prisma Client will then throw this error.
+
+In the future, Prisma Client might support marking individual views as updatable or not updatable. Please comment on our [`views` feedback issue](https://github.com/prisma/prisma/issues/17335) with your use case.
+
+### Materialized views
+
+Some databases support materialized views, e.g. [PostgreSQL](https://www.postgresql.org/docs/current/rules-materializedviews.html), [CockroachDB](https://www.cockroachlabs.com/docs/stable/views.html#materialized-views), [MongoDB](https://www.mongodb.com/docs/manual/core/materialized-views/), and [SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/views/create-indexed-views?view=sql-server-ver16) (where they're called "indexed views").
+
+Materialized views persist the result of the view query for faster access and only update it on demand.
+
+Currently Prisma has no understanding of materialized views, but when you [manually create a view](#create-a-view-in-the-underlying-database) you can also create a materialized view by using the corresponding command in the underlying database. You can then use Prisma's [raw query functionality](/orm/prisma-client/queries/raw-database-access) to execute the command to refresh the view manually.
+
+In the future Prisma Client might support marking individual views as materialized and add a Prisma Client method to refresh the materialized view. Please comment on our [`views` feedback issue](https://github.com/prisma/prisma/issues/17335) with your use case.
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/50-database-mapping.mdx b/docs/200-orm/100-prisma-schema/20-data-model/50-database-mapping.mdx
new file mode 100644
index 0000000000..a7f5471434
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/50-database-mapping.mdx
@@ -0,0 +1,226 @@
+---
+title: 'Database mapping'
+metaTitle: 'Database mapping'
+metaDescription: ''
+tocDepth: 3
+---
+
+
+
+The [Prisma schema](/orm/prisma-schema) includes mechanisms that allow you to define names of certain database objects. You can:
+
+- [Map model and field names to different collection/table and field/column names](#mapping-collectiontable-and-fieldcolumn-names)
+- [Define constraint and index names](#constraint-and-index-names)
+
+
+
+## Mapping collection/table and field/column names
+
+Sometimes the names used to describe entities in your database might not match the names you would prefer in your generated API. Mapping names in the Prisma schema allows you to influence the naming in your Client API without having to change the underlying database names.
+
+A common approach for naming tables/collections in databases for example is to use plural form and [snake_case](https://en.wikipedia.org/wiki/Snake_case) notation. Prisma on the other hand has recommended model [naming conventions (singular form, PascalCase)](/orm/reference/prisma-schema-reference#naming-conventions) which differ from that.
+
+`@map` and `@@map` allow you to [tune the shape of your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) by decoupling model and field names from table and column names in the underlying database.
+
+### Map collection / table names
+
+As an example, when you [introspect](/orm/prisma-schema/introspection) a database with a table named `comments`, the resulting Prisma model will look like this:
+
+```prisma
+model comments {
+ // Fields
+}
+```
+
+However, you can still choose `Comment` as the name of the model (e.g. to follow the naming convention) without renaming the underlying `comments` table in the database by using the [`@@map`](/orm/reference/prisma-schema-reference#map-1) attribute:
+
+```prisma highlight=4;normal
+model Comment {
+ // Fields
+
+ @@map("comments")
+}
+```
+
+With this modified model definition, Prisma automatically maps the `Comment` model to the `comments` table in the underlying database.
+
+### Map field / column names
+
+You can also [`@map`](/orm/reference/prisma-schema-reference#map) a column/field name:
+
+```prisma highlight=2-4;normal
+model Comment {
+ content String @map("comment_text")
+ email String @map("commenter_email")
+ type Enum @map("comment_type")
+
+ @@map("comments")
+}
+```
+
+This way the `comment_text` column is not available under `prisma.comment.comment_text` in the Prisma Client API, but can be accessed via `prisma.comment.content`.
+
+### Map enum names and values
+
+You can also `@map` an enum value, or `@@map` an enum:
+
+```prisma highlight=3,5;normal
+enum Type {
+ Blog,
+ Twitter @map("comment_twitter")
+
+ @@map("comment_source_enum")
+}
+```
+
+## Constraint and index names
+
+In [2.29.0](https://github.com/prisma/prisma/releases/tag/2.29.0) and later, you can optionally use the `map` argument to define the **underlying constraint and index names** in the Prisma schema for the attributes [`@id`](/orm/reference/prisma-schema-reference#id), [`@@id`](/orm/reference/prisma-schema-reference#id-1), [`@unique`](/orm/reference/prisma-schema-reference#unique), [`@@unique`](/orm/reference/prisma-schema-reference#unique-1), [`@@index`](/orm/reference/prisma-schema-reference#index) and [`@relation`](/orm/reference/prisma-schema-reference#relation).
+
+When introspecting a database, the `map` argument will _only_ be rendered in the schema if the name differs from Prisma's [default constraint naming convention for indexes and constraints](#prismas-default-naming-conventions-for-indexes-and-constraints).
+
+
+
+If you use Prisma Migrate in a version earlier than 2.29.0 and want to maintain your existing constraint and index names after upgrading to a newer version, **do not** immediately run `prisma migrate` or `prisma db push`. This will **change any underlying constraint name that does not follow Prisma's convention**. Follow the [upgrade path that allows you to maintain existing constraint and index names](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/named-constraints#option-1-i-want-to-maintain-my-existing-constraint-and-index-names).
+
+
+
+### Use cases for named constraints
+
+Some use cases for explicitly named constraints include:
+
+- Company policy
+- Conventions of other tools
+
+#### Prisma's default naming conventions for indexes and constraints
+
+Prisma naming convention was chosen to align with PostgreSQL since it is deterministic. It also helps to maximize the amount of times where names do not need to be rendered because many databases out there they already align with the convention.
+
+We always use the database names of entities when generating the default names. So if a model is remapped to a different name in the data model, the default name generation will still take the name of the table in the database as input. The same is true for fields and columns.
+
+| Entity | Convention | Example |
+| ----------------- | --------------------------------- | ------------------------------ |
+| Primary Key | \{tablename}\_pkey | `User_pkey` |
+| Unique Constraint | \{tablename}\_\{column_names}\_key | `User_firstName_last_Name_key` |
+| Non-Unique Index | \{tablename}\_\{column_names}\_idx | `User_age_idx` |
+| Foreign Key | \{tablename}\_\{column_names}\_fkey | `User_childName_fkey` |
+
+Since most databases have a length limit for entity names, the names will be trimmed if necessary to not violate the database limits. We will shorten the part before the `_suffix` as necessary so that the full name is at most the maximum length permitted.
+
+### Using default constraint names
+
+When no explicit names are provided via `map` arguments Prisma will assume they follow the default naming convention.
+
+If you introspect a database the names for indexes and constraints will be added to your schema unless they follow Prisma's naming convention. If they do, the names are not rendered to keep the schema more readable. When you migrate such a schema Prisma will infer the default names and persist them in the database.
+
+#### Example
+
+The following schema defines three constraints (`@id`, `@unique`, and `@relation`) and one index (`@@index`) that will
+
+```prisma highlight=2,8,11,13;normal
+model User {
+ id Int @id @default(autoincrement())
+ name String @unique
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ authorName String @default("Anonymous")
+ author User? @relation(fields: [authorName], references: [name])
+
+ @@index([title, authorName])
+}
+```
+
+Since no explicit names are provided via `map` arguments Prisma will assume they follow our default naming convention.
+
+### Prisma's default naming conventions for indexes and constraints
+
+If you introspect a database the names for indexes and constraints will be added to your schema unless they follow Prisma's naming convention. If they do, the names are not rendered to keep the schema more readable. When you migrate such a schema Prisma will infer the default names and persist them in the database.
+
+We chose our naming convention to align with PostgreSQL since it is deterministic and helps us maximize the amount of times where we do not need
+to render names because they already align with the convention.
+
+| Constraint or index | Follows convention | Underlying constraint or index names |
+| ---------------------------------- | ------------------ | ------------------------------------ |
+| `@id` (on `User` > `id` field) | Yes | `User_pk` |
+| `@@index` (on `Post`) | Yes | `Post_title_authorName_idx` |
+| `@id` (on `Post` > `id` field) | Yes | `Post_pk` |
+| `@relation` (on `Post` > `author`) | Yes | `Post_authorName_fkey` |
+
+### Using custom constraint / index names
+
+You can use the `map` argument to define **custom constraint and index names** in the underlying database.
+
+#### Example
+
+The following example adds custom names to one `@id` and the `@@index`:
+
+```prisma highlight=2,13;normal
+model User {
+ id Int @id(map: "Custom_Primary_Key_Constraint_Name") @default(autoincrement())
+ name String @unique
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ authorName String @default("Anonymous")
+ author User? @relation(fields: [authorName], references: [name])
+
+ @@index([title, authorName], map: "My_Custom_Index_Name")
+}
+```
+
+The following table lists the name of each constraint and index in the underlying database:
+
+| Constraint or index | Follows convention | Underlying constraint or index names |
+| ---------------------------------- | ------------------ | ------------------------------------ |
+| `@id` (on `User` > `id` field) | No | `Custom_Primary_Key_Constraint_Name` |
+| `@@index` (on `Post`) | No | `My_Custom_Index_Name` |
+| `@id` (on `Post` > `id` field) | Yes | `Post_pk` |
+| `@relation` (on `Post` > `author`) | Yes | `Post_authorName_fkey` |
+
+### Related: Naming indexes and primary keys for Prisma Client
+
+Additionally to `map`, the `@@id` and `@@unique` attributes take an optional `name` argument that allows you to customize your Prisma Client API.
+
+On a model like:
+
+```prisma
+model User {
+ firstName String
+ lastName String
+
+ @@id([firstName, lastName])
+}
+```
+
+the default API for selecting on that primary key uses a generated combination of the fields:
+
+```ts
+const user = await prisma.user.findUnique({
+ where: {
+ firstName_lastName: {
+ firstName: 'Paul',
+ lastName: 'Panther',
+ },
+ },
+})
+```
+
+Specifying `@@id([firstName, lastName], name: "fullName")` will change the Prisma Client API to this instead:
+
+```ts highlight=3;edit
+const user = await prisma.user.findUnique({
+ where: {
+ fullName: {
+ firstName: 'Paul',
+ lastName: 'Panther',
+ },
+ },
+})
+```
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/60-multi-schema.mdx b/docs/200-orm/100-prisma-schema/20-data-model/60-multi-schema.mdx
new file mode 100644
index 0000000000..0a4848f1e6
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/60-multi-schema.mdx
@@ -0,0 +1,190 @@
+---
+title: How to use Prisma with multiple database schemas
+metaTitle: How to use Prisma with multiple database schemas
+metaDescription: How to use Prisma with multiple database schemas
+tocDepth: 3
+---
+
+
+
+
+
+Multiple database schema support is currently available with the PostgreSQL, CockroachDB, and SQL Server connectors.
+
+
+
+Many database providers allow you to organize database tables into named groups. You can use this to make the logical structure of the data model easier to understand, or to avoid naming collisions between tables.
+
+In PostgreSQL, CockroachDB, and SQL Server, these groups are known as schemas. We will refer to them as _database schemas_ to distinguish them from Prisma's own schema file.
+
+This guide explains how to:
+
+- include multiple database schemas in your Prisma schema
+- apply your schema changes to your database with Prisma Migrate and `db push`
+- introspect an existing database with multiple database schemas
+- query across multiple database schemas with Prisma Client
+
+
+
+## How to enable the `multiSchema` preview feature
+
+Multi-schema support is currently in preview. To enable the `multiSchema` preview feature, add the `multiSchema` feature flag to the `previewFeatures` field of the `generator` block in your Prisma schema file:
+
+```prisma file=schema.prisma highlight=3;add
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["multiSchema"]
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+```
+
+## How to include multiple database schemas in your Prisma schema
+
+To use multiple database schemas in your Prisma schema file, add the names of your database schemas to an array in the `schemas` field, in the `datasource` block. The following example adds a `"base"` and a `"transactional"` schema:
+
+```prisma file=schema.prisma highlight=9;add
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["multiSchema"]
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ schemas = ["base", "transactional"]
+}
+```
+
+You do not need to change your connection string. The `schema` value of your connection string is the default database schema that Prisma Client connects to and uses for raw queries. All other Prisma Client queries use the schema of the model or enum that you are querying.
+
+To designate that a model or enum belongs to a specific database schema, add the `@@schema` attribute with the name of the database schema as a parameter. In the following example, the `User` model is part of the `"base"` schema, and the `Order` model and `Size` enum are part of the `"transactional"` schema:
+
+```prisma file=schema.prisma highlight=5,13;add
+model User {
+ id Int @id
+ orders Order[]
+
+ @@schema("base")
+}
+
+model Order {
+ id Int @id
+ user User @relation(fields: [id], references: [id])
+ user_id Int
+
+ @@schema("transactional")
+}
+
+enum Size {
+ Small
+ Medium
+ Large
+
+ @@schema("transactional")
+}
+```
+
+### Tables with the same name in different database schemas
+
+If you have tables with the same name in different database schemas, you will need to map the table names to unique model names in your Prisma schema. This avoids name conflicts when you query models in Prisma Client.
+
+For example, consider a situation where the `config` table in the `base` database schema has the same name as the `config` table in the `users` database schema. To avoid name conflicts, give the models in your Prisma schema unique names (`BaseConfig` and `UserConfig`) and use the `@@map` attribute to map each model to the corresponding table name:
+
+```prisma file=schema.prisma
+model BaseConfig {
+ id Int @id
+
+ @@map("config")
+ @@schema("base")
+}
+
+model UserConfig {
+ id Int @id
+
+ @@map("config")
+ @@schema("users")
+}
+```
+
+## How to apply your schema changes with Prisma Migrate and `db push`
+
+You can use Prisma Migrate or `db push` to apply changes to a Prisma schema with multiple database schemas.
+
+As an example, add a `Profile` model to the `base` schema of the blog post model above:
+
+```prisma file=schema.prisma highlight=4,9-16;add
+model User {
+ id Int @id
+ orders Order[]
+ profile Profile?
+
+ @@schema("base")
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ bio String
+ user User @relation(fields: [userId], references: [id])
+ userId Int @unique
+
+ @@schema("base")
+}
+
+model Order {
+ id Int @id
+ user User @relation(fields: [id], references: [id])
+ user_id Int
+
+ @@schema("transactional")
+}
+
+enum Size {
+ Small
+ Medium
+ Large
+
+ @@schema("transactional")
+}
+```
+
+You can then apply this schema change to your database. For example, you can use `migrate dev` to create and apply your schema changes as a migration:
+
+```terminal
+npx prisma migrate dev --name add_profile
+```
+
+Note that if you move a model or enum from one schema to another, Prisma deletes the model or enum from the source schema and creates a new one in the target schema.
+
+## How to introspect an existing database with multiple database schemas
+
+You can introspect an existing database that has multiple database schemas in the same way that you introspect a database that has a single database schema, using `db pull`:
+
+```terminal
+npx prisma db pull
+```
+
+This updates your Prisma schema to match the current state of the database.
+
+If you have tables with the same name in different database schemas, Prisma shows a validation error pointing out the conflict. To fix this, [rename the introspected models with the `@map` attribute](#tables-with-the-same-name-in-different-database-schemas).
+
+## How to query across multiple database schemas with Prisma Client
+
+You can query models in multiple database schemas without any change to your Prisma Client query syntax. For example, the following query finds all orders for a given user, using the Prisma schema above:
+
+```ts
+const orders = await prisma.order.findMany({
+ where: {
+ user: {
+ id: 1,
+ },
+ },
+})
+```
+
+## Learn more about the `multiSchema` preview feature
+
+To learn more about future plans for the `multiSchema` preview feature, or to give feedback, refer to [our Github issue](https://github.com/prisma/prisma/issues/1122).
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/70-unsupported-database-features.mdx b/docs/200-orm/100-prisma-schema/20-data-model/70-unsupported-database-features.mdx
new file mode 100644
index 0000000000..8daa975dc6
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/70-unsupported-database-features.mdx
@@ -0,0 +1,99 @@
+---
+title: 'Unsupported database features'
+metaDescription: How to support database features that do not have an equivalent syntax in Prisma Schema Language.
+tocDepth: 2
+---
+
+
+
+Not all database functions and features of all of Prisma's supported databases have a Prisma Schema Language equivalent. Refer to the [database features matrix](/orm/reference/database-features) for a complete list of supported features.
+
+
+
+## Native database functions
+
+Prisma Schema Language supports several [functions](/orm/reference/prisma-schema-reference#attribute-functions) that you can use to set the default value of a field. The following example uses the Prisma-level `uuid()` function to set the value of the `id` field:
+
+```prisma
+model Post {
+ id String @id @default(uuid())
+}
+```
+
+However, you can also use **native database functions** to define default values with [`dbgenerated()`](/orm/reference/prisma-schema-reference#dbgenerated) on relational databases (MongoDB does not have the concept of database-level functions). The following example uses the PostgreSQL `gen_random_uuid()` function to populate the `id` field:
+
+```prisma
+model User {
+ id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
+}
+```
+
+### When to use a database-level function
+
+There are two reasons to use a database-level function:
+
+- There is no equivalent Prisma function (for example, `gen_random_bytes` in PostgreSQL).
+- You cannot or do not want to rely on functions such `uuid()` and `cuid()`, which are only implemented at Prisma level and do not manifest in the database.
+
+ Consider the following example, which sets the `id` field to a randomly generated `UUID`:
+
+ ```prisma
+ model Post {
+ id String @id @default(uuid())
+ }
+ ```
+
+ The UUID is _only_ generated if you use Prisma Client to create the `Post`. If you create posts in any other way, such as a bulk import script written in plain SQL, you must generate the UUID yourself.
+
+### Enable PostgreSQL extensions for native database functions
+
+In PostgreSQL, some native database functions are part of an extension. For example, in PostgreSQL versions 12.13 and earlier, the `gen_random_uuid()` function is part of the [`pgcrypto`](https://www.postgresql.org/docs/10/pgcrypto.html) extension.
+
+To use a PostgreSQL extension, you must first install it on the file system of your database server.
+
+In Prisma versions 4.5.0 and later, you can then activate the extension by declaring it in your Prisma schema with the [`postgresqlExtensions` preview feature](/orm/prisma-schema/postgresql-extensions):
+
+```prisma file=schema.prisma highlight=3,9;add
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["postgresqlExtensions"]
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ extensions = [pgcrypto]
+}
+```
+
+In earlier versions of Prisma, you must instead run a SQL command to activate the extension:
+
+```sql
+CREATE EXTENSION IF NOT EXISTS pgcrypto;
+```
+
+If your project uses [Prisma Migrate](/orm/prisma-migrate), you must [install the extension as part of a migration](/orm/prisma-migrate/workflows/native-database-functions) . Do not install the extension manually, because it is also required by the shadow database.
+
+Prisma Migrate returns the following error if the extension is not available:
+
+```
+Migration `20210221102106_failed_migration` failed to apply cleanly to a temporary database.
+Database error: Error querying the database: db error: ERROR: type "pgcrypto" does not exist
+```
+
+## Unsupported field types
+
+Some database types of relational databases, such as `polygon` or `geometry`, do not have a Prisma Schema Language equivalent. Use the [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) field type to represent the field in your Prisma schema:
+
+```prisma highlight=3;normal
+model Star {
+ id Int @id @default(autoincrement())
+ position Unsupported("circle")? @default(dbgenerated("'<(10,4),11>'::circle"))
+}
+```
+
+The `prisma migrate dev` and `prisma db push` command will both create a `position` field of type `circle` in the database. However, the field will not be available in the generated Prisma Client.
+
+## Unsupported database features
+
+Some features, like SQL views or partial indexes, cannot be represented in the Prisma schema. If your project uses [Prisma Migrate](/orm/prisma-migrate), you must [include unsupported features as part of a migration](/orm/prisma-migrate/workflows/unsupported-database-features) .
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/80-table-inheritance.mdx b/docs/200-orm/100-prisma-schema/20-data-model/80-table-inheritance.mdx
new file mode 100644
index 0000000000..32170bbb82
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/80-table-inheritance.mdx
@@ -0,0 +1,328 @@
+---
+title: Table inheritance
+metaTitle: Table inheritance
+metaDescription: Learn about the use cases and patterns for table inheritance in Prisma ORM that enable usage of union types or polymorphic structures in your application.
+tocDepth: 3
+---
+
+## Overview
+
+Table inheritance is a software design pattern that allows the modeling of hierarchical relationships between entities. Using table inheritance on the database level can also enable the use of union types in your JavaScript/TypeScript application or share a set of common properties across multiple models.
+
+This page introduces two approaches to table inheritance and explains how to use them with Prisma ORM.
+
+A common use case for table inheritance may be when an application needs to display a _feed_ of some kind of _content activities_. A content activity in this case, could be a _video_ or an _article_. As an example, let's assume that:
+
+- a content activity always has an `id` and a `url`
+- in addition to `id` and a `url`, a video also has a `duration` (modeled as an `Int`)
+- in addition to `id` and a `url`, an article also a `body` (modeled as a `String`)
+
+### Use cases
+
+#### Union types
+
+Union types are a convenient feature in TypeScript that allows developers to work more flexibly with the types in their data model.
+
+In TypeScript, union types look as follows:
+
+```ts no-copy
+type Activity = Video | Article
+```
+
+While [it's currently not possible to model union types in the Prisma schema](https://github.com/prisma/prisma/issues/2505), you can use them with Prisma ORM by using table inheritance and some additional type definitions.
+
+#### Sharing properties across multiple models
+
+If you have a use case where multiple models should share a particular set of properties, you can model this using table inheritance as well.
+
+For example, if both the `Video` and `Article` models from above should have a shared `title` property, you can achieve this with table inheritance as well.
+
+### Example
+
+In a simple Prisma schema, this would look as follows. Note that we're adding a `User` model as well to illustrate how this can work with relations:
+
+```prisma file=schema.prisma
+model Video {
+ id Int @id
+ url String @unique
+ duration Int
+
+ user User @relation(fields: [userId], references: [id])
+ userId Int
+}
+
+model Article {
+ id Int @id
+ url String @unique
+ body String
+
+ user User @relation(fields: [userId], references: [id])
+ userId Int
+}
+
+model User {
+ id Int @id
+ name String
+ videos Video[]
+ articles Article[]
+}
+```
+
+Let's investigate how we can model this using table inheritance.
+
+### Single-table vs multi-table inheritance
+
+Here is a quick comparison of the two main approaches for table inheritance:
+
+- **Single-table inheritance (STI)**: Uses a _single_ table to store data of _all_ the different entities in one location. In our example, there'd be a single `Activity` table with the `id`, `url` as well as te `duration` and `body` column. It also uses a `type` column that indicates whether an _activity_ is a _video_ or an _article_.
+- **Multi-table inheritance (MTI)**: Uses _multiple_ tables to store the data of the different entities separately and links them via foreign keys. In our example, there'd be an `Activity` table with the `id`, `url` column, a `Video` table with the `duration` and a foreign key to `Activity` as well as an `Article` table with the `body` and a foreign key. There is also a `type` column that acts as a discriminator and indicates whether an _activity_ is a _video_ or an _article_. Note that multi-table inheritance is also sometimes called _delegated types_.
+
+You can learn about the tradeoffs of both approaches [below](#tradeoffs-between-sti-and-mti).
+
+## Single-table inheritance (STI)
+
+### Data model
+
+Using STI, the above scenario can be modeled as follows:
+
+```prisma
+model Activity {
+ id Int @id // shared
+ url String @unique // shared
+ duration Int? // video-only
+ body String? // article-only
+ type ActivityType // discriminator
+
+ owner User @relation(fields: [ownerId], references: [id])
+ ownerId Int
+}
+
+enum ActivityType {
+ Video
+ Article
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ activities Activity[]
+}
+```
+
+A few things to note:
+
+- The model-specific properties `duration` and `body` must be marked as optional (i.e., with `?`). That's because a record in the `Activity` table that represents a _video_ must not have a value for `body`. Conversely, an `Activity` record representing an _article_ can never have a `duration` set.
+- The `type` discriminator column indicates whether each record represents a _video_ or an _article_ item.
+
+### Prisma Client API
+
+Due to how Prisma ORM generates types and an API for the data model, there will only to be an `Activity` type and the CRUD queries that belong to it (`create`, `update`, `delete`, ...) available to you.
+
+#### Querying for videos and articles
+
+You can now query for only _videos_ or _articles_ by filtering on the `type` column. For example:
+
+```ts
+// Query all videos
+const videos = await prisma.activity.findMany({
+ where: { type: 'Video' },
+})
+
+// Query all articles
+const articles = await prisma.activity.findMany({
+ where: { type: 'Article' },
+})
+```
+
+#### Defining dedicated types
+
+When querying for videos and articles like that, TypeScript will still only recognize an `Activity` type. That can be annoying because even the objects in `videos` will have (optional) `body` and the objects in `articles` will have (optional) `duration` fields.
+
+If you want to have type safety for these objects, you need to define dedicated types for them. You can do this, for example, by using the generated `Activity` type and the TypeScript `Omit` utility type to remove properties from it:
+
+```ts
+import { Activity } from '@prisma/client'
+
+type Video = Omit
+type Article = Omit
+```
+
+In addition, it will be helpful to convert mapping functions that convert an object of type `Activity` to the `Video` and `Article` types:
+
+```ts
+function activityToVideo(activity: Activity): Video {
+ return {
+ url: activity.url,
+ duration: activity.duration ? activity.duration : -1,
+ ownerId: activity.ownerId,
+ } as Video
+}
+
+function activityToArticle(activity: Activity): Article {
+ return {
+ url: activity.url,
+ body: activity.body ? activity.body : '',
+ ownerId: activity.ownerId,
+ } as Article
+}
+```
+
+Now you can turn an `Activity` into a more specific type (i.e., `Article` or `Video`) after querying:
+
+```ts
+const videoActivities = await prisma.activity.findMany({
+ where: { type: 'Video' },
+})
+const videos: Video[] = videoActivities.map(activityToVideo)
+```
+
+#### Using Prisma Client extension for a more convenient API
+
+You can use [Prisma Client extensions](/orm/prisma-client/client-extensions) to create a more convenient API for the table structures in your database.
+
+## Multi-table inheritance (MTI)
+
+### Data model
+
+Using MTI, the above scenario can be modeled as follows:
+
+```prisma
+model Activity {
+ id Int @id @default(autoincrement())
+ url String // shared
+ type ActivityType // discriminator
+
+ video Video? // model-specific 1-1 relation
+ article Article? // model-specific 1-1 relation
+
+ owner User @relation(fields: [ownerId], references: [id])
+ ownerId Int
+}
+
+model Video {
+ id Int @id @default(autoincrement())
+ duration Int // video-only
+ activityId Int @unique
+ activity Activity @relation(fields: [activityId], references: [id])
+}
+
+model Article {
+ id Int @id @default(autoincrement())
+ body String // article-only
+ activityId Int @unique
+ activity Activity @relation(fields: [activityId], references: [id])
+}
+
+enum ActivityType {
+ Video
+ Article
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ activities Activity[]
+}
+```
+
+A few things to note:
+
+- A 1-1 relation is needed between `Activity` and `Video` as well as `Activity` and `Article`. This relationship is used to fetch the specific information about a record when needed.
+- The model-specific properties `duration` and `body` can be made _required_ with this approach.
+- The `type` discriminator column indicates whether each record represents a _video_ or an _article_ item.
+
+### Prisma Client API
+
+This time, you can query for videos and articles directly via the `video` and `article` properties on your `PrismaClient`` instance.
+
+#### Querying for videos and articles
+
+If you want to access the shared properties, you need to use `include` to fetch the relation to `Activity`.
+
+```ts
+// Query all videos
+const videos = await prisma.video.findMany({
+ include: { activity: true },
+})
+
+// Query all articles
+const articles = await prisma.article.findMany({
+ include: { activity: true },
+})
+```
+
+Depending on your needs, you may also query the other way around by filtering on the `type` discriminator column:
+
+```ts
+// Query all articles
+const videoActivities = await prisma.activity.findMany({
+ where: { type: 'Video' }
+ include: { video: true }
+})
+```
+
+#### Defining dedicated types
+
+While a bit more convenient in terms of types compare STI, the generated typings likely still won't fit all your needs.
+
+Here's how you can define `Video` and `Article` types by combining Prisma ORM's generated `Video` and `Article` types with the `Activity` type. These combinations create a new type with the desired properties. Note that we're also omitting the `type` discriminator column because that's not needed anymore on the specific types:
+
+```ts
+import {
+ Video as VideoDB,
+ Article as ArticleDB,
+ Activity,
+} from '@prisma/client'
+
+type Video = Omit
+type Article = Omit
+```
+
+Once these types are defined, you can define mapping functions to convert the types you receive from the queries above into the desired `Video` and `Article` types. Here's the example for the `Video` type:
+
+```ts
+import { Prisma, Video as VideoDB, Activity } from '@prisma/client'
+
+type Video = Omit
+
+// Create `VideoWithActivity` typings for the objects returned above
+const videoWithActivity = Prisma.validator()({
+ include: { activity: true },
+})
+type VideoWithActivity = Prisma.VideoGetPayload
+
+// Map to `Video` type
+function toVideo(a: VideoWithActivity): Video {
+ return {
+ id: a.id,
+ url: a.activity.url,
+ ownerId: a.activity.ownerId,
+ duration: a.duration,
+ activityId: a.activity.id,
+ }
+}
+```
+
+Now you can take the objects returned by the queries above and transform them using `toVideo`:
+
+```ts
+const videoWithActivities = await prisma.video.findMany({
+ include: { activity: true },
+})
+const videos: Video[] = videoWithActivities.map(toVideo)
+```
+
+#### Using Prisma Client extension for a more convenient API
+
+You can use [Prisma Client extensions](/orm/prisma-client/client-extensions) to create a more convenient API for the table structures in your database.
+
+## Tradeoffs between STI and MTI
+
+- **Data model**: The data model may feel more clean with MTI. With STI, you may end up with very wide rows and lots of columns that have `NULL` values in them.
+- **Performance**: MTI may come with a performance cost because you need to join the parent and child tables to access _all_ properties relevant for a model.
+- **Typings**: With Prisma ORM, MTI gives you proper typings for the specific models (i.e., `Article` and `Video` in the examples above) already, while you need to create these from scratch with STI.
+- **IDs / Primary keys**: With MTI, records have two IDs (one on the parent and another on the child table) that may not match. You need to consider this in the business logic of your application.
+
+## Third-party solutions
+
+While Prisma ORM doesn't natively support union types or polymorphism at the moment, you can check out [Zenstack](https://github.com/zenstackhq/zenstack) which is adding an extra layer of features to the Prisma schema. Read their [blog post about polymorphism in Prisma ORM](https://zenstack.dev/blog/polymorphism) to learn more.
diff --git a/docs/200-orm/100-prisma-schema/20-data-model/index.mdx b/docs/200-orm/100-prisma-schema/20-data-model/index.mdx
new file mode 100644
index 0000000000..38f3f46a38
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/20-data-model/index.mdx
@@ -0,0 +1,10 @@
+---
+title: 'Data model'
+metaTitle: 'Data model'
+metaDescription: 'Learn everything you need about the Prisma data model.'
+toc: false
+---
+
+## In this section
+
+
diff --git a/docs/200-orm/100-prisma-schema/50-introspection.mdx b/docs/200-orm/100-prisma-schema/50-introspection.mdx
new file mode 100644
index 0000000000..553f50b67f
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/50-introspection.mdx
@@ -0,0 +1,398 @@
+---
+title: 'Introspection'
+metaTitle: 'What is introspection? (Reference)'
+metaDescription: 'Learn how you can introspect your database to generate a data model into your Prisma schema.'
+---
+
+
+
+You can introspect your database using the Prisma CLI in order to generate the [data model](/orm/prisma-schema/data-model) in your [Prisma schema](/orm/prisma-schema). The data model is needed to [generate Prisma Client](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names).
+
+Introspection is often used to generate an _initial_ version of the data model when [adding Prisma to an existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql).
+
+However, it can also be [used _repeatedly_ in an application](#introspection-with-an-existing-schema). This is most commonly the case when you're _not_ using [Prisma Migrate](/orm/prisma-migrate) but perform schema migrations using plain SQL or another migration tool. In that case, you also need to re-introspect your database and subsequently re-generate Prisma Client to reflect the schema changes in your [Prisma Client API](/orm/prisma-client).
+
+
+
+## What does introspection do?
+
+Introspection has one main function: Populate your Prisma schema with a data model that reflects the current database schema.
+
+
+
+Here's an overview of its main functions on SQL databases:
+
+- Map _tables_ in the database to [Prisma models](/orm/prisma-schema/data-model/models#defining-models)
+- Map _columns_ in the database to the [fields](/orm/prisma-schema/data-model/models#defining-fields) of Prisma models
+- Map _indexes_ in the database to [indexes](/orm/prisma-schema/data-model/models#defining-an-index) in the Prisma schema
+- Map _database constraints_ to [attributes](/orm/prisma-schema/data-model/models#defining-attributes) or [type modifiers](/orm/prisma-schema/data-model/models#type-modifiers) in the Prisma schema
+
+On MongoDB, the main functions are the following:
+
+- Map _collections_ in the database to [Prisma models](/orm/prisma-schema/data-model/models#defining-models)
+- Map _documents_ in the collections to the [fields](/orm/prisma-schema/data-model/models#defining-fields) of Prisma models by _sampling them_
+- Map _indexes_ in the database to [indexes](/orm/prisma-schema/data-model/models#defining-an-index) in the Prisma schema, if the collection contains at least one document contains a field included in the index
+
+You can learn more about how Prisma maps types from the database to the types available in the Prisma schema on the respective docs page for the data source connector:
+
+- [PostgreSQL](/orm/overview/databases/postgresql#type-mapping-between-postgresql-and-prisma-schema)
+- [MySQL](/orm/overview/databases/mysql#type-mapping-between-mysql-to-prisma-schema)
+- [SQLite](/orm/overview/databases/sqlite#type-mapping-between-sqlite-to-prisma-schema)
+- [Microsoft SQL Server](/orm/overview/databases/sql-server#type-mapping-between-microsoft-sql-server-to-prisma-schema)
+
+## The `prisma db pull` command
+
+You can introspect your database using the `prisma db pull` command of the [Prisma CLI](/orm/tools/prisma-cli#installation). Note that using this command requires your [connection URL](/orm/reference/connection-urls) to be set in your Prisma schema [`datasource`](/orm/prisma-schema/overview/data-sources).
+
+Here's a high-level overview of the steps that `prisma db pull` performs internally:
+
+1. Read the [connection URL](/orm/reference/connection-urls) from the `datasource` configuration in the Prisma schema
+1. Open a connection to the database
+1. Introspect database schema (i.e. read tables, columns and other structures ...)
+1. Transform database schema into Prisma data model
+1. Write data model into Prisma schema or [update existing schema](#introspection-with-an-existing-schema)
+
+## Introspection workflow
+
+The typical workflow for projects that are not using Prisma Migrate, but instead use plain SQL or another migration tool looks as follows:
+
+1. Change the database schema (e.g. using plain SQL)
+1. Run `prisma db pull` to update the Prisma schema
+1. Run `prisma generate` to update Prisma Client
+1. Use the updated Prisma Client in your application
+
+Note that as you evolve the application, [this process can be repeated for an indefinite number of times](#introspection-with-an-existing-schema).
+
+
+
+## Rules and conventions
+
+Prisma employs a number of conventions for translating a database schema into a Prisma data model:
+
+### Model, field and enum names
+
+Field, model and enum names (identifiers) must start with a letter and generally must only contain underscores, letters and digits. You can find the naming rules and conventions for each of these identifiers on the respective docs page:
+
+- [Naming models](/orm/reference/prisma-schema-reference#naming-conventions)
+- [Naming fields](/orm/reference/prisma-schema-reference#naming-conventions-1)
+- [Naming enums](/orm/reference/prisma-schema-reference#naming-conventions-2)
+
+The general rule for identifiers is that they need to adhere to this regular expression:
+
+```
+[A-Za-z][A-Za-z0-9_]*
+```
+
+#### Sanitization of invalid characters
+
+**Invalid characters** are being sanitized during introspection:
+
+- If they appear _before_ a letter in an identifier, they get dropped.
+- If they appear _after_ the first letter, they get replaced by an underscore.
+
+Additionally, the transformed name is mapped to the database using `@map` or `@@map` to retain the original name.
+
+Consider the following table as an example:
+
+```sql
+CREATE TABLE "42User" (
+ _id SERIAL PRIMARY KEY,
+ _name VARCHAR(255),
+ two$two INTEGER
+);
+```
+
+Because the leading `42` in the table name as well as the leading underscores and the `$` on the columns are forbidden in Prisma, introspection adds the `@map` and `@@map` attributes so that these names adhere to Prisma's naming conventions:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement()) @map("_id")
+ name String? @map("_name")
+ two_two Int? @map("two$two")
+
+ @@map("42User")
+}
+```
+
+#### Duplicate Identifiers after Sanitization
+
+If sanitization results in duplicate identifiers, no immediate error handling is in place. You get the error later and can manually fix it.
+
+Consider the case of the following two tables:
+
+```sql
+CREATE TABLE "42User" (
+ _id SERIAL PRIMARY KEY
+);
+
+CREATE TABLE "24User" (
+ _id SERIAL PRIMARY KEY
+);
+```
+
+This would result in the following introspection result:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement()) @map("_id")
+
+ @@map("42User")
+}
+
+model User {
+ id Int @id @default(autoincrement()) @map("_id")
+
+ @@map("24User")
+}
+```
+
+Trying to generate your Prisma Client with `prisma generate` you would get the following error:
+
+
+
+
+
+```
+npx prisma generate
+```
+
+
+
+
+
+```code no-copy
+$ npx prisma generate
+Error: Schema parsing
+error: The model "User" cannot be defined because a model with that name already exists.
+ --> schema.prisma:17
+ |
+16 | }
+17 | model User {
+ |
+
+Validation Error Count: 1
+```
+
+
+
+
+
+In this case, you must manually change the name of one of the two generated `User` models because duplicate model names are not allowed in the Prisma schema.
+
+### Order of fields
+
+Introspection lists model fields in the same order as the corresponding table columns in the database.
+
+### Order of attributes
+
+Introspection adds attributes in the following order (this order is mirrored by `prisma format`):
+
+- Block level: `@@id`, `@@unique`, `@@index`, `@@map`
+- Field level : `@id`, `@unique`, `@default`, `@updatedAt`, `@map`, `@relation`
+
+### Relations
+
+Prisma translates foreign keys that are defined on your database tables into [relations](/orm/prisma-schema/data-model/relations).
+
+#### One-to-one relations
+
+Prisma adds a [one-to-one](/orm/prisma-schema/data-model/relations/one-to-one-relations) relation to your data model when the foreign key on a table has a `UNIQUE` constraint, e.g.:
+
+```sql
+CREATE TABLE "User" (
+ id SERIAL PRIMARY KEY
+);
+CREATE TABLE "Profile" (
+ id SERIAL PRIMARY KEY,
+ "user" integer NOT NULL UNIQUE,
+ FOREIGN KEY ("user") REFERENCES "User"(id)
+);
+```
+
+Prisma translates this into the following data model:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ Profile Profile?
+}
+
+model Profile {
+ id Int @id @default(autoincrement())
+ user Int @unique
+ User User @relation(fields: [user], references: [id])
+}
+```
+
+#### One-to-many relations
+
+By default, Prisma adds a [one-to-many](/orm/prisma-schema/data-model/relations/one-to-many-relations) relation to your data model for a foreign key it finds in your database schema:
+
+```sql
+CREATE TABLE "User" (
+ id SERIAL PRIMARY KEY
+);
+CREATE TABLE "Post" (
+ id SERIAL PRIMARY KEY,
+ "author" integer NOT NULL,
+ FOREIGN KEY ("author") REFERENCES "User"(id)
+);
+```
+
+These tables are transformed into the following models:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ Post Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ author Int
+ User User @relation(fields: [author], references: [id])
+}
+```
+
+#### Many-to-many relations
+
+[Many-to-many](/orm/prisma-schema/data-model/relations/many-to-many-relations) relations are commonly represented as [relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) in relational databases.
+
+Prisma supports two ways for defining many-to-many relations in the Prisma schema:
+
+- [Implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) (Prisma manages the relation table under the hood)
+- [Explicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations) (the relation table is present as a [model](/orm/prisma-schema/data-model/models#defining-models))
+
+_Implicit_ many-to-many relations are recognized if they adhere to Prisma's [conventions for relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#conventions-for-relation-tables-in-implicit-m-n-relations). Otherwise the relation table is rendered in the Prisma schema as a model (therefore making it an _explicit_ many-to-many relation).
+
+This topic is covered extensively on the docs page about [Relations](/orm/prisma-schema/data-model/relations).
+
+#### Disambiguating relations
+
+Prisma generally omits the `name` argument on the [`@relation`](/orm/prisma-schema/data-model/relations#the-relation-attribute) attribute if it's not needed. Consider the `User` ↔ `Post` example from the previous section. The `@relation` attribute only has the `references` argument, `name` is omitted because it's not needed in this case:
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ author Int
+ User User @relation(fields: [author], references: [id])
+}
+```
+
+It would be needed if there were _two_ foreign keys defined on the `Post` table:
+
+```sql
+CREATE TABLE "User" (
+ id SERIAL PRIMARY KEY
+);
+CREATE TABLE "Post" (
+ id SERIAL PRIMARY KEY,
+ "author" integer NOT NULL,
+ "favoritedBy" INTEGER,
+ FOREIGN KEY ("author") REFERENCES "User"(id),
+ FOREIGN KEY ("favoritedBy") REFERENCES "User"(id)
+);
+```
+
+In this case, Prisma needs to [disambiguate the relation](/orm/prisma-schema/data-model/relations#disambiguating-relations) using a dedicated relation name:
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ author Int
+ favoritedBy Int?
+ User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id])
+ User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id])
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ Post_Post_authorToUser Post[] @relation("Post_authorToUser")
+ Post_Post_favoritedByToUser Post[] @relation("Post_favoritedByToUser")
+}
+```
+
+Note that you can rename the [Prisma-level](/orm/prisma-schema/data-model/relations#relation-fields) relation field to anything you like so that it looks friendlier in the generated Prisma Client API.
+
+## Introspection with an existing schema
+
+Running `prisma db pull` for relational databases with an existing schema file merges manual changes made to the schema, with changes made in the database. (This functionality has been added for the first time with version 2.6.0.) For MongoDB, Introspection for now is meant to be done only once for the initial data model. Running it repeatedly will lead to loss of custom changes, as the ones listed below.
+
+Introspection for relational databases maintains the following manual changes:
+
+- Order of `model` blocks
+- Order of `enum` blocks
+- Comments
+- `@map` and `@@map` attributes
+- `@updatedAt`
+- `@default(cuid())` (`cuid()` is a Prisma-level function)
+- `@default(uuid())` (`uuid()` is a Prisma-level function)
+- Custom `@relation` names
+
+> **Note**: Only relations between models on the database level will be picked up. This means that there **must be a foreign key set**.
+
+The following properties of the schema are determined by the database:
+
+- Order of fields within `model` blocks
+- Order of values within `enum` blocks
+
+> **Note**: All `enum` blocks are listed below `model` blocks.
+
+### Force overwrite
+
+To overwrite manual changes, and generate a schema based solely on the introspected database and ignore any existing schema file, add the `--force` flag to the `db pull` command:
+
+```terminal
+npx prisma db pull --force
+```
+
+Use cases include:
+
+- You want to start from scratch with a schema generated from the underlying database
+- You have an invalid schema and must use `--force` to make introspection succeed
+
+## Introspecting only a subset of your database schema
+
+Introspecting only a subset of your database schema is [not yet officially supported](https://github.com/prisma/prisma/issues/807) by Prisma.
+
+However, you can achieve this by creating a new database user that only has access to the tables which you'd like to see represented in your Prisma schema, and then perform the introspection using that user. The introspection will then only include the tables the new user has access to.
+
+If your goal is to exclude certain models from the [Prisma Client generation](/orm/prisma-client/setup-and-configuration/generating-prisma-client), you can add the [`@@ignore` attribute](/orm/reference/prisma-schema-reference#ignore-1) to the model definition in your Prisma schema. Ignored models are excluded from the generated Prisma Client.
+
+## Introspection warnings for unsupported features
+
+The Prisma Schema Language (PSL) can express a majority of the database features of the [target databases](/orm/reference/supported-databases) Prisma supports. However, there are features and functionality the Prisma Schema Language still needs to express.
+
+For these features, the Prisma CLI will surface detect usage of the feature in your database and return a warning. The Prisma CLI will also add a comment in the models and fields the features are in use in the Prisma schema. The warnings will also contain a workaround suggestion.
+
+The `prisma db pull` command will surface the following unsupported features:
+
+- From version [4.13.0](https://github.com/prisma/prisma/releases/tag/4.13.0):
+ - [Partitioned tables](https://github.com/prisma/prisma/issues/1708)
+ - [PostgreSQL Row Level Security](https://github.com/prisma/prisma/issues/12735)
+ - [Index sort order, `NULLS FIRST` / `NULLS LAST`](https://github.com/prisma/prisma/issues/15466)
+ - [CockroachDB row-level TTL](https://github.com/prisma/prisma/issues/13982)
+ - [Comments](https://github.com/prisma/prisma/issues/8703)
+ - [PostgreSQL deferred constraints](https://github.com/prisma/prisma/issues/8807)
+- From version [4.14.0](https://github.com/prisma/prisma/releases/tag/4.14.0):
+ - [Check Constraints](https://github.com/prisma/prisma/issues/3388) (MySQL + PostgreSQL)
+ - [Exclusion Constraints](https://github.com/prisma/prisma/issues/17514)
+ - [MongoDB $jsonSchema](https://github.com/prisma/prisma/issues/8135)
+- From version [4.16.0](https://github.com/prisma/prisma/releases/tag/4.16.0):
+ - [Expression indexes](https://github.com/prisma/prisma/issues/2504)
+
+You can find the list of features we intend to support on [GitHub (labeled with `topic:database-functionality`)](https://github.com/prisma/prisma/issues?q=is%3Aopen+label%3A%22topic%3A+database-functionality%22+label%3Ateam%2Fschema+sort%3Aupdated-desc+).
+
+### Workaround for introspection warnings for unsupported features
+
+If you are using a relational database and either one of the above features listed in the previous section:
+
+1. Create a draft migration:
+ ```terminal
+ npx prisma migrate dev --create-only
+ ```
+2. Add the SQL that adds the feature surfaced in the warnings.
+3. Apply the draft migration to your database:
+ ```terminal
+ npx prisma migrate dev
+ ```
diff --git a/docs/200-orm/100-prisma-schema/80-postgresql-extensions.mdx b/docs/200-orm/100-prisma-schema/80-postgresql-extensions.mdx
new file mode 100644
index 0000000000..bb035178bf
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/80-postgresql-extensions.mdx
@@ -0,0 +1,116 @@
+---
+title: 'PostgreSQL extensions'
+metaTitle: 'How to represent PostgreSQL extensions in your Prisma schema'
+metaDescription: 'How to represent PostgreSQL extensions in your Prisma scheme, introspect extensions in your database, and apply changes to extensions with Prisma Migrate'
+preview: true
+tocDepth: 3
+---
+
+
+
+This page introduces PostgreSQL extensions and describes how to represent extensions in your Prisma schema, how to introspect existing extensions in your database, and how to apply changes to your extensions to your database with Prisma Migrate.
+
+
+
+Support for declaring PostgreSQL extensions in your schema is available in preview for the PostgreSQL connector only in Prisma versions 4.5.0 and later.
+
+
+
+
+
+## What are PostgreSQL extensions?
+
+PostgreSQL allows you to extend your database functionality by installing and activating packages known as _extensions_. For example, the `citext` extension adds a case-insensitive string data type. Some extensions, such as `citext`, are supplied directly by PostgreSQL, while other extensions are developed externally. For more information on extensions, see [the PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-createextension.html).
+
+To use an extension, it must first be _installed_ on the local file system of your database server. You then need to _activate_ the extension, which runs a script file that adds the new functionality.
+
+
+
+Note that PostgreSQL's documentation uses the term 'install' to refer to what we call activating an extension. We have used separate terms here to make it clear that these are two different steps.
+
+
+
+Prisma's `postgresqlExtensions` preview feature allows you to represent PostgreSQL extensions in your Prisma schema. Note that specific extensions may add functionality that is not currently supported by Prisma. For example, an extension may add a type or index that is not supported by Prisma. This functionality must be implemented on a case-by-case basis and is not provided by this preview feature.
+
+## How to enable the `postgresqlExtensions` preview feature
+
+Representing PostgreSQL extensions in your Prisma schema is currently a preview feature. To enable the `postgresqlExtensions` preview feature, you will need to add the `postgresqlExtensions` feature flag to the `previewFeatures` field of the `generator` block in your Prisma schema file:
+
+```prisma file=schema.prisma highlight=3;add
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["postgresqlExtensions"]
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+```
+
+## How to represent PostgreSQL extensions in your Prisma schema
+
+To represent PostgreSQL extensions in your Prisma schema, add the `extensions` field to the `datasource` block of your `schema.prisma` file with an array of the extensions that you require. For example, the following schema lists the `hstore`, `pg_trgm` and `postgis` extensions:
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ extensions = [hstore(schema: "myHstoreSchema"), pg_trgm, postgis(version: "2.1")]
+}
+```
+
+Each extension name in the Prisma schema can take the following optional arguments:
+
+- `schema`: the name of the schema in which to activate the extension's objects. If this argument is not specified, the current default object creation schema is used.
+- `version`: the version of the extension to activate. If this argument is not specified, the value given in the extension's control file is used.
+- `map`: the database name of the extension. If this argument is not specified, the name of the extension in the Prisma schema must match the database name.
+
+In the example above, the `hstore` extension uses the `myHstoreSchema` schema, and the `postgis` extension is activated with version 2.1 of the extension.
+
+The `map` argument is useful when the PostgreSQL extension that you want to activate has a name that is not a valid identifier in the Prisma schema. For example, the `uuid-ossp` PostgreSQL extension name is an invalid identifier because it contains a hyphen. In the following example, the extension is mapped to the valid name `uuidOssp` in the Prisma schema:
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ extensions = [uuidOssp(map: "uuid-ossp")]
+}
+```
+
+## How to introspect PostgreSQL extensions
+
+To [introspect](/orm/prisma-schema/introspection) PostgreSQL extensions currently activated in your database and add relevant extensions to your Prisma schema, run `npx prisma db pull`.
+
+Many PostgreSQL extensions are not relevant to the Prisma schema. For example, some extensions are intended for database administration tasks that do not change the schema. If all these extensions were included, the list of extensions would be very long. To avoid this, Prisma maintains an allowlist of known relevant extensions. The current allowlist is the following:
+
+- [`citext`](https://www.postgresql.org/docs/current/citext.html): provides a case-insensitive character string type, `citext`
+- [`pgcrypto`](https://www.postgresql.org/docs/current/pgcrypto.html): provides cryptographic functions, like `gen_random_uuid()`, to generate universally unique identifiers (UUIDs v4)
+- [`uuid-ossp`](https://www.postgresql.org/docs/current/uuid-ossp.html): provides functions, like `uuid_generate_v4()`, to generate universally unique identifiers (UUIDs v4)
+- [`postgis`](https://postgis.net/): adds GIS (Geographic Information Systems) support
+
+**Note**: Since PostgreSQL v13, `gen_random_uuid()` can be used without an extension to generate universally unique identifiers (UUIDs v4).
+
+Extensions are introspected as follows:
+
+- The first time you introspect, all database extensions that are on the allowlist are added to your Prisma schema
+- When you re-introspect, the behavior depends on whether the extension is on the allowlist or not.
+ - Extensions on the allowlist:
+ - are **added** to your Prisma schema if they are in the database but not in the Prisma schema
+ - are **kept** in your Prisma schema if they are in the Prisma schema and in the database
+ - are **removed** from your Prisma schema if they are in the Prisma schema but not the database
+ - Extensions not on the allowlist:
+ - are **kept** in your Prisma schema if they are in the Prisma schema and in the database
+ - are **removed** from your Prisma schema if they are in the Prisma schema but not the database
+
+The `version` argument will not be added to the Prisma schema when you introspect.
+
+## How to migrate PostgreSQL extensions
+
+You can update your list of PostgreSQL extensions in your Prisma schema and apply the changes to your database with [Prisma Migrate](/orm/prisma-migrate).
+
+This works in a similar way to migration of other elements of your Prisma schema, such as models or fields. However, there are the following differences:
+
+- If you remove an extension from your schema but it is still activated on your database, Prisma Migrate will not deactivate it from the database.
+- If you add a new extension to your schema, it will only be activated if it does not already exist in the database, because the extension may already have been created manually.
+- If you remove the `version` or `schema` arguments from the extension definition, it has no effect to the extensions in the database in the following migrations.
diff --git a/docs/200-orm/100-prisma-schema/index.mdx b/docs/200-orm/100-prisma-schema/index.mdx
new file mode 100644
index 0000000000..4ab105016c
--- /dev/null
+++ b/docs/200-orm/100-prisma-schema/index.mdx
@@ -0,0 +1,11 @@
+---
+title: 'Prisma schema'
+metaTitle: 'Prisma schema'
+metaDescription: 'Learn everything you need to know about the Prisma schema.'
+staticLink: true
+toc: false
+---
+
+## In this section
+
+
diff --git a/docs/200-orm/100-prisma-schema/prisma-schema/relations-intro.png b/docs/200-orm/100-prisma-schema/prisma-schema/relations-intro.png
new file mode 100644
index 0000000000..47bb895580
Binary files /dev/null and b/docs/200-orm/100-prisma-schema/prisma-schema/relations-intro.png differ
diff --git a/docs/200-orm/100-prisma-schema/prisma-schema/sample-database.png b/docs/200-orm/100-prisma-schema/prisma-schema/sample-database.png
new file mode 100644
index 0000000000..9aef1eb524
Binary files /dev/null and b/docs/200-orm/100-prisma-schema/prisma-schema/sample-database.png differ
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx
new file mode 100644
index 0000000000..94af6c6b46
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/005-introduction.mdx
@@ -0,0 +1,172 @@
+---
+title: 'Introduction'
+metaTitle: 'Introduction to Prisma Client'
+metaDescription: 'Learn how to set up Prisma Client.'
+---
+
+
+
+Prisma Client is an auto-generated and type-safe query builder that's _tailored_ to your data. The easiest way to get started with Prisma Client is by following the **[Quickstart](/getting-started/quickstart)**.
+
+
+ Quickstart (5 min)
+
+
+The setup instructions [below](#set-up) provide a high-level overview of the steps needed to set up Prisma Client. If you want to get started using Prisma Client with your own database, follow one of these guides:
+
+
+ Set up a new project from scratch
+
+
+
+
+ Add Prisma to an existing project
+
+
+
+
+## Set up
+
+### 1. Prerequisites
+
+In order to set up Prisma Client, you need a [Prisma schema file](/orm/prisma-schema) with your database connection, the Prisma Client generator, and at least one model:
+
+```prisma file=schema.prisma
+datasource db {
+ url = env("DATABASE_URL")
+ provider = "postgresql"
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ email String @unique
+ name String?
+}
+```
+
+Also make sure to [install the Prisma CLI](/orm/tools/prisma-cli#installation):
+
+```
+npm install prisma --save-dev
+npx prisma
+```
+
+### 2. Installation
+
+Install Prisma Client in your project with the following command:
+
+```
+npm install @prisma/client
+```
+
+This command also runs the `prisma generate` command, which generates Prisma Client into the [`node_modules/.prisma/client`](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package) directory.
+
+### 3. Importing Prisma Client
+
+There are multiple ways to import Prisma Client in your project depending on your use case:
+
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+// use `prisma` in your application to read and write data in your DB
+```
+
+
+
+
+
+```js
+const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+// use `prisma` in your application to read and write data in your DB
+```
+
+
+
+
+
+For edge environments, you can import Prisma Client as follows:
+
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client/edge'
+
+const prisma = new PrismaClient()
+// use `prisma` in your application to read and write data in your DB
+```
+
+
+
+
+
+```js
+const { PrismaClient } = require('@prisma/client/edge')
+
+const prisma = new PrismaClient()
+// use `prisma` in your application to read and write data in your DB
+```
+
+
+
+
+
+For Deno, you can import Prisma Client as follows:
+
+```ts file=lib/prisma.ts
+import { PrismaClient } from './generated/client/deno/edge.ts'
+
+const prisma = new PrismaClient()
+// use `prisma` in your application to read and write data in your DB
+```
+
+The import path will depend on the custom `output` specified in Prisma Client's [`generator`](/orm/reference/prisma-schema-reference#fields-1) block in your Prisma schema.
+
+### 4. Use Prisma Client to send queries to your database
+
+Once you have instantiated `PrismaClient`, you can start sending queries in your code:
+
+```ts
+// run inside `async` function
+const newUser = await prisma.user.create({
+ data: {
+ name: 'Alice',
+ email: 'alice@prisma.io',
+ },
+})
+
+const users = await prisma.user.findMany()
+```
+
+
+
+All Prisma Client methods return an instance of [`PrismaPromise`](/orm/reference/prisma-client-reference#prismapromise-behavior) which only executes when you call `await` or `.then()` or `.catch()`.
+
+
+
+### 5. Evolving your application
+
+Whenever you make changes to your database that are reflected in the Prisma schema, you need to manually re-generate Prisma Client to update the generated code in the `node_modules/.prisma/client` directory:
+
+```
+prisma generate
+```
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx
new file mode 100644
index 0000000000..4ff9d3e534
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/010-generating-prisma-client.mdx
@@ -0,0 +1,162 @@
+---
+title: 'Generating Prisma Client'
+metaTitle: 'Generating Prisma Client'
+metaDescription: 'This page explains how to generate Prisma Client. It also provides additional context on the generated client, typical workflows and Node.js configuration.'
+---
+
+
+
+Prisma Client is an auto-generated database client that's tailored to your database schema. By default, Prisma Client is generated into the `node_modules/.prisma/client` folder, but [you can specify a custom location](#using-a-custom-output-path).
+
+To generate and instantiate Prisma Client:
+
+1. Ensure that you have [Prisma CLI installed on your machine](/orm/tools/prisma-cli#installation).
+
+1. Add the following `generator` definition to your Prisma schema:
+
+ ```prisma
+ generator client {
+ provider = "prisma-client-js"
+ }
+ ```
+
+1. Install the `@prisma/client` npm package:
+
+ ```terminal
+ npm install @prisma/client
+ ```
+
+
+
+ We recommend that you keep **both** the `prisma` and `@prisma/client` packages in sync to avoid any unexpected errors or behaviors.
+
+
+
+1. Generate Prisma Client with the following command:
+
+ ```terminal
+ prisma generate
+ ```
+
+1. You can now [instantiate Prisma Client](instantiate-prisma-client) in your code:
+
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+const prisma = new PrismaClient()
+// use `prisma` in your application to read and write data in your DB
+```
+
+
+
+
+
+```js
+const { PrismaClient } = require('@prisma/client')
+const prisma = new PrismaClient()
+// use `prisma` in your application to read and write data in your DB
+```
+
+
+
+
+
+> **Important**: You need to re-run the `prisma generate` command after every change that's made to your Prisma schema to update the generated Prisma Client code.
+
+Here is a graphical illustration of the typical workflow for generation of Prisma Client:
+
+
+
+Note also that `prisma generate` is _automatically_ invoked when you're installing the `@prisma/client` npm package. So, when you're initially setting up Prisma Client, you can typically save the third step from the list above.
+
+
+
+## The `@prisma/client` npm package
+
+The `@prisma/client` npm package consists of two key parts:
+
+- The `@prisma/client` module itself, which only changes when you re-install the package
+- The `.prisma/client` folder, which is the [default location](#using-a-custom-output-path) for the unique Prisma Client generated from your schema
+
+`@prisma/client/index.d.ts` exports `.prisma/client`:
+
+```ts
+export * from '.prisma/client'
+```
+
+This means that you still import `@prisma/client` in your own `.ts` files:
+
+```ts
+import { PrismaClient } from '@prisma/client'
+```
+
+Prisma Client is generated from your Prisma schema and is unique to your project. Each time you change the schema (for example, by performing a [schema migration](/orm/prisma-migrate)) and run `prisma generate`, Prisma Client's code changes:
+
+
+
+The `.prisma` folder is unaffected by [pruning](https://docs.npmjs.com/cli/prune.html) in Node.js package managers.
+
+## The location of Prisma Client
+
+If you do not specify a custom `output` in the `generator` block, Prisma Client is generated into the `./node_modules/.prisma/client` folder by default. There are [some advantages to maintaining the default location](#why-is-prisma-client-generated-into-node_modulesprismaclient-by-default).
+
+### Using a custom `output` path
+
+You can also specify a custom `output` path on the `generator` configuration, for example (assuming your `schema.prisma` file is located at the default `prisma` subfolder):
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+ output = "../src/generated/client"
+}
+```
+
+After running `prisma generate` for that schema file, the Prisma Client package will be located in:
+
+```
+./src/generated/client
+```
+
+To import the `PrismaClient` from a custom location (for example, from a file named `./src/script.ts`):
+
+```ts
+import { PrismaClient } from './generated/client'
+```
+
+### Why is Prisma Client generated into `node_modules/.prisma/client` by default?
+
+#### Importing Prisma Client
+
+By generating Prisma Client into `node_modules/.prisma/client` and exporting it from `@prisma/client`, you can import it and instantiate Prisma Client in your code as follows:
+
+```js
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+// use `prisma` in your application to read and write data in your DB
+```
+
+or
+
+```js
+const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+
+// use `prisma` in your application to read and write data in your DB
+```
+
+#### Keeping the query engine out of version control by default
+
+Prisma Client uses a [_query engine_](/orm/more/under-the-hood/engines) to run queries against the database. This query engine is downloaded when `prisma generate` is invoked and stored in the `output` path together with the generated Client.
+
+By generating Prisma Client into `node_modules`, the query engine is usually kept out of version control by default since `node_modules` is typically ignored for version control.
+When using a custom `output` path for the generated Prisma Client, it is advised to exclude it from your version control. For Git, this means adding the `output` path to your `.gitignore` file.
+
+## Generating Prisma Client in the `postinstall` hook of `@prisma/client`
+
+The `@prisma/client` package defines its own `postinstall` hook that's being executed whenever the package is being installed. This hook invokes the `prisma generate` command which in turn generates the Prisma Client code into the default location `node_modules/.prisma/client`. Notice that this requires the `prisma` CLI to be available, either as local dependency or as a global installation. It is recommended to always install the `prisma` package as a development dependency, using `npm install prisma --save-dev`, to avoid versioning conflicts.
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/015-instantiate-prisma-client.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/015-instantiate-prisma-client.mdx
new file mode 100644
index 0000000000..45ef965454
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/015-instantiate-prisma-client.mdx
@@ -0,0 +1,63 @@
+---
+title: 'Instantiating Prisma Client'
+metaTitle: 'Instantiating Prisma Client'
+metaDescription: 'How to create and use an instance of PrismaClient in your app.'
+tocDepth: 3
+---
+
+
+
+The following example demonstrates how to import and instantiate your [generated client](generating-prisma-client) from the [default path](generating-prisma-client#using-a-custom-output-path).
+
+
+
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+```
+
+
+
+
+
+```js
+const { PrismaClient } = require('@prisma/client')
+
+const prisma = new PrismaClient()
+```
+
+
+
+
+
+:::tip
+
+You can further customize `PrismaClient` with [constructor parameters](/orm/reference/prisma-client-reference#prismaclient) - for example, set [logging levels](/orm/prisma-client/observability-and-logging/logging) or customize [error formatting](error-formatting).
+
+:::
+
+## The number of `PrismaClient` instances matters
+
+Your application should generally only create **one instance** of `PrismaClient`. How to achieve this depends on whether you are using Prisma in a [long-running application](/orm/prisma-client/setup-and-configuration/databases-connections#prismaclient-in-long-running-applications) or in a [serverless environment](/orm/prisma-client/setup-and-configuration/databases-connections#prismaclient-in-serverless-environments) .
+
+The reason for this is that each instance of `PrismaClient` manages a connection pool, which means that a large number of clients can **exhaust the database connection limit**. This applies to all database connectors.
+
+If you use the **MongoDB connector**, connections are managed by the MongoDB driver connection pool. If you use a **relational database connector**, connections are managed by Prisma's [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool). Each instance of `PrismaClient` creates its own pool.
+
+1. Each client creates its own instance of the [query engine](/orm/more/under-the-hood/engines).
+1. Each query engine creates a [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) with a default pool size of:
+
+ - `num_physical_cpus * 2 + 1` for relational databases
+ - [`100` for MongoDB](https://docs.mongodb.com/manual/reference/connection-string/#mongodb-urioption-urioption.maxPoolSize)
+
+1. Too many connections may start to **slow down your database** and eventually lead to errors such as:
+
+ ```
+ Error in connector: Error querying the database: db error: FATAL: sorry, too many clients already
+ at PrismaClientFetcher.request
+ ```
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/100-connection-management.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/100-connection-management.mdx
new file mode 100644
index 0000000000..c74b5fbf5f
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/100-connection-management.mdx
@@ -0,0 +1,108 @@
+---
+title: 'Connection management'
+metaTitle: 'Connection management'
+metaDescription: 'This page explains how database connections are handled with Prisma Client and how to manually connect and disconnect your database.'
+tocDepth: 3
+---
+
+
+
+`PrismaClient` connects and disconnects from your data source using the following two methods:
+
+- [`$connect()`](/orm/reference/prisma-client-reference#connect-1)
+- [`$disconnect()`](/orm/reference/prisma-client-reference#disconnect-1)
+
+In most cases, you **do not need to explicitly call these methods**. `PrismaClient` automatically connects when you run your first query, creates a [connection pool](connection-pool), and disconnects when the Node.js process ends.
+
+See the [connection management guide](/orm/prisma-client/setup-and-configuration/databases-connections) for information about managing connections for different deployment paradigms (long-running processes and serverless functions).
+
+
+
+## `$connect()`
+
+It is not necessary to call [`$connect()`](/orm/reference/prisma-client-reference#connect-1) thanks to the _lazy connect_ behavior: The `PrismaClient` instance connects lazily when the first request is made to the API (`$connect()` is called for you under the hood).
+
+### Calling `$connect()` explicitly
+
+If you need the first request to respond instantly and cannot wait for a lazy connection to be established, you can explicitly call `prisma.$connect()` to establish a connection to the data source:
+
+```ts
+const prisma = new PrismaClient()
+
+// run inside `async` function
+await prisma.$connect()
+```
+
+## `$disconnect()`
+
+When you call [`$disconnect()`](/orm/reference/prisma-client-reference#disconnect-1) , Prisma Client:
+
+1. Runs the [`beforeExit` hook](#exit-hooks)
+2. Ends the Query Engine child process and closes all connections
+
+In a long-running application such as a GraphQL API, which constantly serves requests, it does not make sense to `$disconnect()` after each request - it takes time to establish a connection, and doing so as part of each request will slow down your application.
+
+:::tip
+
+To avoid too _many_ connections in a long-running application, we recommend that you [use a single instance of `PrismaClient` across your application](/orm/prisma-client/setup-and-configuration/instantiate-prisma-client#the-number-of-prismaclient-instances-matters).
+
+:::
+
+### Calling `$disconnect()` explicitly
+
+One scenario where you should call `$disconnect()` explicitly is where a script:
+
+1. Runs **infrequently** (for example, a scheduled job to send emails each night), which means it does not benefit from a long-running connection to the database _and_
+2. Exists in the context of a **long-running application**, such as a background service. If the application never shuts down, Prisma Client never disconnects.
+
+The following script creates a new instance of `PrismaClient`, performs a task, and then disconnects - which closes the connection pool:
+
+```ts highlight=19;normal
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+const emailService = new EmailService()
+
+async function main() {
+ const allUsers = await prisma.user.findMany()
+ const emails = allUsers.map((x) => x.email)
+
+ await emailService.send(emails, 'Hello!')
+}
+
+main()
+ .then(async () => {
+ await prisma.$disconnect()
+ })
+ .catch(async (e) => {
+ console.error(e)
+ await prisma.$disconnect()
+ process.exit(1)
+ })
+```
+
+If the above script runs multiple times in the context of a long-running application _without_ calling `$disconnect()`, a new connection pool is created with each new instance of `PrismaClient`.
+
+## Exit hooks
+
+
+
+From Prisma 5.0.0, the `beforeExit` hook only applies to the [binary Query Engine](/orm/more/under-the-hood/engines#configuring-the-query-engine).
+
+
+
+The `beforeExit` hook runs when Prisma is triggered externally (e.g. via a `SIGINT` signal) to shut down, and allows you to run code _before_ Prisma Client disconnects - for example, to issue queries as part of a graceful shutdown of a service:
+
+```ts
+const prisma = new PrismaClient()
+
+prisma.$on('beforeExit', async () => {
+ console.log('beforeExit hook')
+ // PrismaClient still available
+ await prisma.message.create({
+ data: {
+ message: 'Shutting down server',
+ },
+ })
+})
+```
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/115-connection-pool.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/115-connection-pool.mdx
new file mode 100644
index 0000000000..54e52841b6
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/115-connection-pool.mdx
@@ -0,0 +1,217 @@
+---
+title: Connection pool
+metaDescription: Prisma's query engine creates a connection pool to store and manage database connections.
+tocDepth: 4
+---
+
+
+
+The query engine manages a **connection pool** of database connections. The pool is created when Prisma Client opens the _first_ connection to the database, which can happen in one of two ways:
+
+- By [explicitly calling `$connect()`](connection-management#connect) _or_
+- By running the first query, which calls `$connect()` under the hood
+
+Relational database connectors use Prisma's own connection pool, and the MongoDB connectors uses the [MongoDB driver connection pool](https://github.com/mongodb/specifications/blob/master/source/connection-monitoring-and-pooling/connection-monitoring-and-pooling.rst).
+
+
+
+## Relational databases
+
+The relational database connectors use Prisma's connection pool. The connection pool has a **connection limit** and a **pool timeout**, which are controlled by connection URL parameters.
+
+### How the connection pool works
+
+The following steps describe how the query engine uses the connection pool:
+
+1. The query engine instantiates a connection pool with a [configurable pool size](#setting-the-connection-pool-size) and [pool timeout](#setting-the-connection-pool-timeout).
+1. The query engine creates one connection and adds it to the connection pool.
+1. When a query comes in, the query engine reserves a connection from the pool to process query.
+1. If there are no idle connections available in the connection pool, the query engine opens additional database connections and adds them to the connection pool until the number of database connections reaches the limit defined by `connection_limit`.
+1. If the query engine cannot reserve a connection from the pool, queries are added to a FIFO (First In First Out) queue in memory. FIFO means that queries are processed in the order they enter the queue.
+1. If the query engine cannot process a query in the queue for **before the [time limit](#default-pool-timeout)**, it throws an exception with error code `P2024` for that query and moves on to the next one in the queue.
+
+If you consistently experience pool timeout errors, you need to [optimize the connection pool](/orm/prisma-client/setup-and-configuration/databases-connections#optimizing-the-connection-pool) .
+
+### Connection pool size
+
+#### Default connection pool size
+
+The default number of connections (pool size) is calculated with the following formula:
+
+```bash
+num_physical_cpus * 2 + 1
+```
+
+`num_physical_cpus` represents the number of physical CPUs on the machine your application is running on. If your machine has **four** physical CPUs, your connection pool will contain **nine** connections (`4 * 2 + 1 = 9`).
+
+Although the formula represents a good starting point, the [recommended connection limit](/orm/prisma-client/setup-and-configuration/databases-connections#recommended-connection-pool-size) also depends on your deployment paradigm - particularly if you are using serverless.
+
+#### Setting the connection pool size
+
+You can specify the number of connections by explicitly setting the `connection_limit` parameter in your database connection URL. For example, with the following `datasource` configuration in your [Prisma schema](/orm/prisma-schema) the connection pool will have exactly five connections:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5"
+}
+```
+
+#### Viewing the connection pool size
+
+The number of connections Prisma Client uses can be viewed using [logging](/orm/prisma-client/observability-and-logging/logging) and [metrics](/orm/prisma-client/observability-and-logging/metrics).
+
+Using the `info` [logging level](/orm/reference/prisma-client-reference#log-levels), you can log the number of connections in a connection pool that are opened when Prisma Client is instantiated.
+
+For example, consider the following Prisma Client instance and invocation:
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient({
+ log: ['info'],
+})
+
+async function main() {
+ await prisma.user.findMany()
+}
+
+main()
+```
+
+
+
+
+```text no-copy
+prisma:info Starting a postgresql pool with 21 connections.
+```
+
+
+
+
+When the `PrismaClient` class was instantiated, the logging notified `stdout` that a connection pool with 21 connections was started.
+
+
+
+Note that the output generated by `log: ['info']` can change in any release without notice. Be aware of this in case you are relying on the output in your application or a tool that you're building.
+
+
+
+If you need even more insights into the size of your connection pool and the amount of in-use and idle connection, you can use the [metrics](/orm/prisma-client/observability-and-logging/metrics) feature (which is currently in Preview).
+
+Consider the following example:
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ await Promise.all([prisma.user.findMany(), prisma.post.findMany()])
+
+ const metrics = await prisma.$metrics.json()
+ console.dir(metrics, { depth: Infinity })
+}
+
+main()
+```
+
+
+
+
+```json no-copy
+{
+ "counters": [
+ // ...
+ {
+ "key": "prisma_pool_connections_open",
+ "labels": {},
+ "value": 2,
+ "description": "Number of currently open Pool Connections"
+ }
+ ],
+ "gauges": [
+ // ...
+ {
+ "key": "prisma_pool_connections_busy",
+ "labels": {},
+ "value": 0,
+ "description": "Number of currently busy Pool Connections (executing a datasource query)"
+ },
+ {
+ "key": "prisma_pool_connections_idle",
+ "labels": {},
+ "value": 21,
+ "description": "Number of currently unused Pool Connections (waiting for the next datasource query to run)"
+ },
+ {
+ "key": "prisma_pool_connections_opened_total",
+ "labels": {},
+ "value": 2,
+ "description": "Total number of Pool Connections opened"
+ }
+ ],
+ "histograms": [
+ /** ... **/
+ ]
+}
+```
+
+
+
+
+
+
+For more details on what is available in the metrics output, see the [About metrics](/orm/prisma-client/observability-and-logging/metrics#about-metrics) section.
+
+
+
+### Connection pool timeout
+
+#### Default pool timeout
+
+The default connection pool timeout is 10 seconds. If the Query Engine does not get a connection from the database connection pool within that time, it throws an exception and moves on to the next query in the queue.
+
+#### Setting the connection pool timeout
+
+You can specify the pool timeout by explicitly setting the `pool_timeout` parameter in your database connection URL. In the following example, the pool times out after `2` seconds:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=2"
+}
+```
+
+#### Disabling the connection pool timeout
+
+You disable the connection pool timeout by setting the `pool_timeout` parameter to `0`:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=0"
+}
+```
+
+You can choose to [disable the connection pool timeout if queries **must** remain in the queue](/orm/prisma-client/setup-and-configuration/databases-connections#disabling-the-pool-timeout) - for example, if you are importing a large number of records in parallel and are confident that the queue will not use up all available RAM before the job is complete.
+
+## MongoDB
+
+The MongoDB connector does not use the Prisma connection pool. The connection pool is managed internally by the MongoDB driver and [configured via connection string parameters](https://docs.mongodb.com/manual/reference/connection-string/#connection-pool-options).
+
+## External connection poolers
+
+You cannot increase the `connection_limit` beyond what the underlying database can support. This is a particular challenge in serverless environments, where each function manages an instance of `PrismaClient` - and its own connection pool.
+
+Consider introducing [an external connection pooler like PgBouncer](/orm/prisma-client/setup-and-configuration/databases-connections#pgbouncer) to prevent your application or functions from exhausting the database connection limit.
+
+## Manual database connection handling
+
+When using Prisma, the database connections are handled on an [engine](https://github.com/prisma/prisma-engines)-level. This means they're not exposed to the developer and it's not possible to manually access them.
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/200-pgbouncer.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/200-pgbouncer.mdx
new file mode 100644
index 0000000000..18aa50bfce
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/200-pgbouncer.mdx
@@ -0,0 +1,82 @@
+---
+title: Configure Prisma Client with PgBouncer
+metaTitle: Configure Prisma Client with PgBouncer
+---
+
+
+
+An external connection pooler like PgBouncer holds a connection pool to the database, and proxies incoming client connections by sitting between Prisma Client and the database. This reduces the number of processes a database has to handle at any given time.
+
+Usually, this works transparently, but some connection poolers only support a limited set of functionality. One common feature that external connection poolers do not support are named prepared statements, which Prisma uses. For these cases, Prisma can be configured to behave differently.
+
+
+
+## PgBouncer
+
+### Set PgBouncer to transaction mode
+
+For Prisma Client to work reliably, PgBouncer must run in [**Transaction mode**](https://www.pgbouncer.org/features.html).
+
+Transaction mode offers a connection for every transaction – a requirement for the Prisma Client to work with PgBouncer.
+
+### Add `pgbouncer=true` to the connection URL
+
+To use Prisma Client with PgBouncer, add the `?pgbouncer=true` flag to the PostgreSQL connection URL:
+
+```
+postgresql://USER:PASSWORD@HOST:PORT/DATABASE?pgbouncer=true
+```
+
+> Note: `PORT` specified for PgBouncer pooling is sometimes different from the default `5432` port. Check your database provider docs for the correct port number.
+
+
+ How `pgbouncer` mode works in Prisma
+
+- Prisma opens a transaction for every query – even when just reading data, allowing Prisma to use prepared statements.
+- Prisma does not try to set the `search_path`, which is not supported by PgBouncer.
+- Prisma cleans up already present prepared statements in the connection by running `DEALLOCATE ALL` before preparing and executing Prisma Client queries.
+- Prisma also disables any prepared statement or type query caches.
+
+
+
+### Prisma Migrate and PgBouncer workaround
+
+Prisma Migrate uses **database transactions** to check out the current state of the database and the migrations table. However, the Schema Engine is designed to use a **single connection to the database**, and does not support connection pooling with PgBouncer. If you attempt to run Prisma Migrate commands in any environment that uses PgBouncer for connection pooling, you might see the following error:
+
+```bash
+Error: undefined: Database error
+Error querying the database: db error: ERROR: prepared statement "s0" already exists
+```
+
+To work around this issue, you must connect directly to the database rather than going through PgBouncer. To achieve this, you can use the [`directUrl`](/orm/reference/prisma-schema-reference#fields) field in your [`datasource`](/orm/reference/prisma-schema-reference#datasource) block.
+
+For example, consider the following `datasource` block:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgres://USER:PASSWORD@HOST:PORT/DATABASE?pgbouncer=true"
+ directUrl = "postgres://USER:PASSWORD@HOST:PORT/DATABASE"
+}
+```
+
+The block above uses a PgBouncer connection string as the primary URL using `url`, allowing Prisma Client to take advantage of the PgBouncer connection pooler.
+
+It also provides a connection string directly to the database, without PgBouncer, using the `directUrl` field. This connection string will be used when commands that require a single connection to the database, such as `prisma migrate dev` or `prisma db push`, are invoked.
+
+### PgBouncer with different database providers
+
+There are sometimes minor differences in how to connect directly to a Postgres database that depend on the provider hosting the database.
+
+Below are links to information on how to set up these connections with providers who have setup steps not covered here in our documentation:
+
+- [Connecting directly to a PostgreSQL database hosted on Digital Ocean](https://github.com/prisma/prisma/issues/6157)
+- [Connecting directly to a PostgreSQL database hosted on ScaleGrid](https://github.com/prisma/prisma/issues/6701#issuecomment-824387959)
+
+## Supabase Supavisor
+
+Supabase's Supavisor behaves similarly to [PgBouncer](#pgbouncer). You can add `?pgbouncer=true` to your connection pooled connection string available via your [Supabase database settings](https://supabase.com/dashboard/project/_/settings/database).
+
+## Other external connection poolers
+
+Although Prisma does not have explicit support for other connection poolers, if the limitations are similar to the ones of [PgBouncer](#pgbouncer) you can usually also use `pgbouncer=true` in your connection string to put Prisma in a mode that works with them as well.
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx
new file mode 100644
index 0000000000..856fe1e92e
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/index.mdx
@@ -0,0 +1,337 @@
+---
+title: Database connections
+metaTitle: Database connections
+metaDescription: 'Databases connections'
+tocDepth: 3
+---
+
+
+
+Databases can handle a limited number of concurrent connections. Each connection requires RAM, which means that simply increasing the database connection limit without scaling available resources:
+
+- ✔ might allow more processes to connect _but_
+- ✘ significantly affects **database performance**, and can result in the database being **shut down** due to an out of memory error
+
+The way your application **manages connections** also impacts performance. This guide describes how to approach connection management in [serverless environments](#serverless-environments-faas) and [long-running processes](#long-running-processes).
+
+
+
+This guide focuses on **relational databases** and how to configure and tune the Prisma connection pool (MongoDB uses the MongoDB driver connection pool).
+
+
+
+
+
+## Long-running processes
+
+Examples of long-running processes include Node.js applications hosted on a service like Heroku or a virtual machine. Use the following checklist as a guide to connection management in long-running environments:
+
+- Start with the [recommended pool size (`connection_limit`)](#recommended-connection-pool-size) and [tune it](#optimizing-the-connection-pool)
+- Make sure you have [**one** global instance of `PrismaClient`](#prismaclient-in-long-running-applications)
+
+### Recommended connection pool size
+
+The recommended connection pool size (`connection_limit`) to [start with](#optimizing-the-connection-pool) for long-running processes is the **default pool size** (`num_physical_cpus * 2 + 1`) ÷ **number of application instances**.
+
+
+
+`num_physical_cpus` refers to the the number of CPUs of the machine your application is running on.
+
+
+
+If you have **one** application instances:
+
+- The default pool size applies by default (`num_physical_cpus * 2 + 1`) - you do not need to set the `connection_limit` parameter.
+- You can optionally [tune the pool size](#optimizing-the-connection-pool).
+
+If you have **multiple** application instances:
+
+- You must **manually** [set the `connection_limit` parameter](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#setting-the-connection-pool-size) . For example, if your calculated pool size is _10_ and you have _2_ instances of your app, the `connection_limit` parameter should be **no more than _5_**.
+- You can optionally [tune the pool size](#optimizing-the-connection-pool).
+
+### `PrismaClient` in long-running applications
+
+In **long-running** applications, we recommend that you:
+
+- ✔ Create **one** instance of `PrismaClient` and re-use it across your application
+- ✔ Assign `PrismaClient` to a global variable _in dev environments only_ to [prevent hot reloading from creating new instances](#prevent-hot-reloading-from-creating-new-instances-of-prismaclient)
+
+#### Re-using a single `PrismaClient` instance
+
+To re-use a single instance, create a module that exports a `PrismaClient` object:
+
+```ts file=client.ts
+import { PrismaClient } from '@prisma/client'
+
+let prisma = new PrismaClient()
+
+export default prisma
+```
+
+The object is [cached](https://nodejs.org/api/modules.html#modules_caching) the first time the module is imported. Subsequent requests return the cached object rather than creating a new `PrismaClient`:
+
+```ts file=app.ts
+import prisma from './client'
+
+async function main() {
+ const allUsers = await prisma.user.findMany()
+}
+
+main()
+```
+
+You do not have to replicate the example above exactly - the goal is to make sure `PrismaClient` is cached. For example, you can [instantiate `PrismaClient` in the `context` object](https://github.com/prisma/prisma-examples/blob/9f1a6b9e7c25b9e1851bd59b273046158d748995/typescript/graphql-express/src/context.ts#L9) that you [pass into an Express app](https://github.com/prisma/prisma-examples/blob/9f1a6b9e7c25b9e1851bd59b273046158d748995/typescript/graphql-express/src/server.ts#L12).
+
+#### Do not explicitly `$disconnect()`
+
+You [do not need to explicitly `$disconnect()`](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management#calling-disconnect-explicitly) in the context of a long-running application that is continuously serving requests. Opening a new connection takes time and can slow down your application if you disconnect after each query.
+
+#### Prevent hot reloading from creating new instances of `PrismaClient`
+
+Frameworks like [Next.js](https://nextjs.org/) support hot reloading of changed files, which enables you to see changes to your application without restarting. However, if the framework refreshes the module responsible for exporting `PrismaClient`, this can result in **additional, unwanted instances of `PrismaClient` in a development environment**.
+
+As a workaround, you can store `PrismaClient` as a global variable in development environments only, as global variables are not reloaded:
+
+
+```ts file=client.ts
+import { PrismaClient } from '@prisma/client'
+
+const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }
+
+export const prisma =
+ globalForPrisma.prisma || new PrismaClient()
+
+if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
+```
+
+The way that you import and use Prisma Client does not change:
+
+```ts file=app.ts
+import { prisma } from './client'
+
+async function main() {
+ const allUsers = await prisma.user.findMany()
+}
+
+main()
+```
+
+## Serverless environments (FaaS)
+
+Examples of serverless environments include Node.js functions hosted on AWS Lambda, Vercel or Netlify Functions. Use the following checklist as a guide to connection management in serverless environments:
+
+- Familiarize yourself with the [serverless connection management challenge](#the-serverless-challenge)
+- [Set pool size (`connection_limit`)](#recommended-connection-pool-size-1) based on whether you have an external connection pooler, and optionally [tune the pool size](#optimizing-the-connection-pool)
+- [Instantiate `PrismaClient` outside the handler](#instantiate-prismaclient-outside-the-handler) and do not explicitly `$disconnect()`
+- Configure [function concurrency](#concurrency-limits) and handle [idle connections](#zombie-connections)
+
+### The serverless challenge
+
+In a serverless environment, each function creates **its own instance** of `PrismaClient`, and each client instance has its own connection pool.
+
+Consider the following example, where a single AWS Lambda function uses `PrismaClient` to connect to a database. The `connection_limit` is **3**:
+
+
+
+A traffic spike causes AWS Lambda to spawn two additional lambdas to handle the increased load. Each lambda creates an instance of `PrismaClient`, each with a `connection_limit` of **3**, which results in a maximum of **9** connections to the database:
+
+
+
+200 _concurrent functions_ (and therefore 600 possible connections) responding to a traffic spike 📈 can exhaust the database connection limit very quickly. Furthermore, any functions that are **paused** keep their connections open by default and block them from being used by another function.
+
+1. Start by [setting the `connection_limit` to `1`](#recommended-connection-pool-size-1)
+2. If a smaller pool size is not enough, consider using an [external connection pooler like PgBouncer](#external-connection-poolers)
+
+### Recommended connection pool size
+
+The recommended pool size (`connection_limit`) in serverless environments depends on:
+
+- Whether you are using an [external connection pooler](#external-connection-poolers)
+- Whether your functions are [designed to send queries in parallel](#optimizing-for-parallel-requests)
+
+#### Without an external connection pooler
+
+If you are **not** using an external connection pooler, _start_ by setting the pool size (`connection_limit`) to **1**, then [optimize](#optimizing-for-parallel-requests). Each incoming request starts a short-lived Node.js process, and many concurrent functions with a high `connection_limit` can quickly **exhaust the _database_ connection limit** during a traffic spike.
+
+The following example demonstrates how to set the `connection_limit` to 1 in your connection URL:
+
+
+
+
+```
+postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=public&connection_limit=1
+```
+
+
+
+
+```
+mysql://USER:PASSWORD@HOST:PORT/DATABASE?connection_limit=1
+```
+
+
+
+
+:::tip
+
+If you are using AWS Lambda and _not_ configuring a `connection_limit`, refer to the following GitHub issue for information about the expected default pool size: https://github.com/prisma/docs/issues/667
+
+:::
+
+#### With an external connection pooler
+
+If you are using an external connection pooler, use the default pool size (`num_physical_cpus * 2 + 1`) as a starting point and then [tune the pool size](#optimizing-the-connection-pool). The external connection pooler should prevent a traffic spike from overwhelming the database.
+
+#### Optimizing for parallel requests
+
+If you rarely or never exceed the database connection limit with the pool size set to 1, you can further optimize the connection pool size. Consider a function that sends queries in parallel:
+
+```ts
+Promise.all() {
+ query1,
+ query2,
+ query3
+ query4,
+ ...
+}
+```
+
+If the `connection_limit` is 1, this function is forced to send queries **serially** (one after the other) rather than **in parallel**. This slows down the function's ability to process requests, and may result in pool timeout errors. Tune the `connection_limit` parameter until a traffic spike:
+
+- Does not exhaust the database connection limit
+- Does not result in pool timeout errors
+
+### `PrismaClient` in serverless environments
+
+#### Instantiate `PrismaClient` outside the handler
+
+Instantiate `PrismaClient` [outside the scope of the function handler](https://github.com/prisma/e2e-tests/blob/5d1041d3f19245d3d237d959eca94d1d796e3a52/platforms/serverless-lambda/index.ts#L3) to increase the chances of reuse. As long as the handler remains 'warm' (in use), the connection is potentially reusable:
+
+```ts highlight=3;normal
+import { PrismaClient } from '@prisma/client'
+
+const client = new PrismaClient()
+
+export async function handler() {
+ /* ... */
+}
+```
+
+#### Do not explicitly `$disconnect()`
+
+You [do not need to explicitly `$disconnect()`](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management#calling-disconnect-explicitly) at the end of a function, as there is a possibility that the container might be reused. Opening a new connection takes time and slows down your function's ability to process requests.
+
+### Other serverless considerations
+
+#### Container reuse
+
+There is no guarantee that subsequent nearby invocations of a function will hit the same container - for example, AWS can choose to create a new container at any time.
+
+Code should assume the container to be stateless and create a connection only if it does not exist - Prisma Client JS already implements this logic.
+
+#### Zombie connections
+
+Containers that are marked "to be removed" and are not being reused still **keep a connection open** and can stay in that state for some time (unknown and not documented from AWS). This can lead to sub-optimal utilization of the database connections.
+
+A potential solution is to **clean up idle connections** ([`serverless-mysql`](https://github.com/jeremydaly/serverless-mysql) implements this idea, but cannot be used with Prisma).
+
+#### Concurrency limits
+
+Depending on your serverless concurrency limit (the number of serverless functions running in parallel), you might still exhaust your database's connection limit. This can happen when too many functions are invoked concurrently, each with its own connection pool, which eventually exhausts the database connection limit. To prevent this, you can [set your serverless concurrency limit](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html) to a number lower than the maximum connection limit of your database divided by the number of connections used by each function invocation (as you might want to be able to connect from another client for other purposes).
+
+## Optimizing the connection pool
+
+If the query engine cannot [process a query in the queue before the time limit](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#how-the-connection-pool-works) , you will see connection pool timeout exceptions in your log. A connection pool timeout can occur if:
+
+- Many users are accessing your app simultaneously
+- You send a large number of queries in parallel (for example, using `await Promise.all()`)
+
+If you consistently experience connection pool timeouts after configuring the recommended pool size, you can further tune the `connection_limit` and `pool_timeout` parameters.
+
+### Increasing the pool size
+
+Increasing the pool size allows the query engine to process a larger number of queries in parallel. Be aware that your database must be able to support the increased number of concurrent connections, otherwise you will **exhaust the database connection limit**.
+
+To increase the pool size, manually set the `connection_limit` to a higher number:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public&connection_limit=40"
+}
+```
+
+> **Note**: Setting the `connection_limit` to 1 in serverless environments is a recommended starting point, but [this value can also be tuned](#optimizing-for-parallel-requests).
+
+### Increasing the pool timeout
+
+Increasing the pool timeout gives the query engine more time to process queries in the queue. You might consider this approach in the following scenario:
+
+- You have already increased the `connection_limit`.
+- You are confident that the queue will not grow beyond a certain size, otherwise **you will eventually run out of RAM**.
+
+To increase the pool timeout, set the `pool_timeout` parameter to a value larger than the default (10 seconds):
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=20"
+}
+```
+
+### Disabling the pool timeout
+
+Disabling the pool timeout prevents the query engine from throwing an exception after x seconds of waiting for a connection and allows the queue to build up. You might consider this approach in the following scenario:
+
+- You are submitting a large number of queries for a limited time - for example, as part of a job to import or update every customer in your database.
+- You have already increased the `connection_limit`.
+- You are confident that the queue will not grow beyond a certain size, otherwise **you will eventually run out of RAM**.
+
+To disable the pool timeout, set the `pool_timeout` parameter to `0`:
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=0"
+}
+```
+
+## External connection poolers
+
+Connection poolers like [Prisma Accelerate](/accelerate) and PgBouncer prevent your application from exhausting the database's connection limit.
+
+If you would like to use the Prisma CLI in order to perform other actions on your database ,e.g. migrations and introspection, you will need to add an environment variable that provides a direct connection to your database in the `datasource.directUrl` property in your Prisma schema:
+
+```env file=.env highlight=4,5;add
+# Connection URL to your database using PgBouncer.
+DATABASE_URL="postgres://root:password@127.0.0.1:54321/postgres?pgbouncer=true"
+
+# Direct connection URL to the database used for migrations
+DIRECT_URL="postgres://root:password@127.0.0.1:5432/postgres"
+```
+
+You can then update your `schema.prisma` to use the new direct URL:
+
+```prisma file=schema.prisma highlight=4;add
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ directUrl = env("DIRECT_URL")
+}
+```
+
+More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields).
+
+### Prisma Accelerate
+
+[Prisma Accelerate](/accelerate) is a managed external connection pooler built by Prisma that is integrated in the [Prisma Data Platform](/platform) and handles connection pooling for you.
+
+### PgBouncer
+
+PostgreSQL only supports a certain amount of concurrent connections, and this limit can be reached quite fast when the service usage goes up – especially in [serverless environments](#serverless-environments-faas).
+
+[PgBouncer](https://www.pgbouncer.org/) holds a connection pool to the database and proxies incoming client connections by sitting between Prisma Client and the database. This reduces the number of processes a database has to handle at any given time. PgBouncer passes on a limited number of connections to the database and queues additional connections for delivery when connections becomes available. To use PgBouncer, see [Configure Prisma Client with PgBouncer](/orm/prisma-client/setup-and-configuration/databases-connections/pgbouncer).
+
+### AWS RDS Proxy
+
+Due to the way AWS RDS Proxy pins connections, [it does not provide any connection pooling benefits](/orm/prisma-client/deployment/caveats-when-deploying-to-aws-platforms#aws-rds-proxy) when used together with Prisma Client.
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/serverless-connections-2.png b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/serverless-connections-2.png
new file mode 100644
index 0000000000..a933db1341
Binary files /dev/null and b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/serverless-connections-2.png differ
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/serverless-connections.png b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/serverless-connections.png
new file mode 100644
index 0000000000..6c4b56ea9b
Binary files /dev/null and b/docs/200-orm/200-prisma-client/000-setup-and-configuration/050-databases-connections/serverless-connections.png differ
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/100-custom-model-and-field-names.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/100-custom-model-and-field-names.mdx
new file mode 100644
index 0000000000..a60eb98ed9
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/100-custom-model-and-field-names.mdx
@@ -0,0 +1,310 @@
+---
+title: 'Custom model and field names'
+metaTitle: 'Custom model and field names'
+metaDescription: 'Learn how you can decouple the naming of Prisma models from database tables to improve the ergonomics of the generated Prisma Client API.'
+---
+
+
+
+The Prisma Client API is generated based on the models in your [Prisma schema](/orm/prisma-schema). Models are _typically_ 1:1 mappings of your database tables.
+
+In some cases, especially when using [introspection](/orm/prisma-schema/introspection), it might be useful to _decouple_ the naming of database tables and columns from the names that are used in your Prisma Client API. This can be done via the [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections) attributes in your Prisma schema.
+
+You can use `@map` and `@@map` to rename MongoDB fields and collections respectively. This page uses a relational database example.
+
+
+
+## Example: Relational database
+
+Assume you have a PostgreSQL relational database schema looking similar to this:
+
+```sql
+CREATE TABLE users (
+ user_id SERIAL PRIMARY KEY NOT NULL,
+ name VARCHAR(256),
+ email VARCHAR(256) UNIQUE NOT NULL
+);
+CREATE TABLE posts (
+ post_id SERIAL PRIMARY KEY NOT NULL,
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
+ title VARCHAR(256) NOT NULL,
+ content TEXT,
+ author_id INTEGER REFERENCES users(user_id)
+);
+CREATE TABLE profiles (
+ profile_id SERIAL PRIMARY KEY NOT NULL,
+ bio TEXT,
+ user_id INTEGER NOT NULL UNIQUE REFERENCES users(user_id)
+);
+CREATE TABLE categories (
+ category_id SERIAL PRIMARY KEY NOT NULL,
+ name VARCHAR(256)
+);
+CREATE TABLE post_in_categories (
+ post_id INTEGER NOT NULL REFERENCES posts(post_id),
+ category_id INTEGER NOT NULL REFERENCES categories(category_id)
+);
+CREATE UNIQUE INDEX post_id_category_id_unique ON post_in_categories(post_id int4_ops,category_id int4_ops);
+```
+
+When introspecting a database with that schema, you'll get a Prisma schema looking similar to this:
+
+```prisma
+model categories {
+ category_id Int @id @default(autoincrement())
+ name String? @db.VarChar(256)
+ post_in_categories post_in_categories[]
+}
+
+model post_in_categories {
+ post_id Int
+ category_id Int
+ categories categories @relation(fields: [category_id], references: [category_id], onDelete: NoAction, onUpdate: NoAction)
+ posts posts @relation(fields: [post_id], references: [post_id], onDelete: NoAction, onUpdate: NoAction)
+
+ @@unique([post_id, category_id], map: "post_id_category_id_unique")
+}
+
+model posts {
+ post_id Int @id @default(autoincrement())
+ created_at DateTime? @default(now()) @db.Timestamptz(6)
+ title String @db.VarChar(256)
+ content String?
+ author_id Int?
+ users users? @relation(fields: [author_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
+ post_in_categories post_in_categories[]
+}
+
+model profiles {
+ profile_id Int @id @default(autoincrement())
+ bio String?
+ user_id Int @unique
+ users users @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
+}
+
+model users {
+ user_id Int @id @default(autoincrement())
+ name String? @db.VarChar(256)
+ email String @unique @db.VarChar(256)
+ posts posts[]
+ profiles profiles?
+}
+```
+
+There are a few "issues" with this Prisma schema when the Prisma Client API is generated:
+
+**Adhering to Prisma's naming conventions**
+
+Prisma has a [naming convention](/orm/reference/prisma-schema-reference#naming-conventions) of **camelCasing** and using the **singular form** for Prisma models. If these naming conventions are not met, the Prisma schema can become harder to interpret and the generated Prisma Client API will feel less natural. Consider the following, generated model:
+
+```prisma
+model users {
+ user_id Int @id @default(autoincrement())
+ name String? @db.VarChar(256)
+ email String @unique @db.VarChar(256)
+ posts posts[]
+ profiles profiles?
+}
+```
+
+Although `profiles` refers to a 1:1 relation, its type is currently called `profiles` in plural, suggesting that there might be many `profiles` in this relation. With Prisma conventions, the models and fields were _ideally_ named as follows:
+
+```prisma
+model User {
+ user_id Int @id @default(autoincrement())
+ name String? @db.VarChar(256)
+ email String @unique @db.VarChar(256)
+ posts Post[]
+ profile Profile?
+}
+```
+
+Because these fields are "Prisma-level" [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) that do not manifest you can manually rename them in your Prisma schema.
+
+**Naming of annotated relation fields**
+
+Foreign keys are represented as a combination of a [annotated relation fields](/orm/prisma-schema/data-model/relations#relation-fields) and its corresponding relation scalar field in the Prisma schema. Here's how all the relations from the SQL schema are currently represented:
+
+```prisma
+model categories {
+ category_id Int @id @default(autoincrement())
+ name String? @db.VarChar(256)
+ post_in_categories post_in_categories[] // virtual relation field
+}
+
+model post_in_categories {
+ post_id Int // relation scalar field
+ category_id Int // relation scalar field
+ categories categories @relation(fields: [category_id], references: [category_id], onDelete: NoAction, onUpdate: NoAction) // virtual relation field
+ posts posts @relation(fields: [post_id], references: [post_id], onDelete: NoAction, onUpdate: NoAction)
+
+ @@unique([post_id, category_id], map: "post_id_category_id_unique")
+}
+
+model posts {
+ post_id Int @id @default(autoincrement())
+ created_at DateTime? @default(now()) @db.Timestamptz(6)
+ title String @db.VarChar(256)
+ content String?
+ author_id Int?
+ users users? @relation(fields: [author_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
+ post_in_categories post_in_categories[]
+}
+
+model profiles {
+ profile_id Int @id @default(autoincrement())
+ bio String?
+ user_id Int @unique
+ users users @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction)
+}
+
+model users {
+ user_id Int @id @default(autoincrement())
+ name String? @db.VarChar(256)
+ email String @unique @db.VarChar(256)
+ posts posts[]
+ profiles profiles?
+}
+```
+
+## Using `@map` and `@@map` to rename fields and models in the Prisma Client API
+
+You can "rename" fields and models that are used in Prisma Client by mapping them to the "original" names in the database using the `@map` and `@@map` attributes. For the example above, you could e.g. annotate your models as follows.
+
+_After_ you introspected your database with `prisma db pull`, you can manually adjust the resulting Prisma schema as follows:
+
+```prisma
+model Category {
+ id Int @id @default(autoincrement()) @map("category_id")
+ name String? @db.VarChar(256)
+ post_in_categories PostInCategories[]
+
+ @@map("categories")
+}
+
+model PostInCategories {
+ post_id Int
+ category_id Int
+ categories Category @relation(fields: [category_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
+ posts Post @relation(fields: [post_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
+
+ @@unique([post_id, category_id], map: "post_id_category_id_unique")
+ @@map("post_in_categories")
+}
+
+model Post {
+ id Int @id @default(autoincrement()) @map("post_id")
+ created_at DateTime? @default(now()) @db.Timestamptz(6)
+ title String @db.VarChar(256)
+ content String?
+ author_id Int?
+ users User? @relation(fields: [author_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
+ post_in_categories PostInCategories[]
+
+ @@map("posts")
+}
+
+model Profile {
+ id Int @id @default(autoincrement()) @map("profile_id")
+ bio String?
+ user_id Int @unique
+ users User @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
+
+ @@map("profiles")
+}
+
+model User {
+ id Int @id @default(autoincrement()) @map("user_id")
+ name String? @db.VarChar(256)
+ email String @unique @db.VarChar(256)
+ posts Post[]
+ profiles Profile?
+
+ @@map("users")
+}
+```
+
+With these changes, you're now adhering to Prisma's naming conventions and the generated Prisma Client API feels more "natural":
+
+```ts
+// Nested writes
+const profile = await prisma.profile.create({
+ data: {
+ bio: 'Hello World',
+ users: {
+ create: {
+ name: 'Alice',
+ email: 'alice@prisma.io',
+ },
+ },
+ },
+})
+
+// Fluent API
+const userByProfile = await prisma.profile
+ .findUnique({
+ where: { id: 1 },
+ })
+ .users()
+```
+
+## Renaming relation fields
+
+Prisma-level [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) (sometimes referred to as "virtual relation fields") only exist in the Prisma schema, but do not actually manifest in the underlying database. You can therefore name these fields whatever you want.
+
+Consider the following example of an ambiguous relation in a SQL database:
+
+```sql
+CREATE TABLE "User" (
+ id SERIAL PRIMARY KEY
+);
+CREATE TABLE "Post" (
+ id SERIAL PRIMARY KEY,
+ "author" integer NOT NULL,
+ "favoritedBy" INTEGER,
+ FOREIGN KEY ("author") REFERENCES "User"(id),
+ FOREIGN KEY ("favoritedBy") REFERENCES "User"(id)
+);
+```
+
+Prisma's introspection will output the following Prisma schema:
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ author Int
+ favoritedBy Int?
+ User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id], onDelete: NoAction, onUpdate: NoAction)
+ User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id], onDelete: NoAction, onUpdate: NoAction)
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ Post_Post_authorToUser Post[] @relation("Post_authorToUser")
+ Post_Post_favoritedByToUser Post[] @relation("Post_favoritedByToUser")
+}
+```
+
+Because the names of the virtual relation fields `Post_Post_authorToUser` and `Post_Post_favoritedByToUser` are based on the generated relation names, they don't look very friendly in the Prisma Client API. In that case, you can rename the relation fields. For example:
+
+```prisma highlight=11-12;edit
+model Post {
+ id Int @id @default(autoincrement())
+ author Int
+ favoritedBy Int?
+ User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id], onDelete: NoAction, onUpdate: NoAction)
+ User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id], onDelete: NoAction, onUpdate: NoAction)
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ writtenPosts Post[] @relation("Post_authorToUser")
+ favoritedPosts Post[] @relation("Post_favoritedByToUser")
+}
+```
+
+
+
+`prisma db pull` preserves custom relation fields defined in your Prisma schema on re-introspecting your database.
+
+
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/150-error-formatting.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/150-error-formatting.mdx
new file mode 100644
index 0000000000..c880444b25
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/150-error-formatting.mdx
@@ -0,0 +1,41 @@
+---
+title: 'Configuring error formatting'
+metaTitle: 'Configuring error formatting (Concepts)'
+metaDescription: 'This page explains how to configure the formatting of errors when using Prisma Client.'
+---
+
+
+
+By default, Prisma Client uses [ANSI escape characters](https://en.wikipedia.org/wiki/ANSI_escape_code) to pretty print the error stack and give recommendations on how to fix a problem. While this is very useful when using Prisma Client from the terminal, in contexts like a GraphQL API, you only want the minimal error without any additional formatting.
+
+This page explains how error formatting can be configured with Prisma Client.
+
+
+
+## Formatting levels
+
+There are 3 error formatting levels:
+
+1. **Pretty Error** (default): Includes a full stack trace with colors, syntax highlighting of the code and extended error message with a possible solution for the problem.
+2. **Colorless Error**: Same as pretty errors, just without colors.
+3. **Minimal Error**: The raw error message.
+
+In order to configure these different error formatting levels, there are two options:
+
+- Setting the config options via environment variables
+- Providing the config options to the `PrismaClient` constructor
+
+## Formatting via environment variables
+
+- [`NO_COLOR`](/orm/reference/environment-variables-reference#no_color): If this env var is provided, colors are stripped from the error messages. Therefore you end up with a **colorless error**. The `NO_COLOR` environment variable is a standard described [here](https://no-color.org/).
+- `NODE_ENV=production`: If the env var `NODE_ENV` is set to `production`, only the **minimal error** will be printed. This allows for easier digestion of logs in production environments.
+
+### Formatting via the `PrismaClient` constructor
+
+Alternatively, use the `PrismaClient` [`errorFormat`](/orm/reference/prisma-client-reference#errorformat) parameter to set the error format:
+
+```ts
+const prisma = new PrismaClient({
+ errorFormat: 'pretty',
+})
+```
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/200-read-replicas.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/200-read-replicas.mdx
new file mode 100644
index 0000000000..0d73fbb82b
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/200-read-replicas.mdx
@@ -0,0 +1,83 @@
+---
+title: 'Read replicas'
+metaTitle: 'Read replicas'
+metaDescription: 'Learn how to set up and use read replicas with Prisma Client'
+tocDepth: 3
+---
+
+
+
+Read replicas enable you to distribute workloads across database replicas for high-traffic workloads. The [read replicas extension](https://github.com/prisma/extension-read-replicas), `@prisma/extension-read-replicas`, adds support for read-only database replicas to Prisma Client.
+
+The read replicas extension supports Prisma versions [5.2.0](https://github.com/prisma/prisma/releases/tag/5.2.0) and higher. If you run into a bug or have feedback, create a GitHub issue [here](https://github.com/prisma/extension-read-replicas/issues/new).
+
+
+
+## Setup the read replicas extension
+
+Install the extension:
+
+```terminal
+npm install @prisma/extension-read-replicas
+```
+
+Initialize the extension by extending your Prisma Client instance and provide the extension a connection string that points to your read replica in the `url` option of the extension.
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+import { readReplicas } from '@prisma/extension-read-replicas'
+
+const prisma = new PrismaClient().$extends(
+ readReplicas({
+ url: process.env.DATABASE_URL_REPLICA,
+ })
+)
+
+// Query is run against the database replica
+await prisma.post.findMany()
+
+// Query is run against the primary database
+await prisma.post.create({
+ data: {/** */},
+})
+```
+
+
+All read operations, e.g. `findMany`, will be executed against the database replica with the above setup. All write operations — e.g. `create`, `update` — and `$transaction` queries, will be executed against your primary database.
+
+If you run into a bug or have feedback, create a GitHub issue [here](https://github.com/prisma/extension-read-replicas/issues/new).
+
+## Configure multiple database replicas
+
+The `url` property also accepts an array of values, i.e. an array of all your database replicas you would like to configure:
+
+```ts
+const prisma = new PrismaClient().$extends(
+ readReplicas({
+ url: [
+ process.env.DATABASE_URL_REPLICA_1,
+ process.env.DATABASE_URL_REPLICA_2,
+ ],
+ })
+)
+```
+
+If you have more than one read replica configured, a database replica will be randomly selected to execute your query.
+
+## Executing read operations against your primary database
+
+You can use the `$primary()` method to explicitly execute a read operation against your primary database:
+
+```ts
+const posts = await prisma.$primary().post.findMany()
+```
+
+## Executing operations against a database replica
+
+You can use the `$replica()` method to explicitly execute your query against a replica instead of your primary database:
+
+```ts
+const result = await prisma.$replica().$queryRaw`SELECT ...`
+```
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/220-database-polyfills.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/220-database-polyfills.mdx
new file mode 100644
index 0000000000..9cfe6e692e
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/220-database-polyfills.mdx
@@ -0,0 +1,22 @@
+---
+title: 'Database polyfills'
+metaTitle: 'Database polyfills (Concepts)'
+metaDescription: 'Prisma Client provides features that are not achievable with relational databases. These features are referred to as "polyfills" and explained on this page.'
+---
+
+
+
+Prisma Client provides features that are typically either not achievable with particular databases or require extensions. These features are referred to as _polyfills_. For all databases, this includes:
+
+- Initializing [ID](/orm/prisma-schema/data-model/models#defining-an-id-field) values with `cuid` and `uuid` values
+- Using [`@updatedAt`](/orm/prisma-schema/data-model/models#defining-attributes) to store the time when a record was last updated
+
+For relational databases, this includes:
+
+- [Implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations)
+
+For MongoDB, this includes:
+
+- [Relations in general](/orm/prisma-schema/data-model/relations) - foreign key relations between documents are not enforced in MongoDB
+
+
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/index.mdx b/docs/200-orm/200-prisma-client/000-setup-and-configuration/index.mdx
new file mode 100644
index 0000000000..c1c3f53673
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/000-setup-and-configuration/index.mdx
@@ -0,0 +1,15 @@
+---
+title: 'Setup & configuration'
+metaTitle: 'Setup & configuration'
+metaDescription: 'This section explains how to generate, configure, and instantiate Prisma Client, as well as when and how to manage database connections.'
+---
+
+
+
+This section describes how to set up, generate, configure, and instantiate `PrismaClient` , as well as when and how to actively [manage connections](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management).
+
+
+
+## In this section
+
+
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/prisma-client-generation-workflow.png b/docs/200-orm/200-prisma-client/000-setup-and-configuration/prisma-client-generation-workflow.png
new file mode 100644
index 0000000000..1faf99964c
Binary files /dev/null and b/docs/200-orm/200-prisma-client/000-setup-and-configuration/prisma-client-generation-workflow.png differ
diff --git a/docs/200-orm/200-prisma-client/000-setup-and-configuration/prisma-client-node-module.png b/docs/200-orm/200-prisma-client/000-setup-and-configuration/prisma-client-node-module.png
new file mode 100644
index 0000000000..890f494d68
Binary files /dev/null and b/docs/200-orm/200-prisma-client/000-setup-and-configuration/prisma-client-node-module.png differ
diff --git a/docs/200-orm/200-prisma-client/100-queries/030-crud.mdx b/docs/200-orm/200-prisma-client/100-queries/030-crud.mdx
new file mode 100644
index 0000000000..e89a2c2ba6
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/030-crud.mdx
@@ -0,0 +1,996 @@
+---
+title: 'CRUD'
+metaTitle: 'CRUD (Reference)'
+metaDescription: 'How to perform CRUD with Prisma Client.'
+tocDepth: 4
+---
+
+
+
+This page describes how to perform CRUD operations with your generated Prisma Client API. CRUD is an acronym that stands for:
+
+- [Create](#create)
+- [Read](#read)
+- [Update](#update)
+- [Delete](#delete)
+
+Refer to the [Prisma Client API reference documentation](/orm/reference/prisma-client-reference) for detailed explanations of each method.
+
+
+
+## Example schema
+
+All examples are based on the following schema:
+
+
+
+Expand for sample schema
+
+
+
+
+```prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model ExtendedProfile {
+ id Int @id @default(autoincrement())
+ biography String
+ user User @relation(fields: [userId], references: [id])
+ userId Int @unique
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ email String @unique
+ profileViews Int @default(0)
+ role Role @default(USER)
+ coinflips Boolean[]
+ posts Post[]
+ profile ExtendedProfile?
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ published Boolean @default(true)
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ comments Json?
+ views Int @default(0)
+ likes Int @default(0)
+ categories Category[]
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String @unique
+ posts Post[]
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+```prisma
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model ExtendedProfile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ biography String
+ user User @relation(fields: [userId], references: [id])
+ userId String @unique @db.ObjectId
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ email String @unique
+ profileViews Int @default(0)
+ role Role @default(USER)
+ coinflips Boolean[]
+ posts Post[]
+ profile ExtendedProfile?
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ published Boolean @default(true)
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ comments Json?
+ views Int @default(0)
+ likes Int @default(0)
+ categories Category[]
+}
+
+model Category {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String @unique
+ posts Post[]
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+
+
+For **relational databases**, use `db push` command to push the example schema to your own database
+
+```terminal
+npx prisma db push
+```
+
+For **MongoDB**, ensure your data is in a uniform shape and matches the model defined in the Prisma schema.
+
+## Create
+
+### Create a single record
+
+The following query creates ([`create`](/orm/reference/prisma-client-reference#create) ) a single user with two fields:
+
+
+
+
+```ts
+const user = await prisma.user.create({
+ data: {
+ email: 'elsa@prisma.io',
+ name: 'Elsa Prisma',
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 22,
+ name: 'Elsa Prisma',
+ email: 'elsa@prisma.io',
+ profileViews: 0,
+ role: 'USER',
+ coinflips: []
+}
+```
+
+
+
+
+The user's `id` is auto-generated, and your schema determines [which fields are mandatory](/orm/prisma-schema/data-model/models#optional-and-mandatory-fields).
+
+#### Create a single record using generated types
+
+The following example produces an identical result, but creates a `UserCreateInput` variable named `user` _outside_ the context of the `create` query. After completing a simple check (should posts be included in this `create` query?), the `user` variable is passed into the query:
+
+```ts
+import { PrismaClient, Prisma } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ let includePosts: boolean = false
+ let user: Prisma.UserCreateInput
+
+ // Check if posts should be included in the query
+ if (includePosts) {
+ user = {
+ email: 'elsa@prisma.io',
+ name: 'Elsa Prisma',
+ posts: {
+ create: {
+ title: 'Include this post!',
+ },
+ },
+ }
+ } else {
+ user = {
+ email: 'elsa@prisma.io',
+ name: 'Elsa Prisma',
+ }
+ }
+
+ // Pass 'user' object into query
+ const createUser = await prisma.user.create({ data: user })
+}
+
+main()
+```
+
+For more information about working with generated types, see: [Generated types](/orm/prisma-client/type-safety).
+
+### Create multiple records
+
+Prisma Client supports bulk inserts as a GA feature in [2.20.0](https://github.com/prisma/prisma/releases/2.20.0) and later.
+
+The following [`createMany`](/orm/reference/prisma-client-reference#createmany) query creates multiple users and skips any duplicates (`email` must be unique):
+
+
+
+
+```ts
+const createMany = await prisma.user.createMany({
+ data: [
+ { name: 'Bob', email: 'bob@prisma.io' },
+ { name: 'Bobo', email: 'bob@prisma.io' }, // Duplicate unique key!
+ { name: 'Yewande', email: 'yewande@prisma.io' },
+ { name: 'Angelique', email: 'angelique@prisma.io' },
+ ],
+ skipDuplicates: true, // Skip 'Bobo'
+})
+```
+
+
+
+
+```js no-copy
+{
+ count: 3
+}
+```
+
+
+
+
+
+
+
+Note `skipDuplicates` is not supported when using MongoDB or SQLServer.
+
+
+
+`createMany` uses a single `INSERT INTO` statement with multiple values, which is generally more efficient than a separate `INSERT` per row:
+
+```sql
+BEGIN
+INSERT INTO "public"."User" ("id","name","email","profileViews","role","coinflips","testing","city","country") VALUES (DEFAULT,$1,$2,$3,$4,DEFAULT,DEFAULT,DEFAULT,$5), (DEFAULT,$6,$7,$8,$9,DEFAULT,DEFAULT,DEFAULT,$10), (DEFAULT,$11,$12,$13,$14,DEFAULT,DEFAULT,DEFAULT,$15), (DEFAULT,$16,$17,$18,$19,DEFAULT,DEFAULT,DEFAULT,$20) ON CONFLICT DO NOTHING
+COMMIT
+SELECT "public"."User"."country", "public"."User"."city", "public"."User"."email", SUM("public"."User"."profileViews"), COUNT(*) FROM "public"."User" WHERE 1=1 GROUP BY "public"."User"."country", "public"."User"."city", "public"."User"."email" HAVING AVG("public"."User"."profileViews") >= $1 ORDER BY "public"."User"."country" ASC OFFSET $2
+```
+
+> **Note**: Multiple `create` statements inside a `$transaction` results in multiple `INSERT` statements.
+
+The following video demonstrates how to use `createMany` and [faker.js](https://github.com/faker-js/faker/) to seed a database with sample data:
+
+
+
+
+
+### Create records and connect or create related records
+
+See [Working with relations > Nested writes](relation-queries#nested-writes) for information about creating a record and one or more related records at the same time.
+
+## Read
+
+### Get record by ID or unique identifier
+
+The following queries return a single record ([`findUnique`](/orm/reference/prisma-client-reference#findunique) ) by unique identifier or ID:
+
+```ts
+// By unique identifier
+const user = await prisma.user.findUnique({
+ where: {
+ email: 'elsa@prisma.io',
+ },
+})
+
+// By ID
+const user = await prisma.user.findUnique({
+ where: {
+ id: 99,
+ },
+})
+```
+
+If you are using the MongoDB connector and your underlying ID type is `ObjectId`, you can use the string representation of that `ObjectId`:
+
+```ts
+// By ID
+const user = await prisma.user.findUnique({
+ where: {
+ id: '60d5922d00581b8f0062e3a8',
+ },
+})
+```
+
+### Get all records
+
+The following [`findMany`](/orm/reference/prisma-client-reference#findmany) query returns _all_ `User` records:
+
+```ts
+const users = await prisma.user.findMany()
+```
+
+You can also [paginate your results](pagination).
+
+### Get the first record that matches a specific criteria
+
+The following [`findFirst`](/orm/reference/prisma-client-reference#findfirst) query returns the _most recently created user_ with at least one post that has more than 100 likes:
+
+1. Order users by descending ID (largest first) - the largest ID is the most recent
+2. Return the first user in descending order with at least one post that has more than 100 likes
+
+```ts
+const findUser = await prisma.user.findFirst({
+ where: {
+ posts: {
+ some: {
+ likes: {
+ gt: 100,
+ },
+ },
+ },
+ },
+ orderBy: {
+ id: 'desc',
+ },
+})
+```
+
+### Get a filtered list of records
+
+Prisma Client supports [filtering](filtering-and-sorting) on record fields and related record fields.
+
+#### Filter by a single field value
+
+The following query returns all `User` records with an email that ends in `"prisma.io"`:
+
+```ts
+const users = await prisma.user.findMany({
+ where: {
+ email: {
+ endsWith: 'prisma.io',
+ },
+ },
+})
+```
+
+#### Filter by multiple field values
+
+The following query uses a combination of [operators](/orm/reference/prisma-client-reference#filter-conditions-and-operators) to return users whose name start with `E` _or_ administrators with at least 1 profile view:
+
+```ts
+const users = await prisma.user.findMany({
+ where: {
+ OR: [
+ {
+ name: {
+ startsWith: 'E',
+ },
+ },
+ {
+ AND: {
+ profileViews: {
+ gt: 0,
+ },
+ role: {
+ equals: 'ADMIN',
+ },
+ },
+ },
+ ],
+ },
+})
+```
+
+#### Filter by related record field values
+
+The following query returns users with an email that ends with `prisma.io` _and_ have at least _one_ post (`some`) that is not published:
+
+```ts
+const users = await prisma.user.findMany({
+ where: {
+ email: {
+ endsWith: 'prisma.io',
+ },
+ posts: {
+ some: {
+ published: false,
+ },
+ },
+ },
+})
+```
+
+See [Working with relations](relation-queries) for more examples of filtering on related field values.
+
+### Select a subset of fields
+
+The following `findUnique` query uses `select` to return the `email` and `name` fields of a specific `User` record:
+
+
+
+
+```ts
+const user = await prisma.user.findUnique({
+ where: {
+ email: 'emma@prisma.io',
+ },
+ select: {
+ email: true,
+ name: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{ email: 'emma@prisma.io', name: "Emma" }
+```
+
+
+
+
+For more information about including relations, refer to:
+
+- [Select fields](select-fields)
+- [Relation queries](relation-queries)
+
+#### Select a subset of related record fields
+
+The following query uses a nested `select` to return:
+
+- The user's `email`
+- The `likes` field of each post
+
+
+
+
+```ts
+const user = await prisma.user.findUnique({
+ where: {
+ email: 'emma@prisma.io',
+ },
+ select: {
+ email: true,
+ posts: {
+ select: {
+ likes: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{ email: 'emma@prisma.io', posts: [ { likes: 0 }, { likes: 0 } ] }
+```
+
+
+
+
+For more information about including relations, see [Select fields and include relations](select-fields).
+
+### Select distinct field values
+
+See [Select `distinct`](aggregation-grouping-summarizing#select-distinct) for information about selecting distinct field values.
+
+### Include related records
+
+The following query returns all `ADMIN` users and includes each user's posts in the result:
+
+
+
+
+```ts
+const users = await prisma.user.findMany({
+ where: {
+ role: 'ADMIN',
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 38,
+ "name": "Maria",
+ "email": "maria@prisma.io",
+ "profileViews": 20,
+ "role": "ADMIN",
+ "coinflips": [
+ true,
+ false,
+ false
+ ],
+ "posts": []
+},
+{
+ "id": 39,
+ "name": "Oni",
+ "email": "oni2@prisma.io",
+ "profileViews": 20,
+ "role": "ADMIN",
+ "coinflips": [
+ true,
+ false,
+ false
+ ],
+ "posts": [
+ {
+ "id": 25,
+ "authorId": 39,
+ "title": "My awesome post",
+ "published": true,
+ "comments": null,
+ "views": 0,
+ "likes": 0
+ }
+ ]
+}
+```
+
+
+
+
+For more information about including relations, see [Select fields and include relations](select-fields).
+
+#### Include a filtered list of relations
+
+See [Working with relations](relation-queries#filter-a-list-of-relations) to find out how to combine [`include`](/orm/reference/prisma-client-reference#include) and `where` for a filtered list of relations - for example, only include a user's published posts.
+
+## Update
+
+### Update a single record
+
+The following query uses [`update`](/orm/reference/prisma-client-reference#update) to find and update a single `User` record by `email`:
+
+
+
+
+```ts
+const updateUser = await prisma.user.update({
+ where: {
+ email: 'viola@prisma.io',
+ },
+ data: {
+ name: 'Viola the Magnificent',
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 43,
+ "name": "Viola the Magnificent",
+ "email": "viola@prisma.io",
+ "profileViews": 0,
+ "role": "USER",
+ "coinflips": [],
+}
+```
+
+
+
+
+### Update multiple records
+
+The following query uses [`updateMany`](/orm/reference/prisma-client-reference#updatemany) to update all `User` records that contain `prisma.io`:
+
+
+
+
+```ts
+const updateUsers = await prisma.user.updateMany({
+ where: {
+ email: {
+ contains: 'prisma.io',
+ },
+ },
+ data: {
+ role: 'ADMIN',
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "count": 19
+}
+```
+
+
+
+
+### Update _or_ create records
+
+The following query uses [`upsert`](/orm/reference/prisma-client-reference#upsert) to update a `User` record with a specific email address, or create that `User` record if it does not exist:
+
+
+
+
+```ts
+const upsertUser = await prisma.user.upsert({
+ where: {
+ email: 'viola@prisma.io',
+ },
+ update: {
+ name: 'Viola the Magnificent',
+ },
+ create: {
+ email: 'viola@prisma.io',
+ name: 'Viola the Magnificent',
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 43,
+ "name": "Viola the Magnificent",
+ "email": "viola@prisma.io",
+ "profileViews": 0,
+ "role": "ADMIN",
+ "coinflips": [],
+}
+```
+
+
+
+
+
+
+From version 4.6.0, Prisma carries out upserts with database native SQL commands where possible. [Learn more](/orm/reference/prisma-client-reference#database-upserts).
+
+
+
+Prisma does not have a `findOrCreate` query. You can use `upsert` as a workaround. To make `upsert` behave like a `findOrCreate` method, provide an empty `update` parameter to `upsert`.
+
+
+
+A limitation to using `upsert` as a workaround for `findOrCreate` is that `upsert` will only accept unique model fields in the `where` condition. So it's not possible to use `upsert` to emulate `findOrCreate` if the `where` condition contains non-unique fields.
+
+
+
+### Update a number field
+
+Use [atomic number operations](/orm/reference/prisma-client-reference#atomic-number-operations) to update a number field **based on its current value** - for example, increment or multiply. The following query increments the `views` and `likes` fields by `1`:
+
+```ts
+const updatePosts = await prisma.post.updateMany({
+ data: {
+ views: {
+ increment: 1,
+ },
+ likes: {
+ increment: 1,
+ },
+ },
+})
+```
+
+### Connect and disconnect related records
+
+Refer to [Working with relations](relation-queries) for information about disconnecting ([`disconnect`](/orm/reference/prisma-client-reference#disconnect) ) and connecting ([`connect`](/orm/reference/prisma-client-reference#connect) ) related records.
+
+## Delete
+
+### Delete a single record
+
+The following query uses [`delete`](/orm/reference/prisma-client-reference#delete) to delete a single `User` record:
+
+```ts
+const deleteUser = await prisma.user.delete({
+ where: {
+ email: 'bert@prisma.io',
+ },
+})
+```
+
+Attempting to delete a user with one or more posts result in an error, as every `Post` requires an author - see [cascading deletes](#cascading-deletes-deleting-related-records).
+
+### Delete multiple records
+
+The following query uses `deleteMany` to delete all `User` records where `email` contains `prisma.io`:
+
+```ts
+const deleteUsers = await prisma.user.deleteMany({
+ where: {
+ email: {
+ contains: 'prisma.io',
+ },
+ },
+})
+```
+
+Attempting to delete a user with one or more posts result in an error, as every `Post` requires an author - see [cascading deletes](#cascading-deletes-deleting-related-records).
+
+### Delete all records
+
+The following query uses `deleteMany` to delete all `User` records:
+
+```ts
+const deleteUsers = await prisma.user.deleteMany({})
+```
+
+Be aware that this query will fail if the user has any related records (such as posts). In this case, you need to [delete the related records first](#cascading-deletes-deleting-related-records).
+
+### Cascading deletes (deleting related records)
+
+
+
+In [2.26.0](https://github.com/prisma/prisma/releases/tag/2.26.0) and later it is possible to do cascading deletes using the **preview feature** [referential actions](/orm/prisma-schema/data-model/relations/referential-actions).
+
+
+
+The following query uses [`delete`](/orm/reference/prisma-client-reference#delete) to delete a single `User` record:
+
+```ts
+const deleteUser = await prisma.user.delete({
+ where: {
+ email: 'bert@prisma.io',
+ },
+})
+```
+
+However, the example schema includes a **required relation** between `Post` and `User`, which means that you cannot delete a user with posts:
+
+```
+The change you are trying to make would violate the required relation 'PostToUser' between the `Post` and `User` models.
+```
+
+To resolve this error, you can:
+
+- Make the relation optional:
+
+ ```prisma highlight=3,4;add|5,6;delete
+ model Post {
+ id Int @id @default(autoincrement())
+ author User? @relation(fields: [authorId], references: [id])
+ authorId Int?
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ }
+ ```
+
+- Change the author of the posts to another user before deleting the user.
+
+- Delete a user and all their posts with two separate queries in a transaction (all queries must succeed):
+
+ ```ts
+ const deletePosts = prisma.post.deleteMany({
+ where: {
+ authorId: 7,
+ },
+ })
+
+ const deleteUser = prisma.user.delete({
+ where: {
+ id: 7,
+ },
+ })
+
+ const transaction = await prisma.$transaction([deletePosts, deleteUser])
+ ```
+
+### Delete all records from all tables
+
+Sometimes you want to remove all data from all tables but keep the actual tables. This can be particularly useful in a development environment and whilst testing.
+
+The following shows how to delete all records from all tables with Prisma Client and with Prisma Migrate.
+
+#### Deleting all data with `deleteMany`
+
+When you know the order in which your tables should be deleted, you can use the [`deleteMany`](/orm/reference/prisma-client-reference#deletemany) function. This is executed synchronously in a [`$transaction`](/orm/prisma-client/queries/transactions) and can be used with all types of databases.
+
+```ts
+const deletePosts = prisma.post.deleteMany()
+const deleteProfile = prisma.profile.deleteMany()
+const deleteUsers = prisma.user.deleteMany()
+
+// The transaction runs synchronously so deleteUsers must run last.
+await prisma.$transaction([deleteProfile, deletePosts, deleteUsers])
+```
+
+✅ **Pros**:
+
+- Works well when you know the structure of your schema ahead of time
+- Synchronously deletes each tables data
+
+❌ **Cons**:
+
+- When working with relational databases, this function doesn't scale as well as having a more generic solution which looks up and `TRUNCATE`s your tables regardless of their relational constraints. Note that this scaling issue does not apply when using the MongoDB connector.
+
+> **Note**: The `$transaction` performs a cascading delete on each models table so they have to be called in order.
+
+#### Deleting all data with raw SQL / `TRUNCATE`
+
+If you are comfortable working with raw SQL you can perform a `TRUNCATE` on a table by utilizing [`$executeRawUnsafe`](/orm/prisma-client/queries/raw-database-access/raw-queries#executerawunsafe).
+
+In the following examples, the first tab shows how to perform a `TRUNCATE` on a Postgres database by using a `$queryRaw` look up that maps over the table and `TRUNCATES` all tables in a single query.
+
+The second tab shows performing the same function but with a MySQL database. In this instance the constraints must be removed before the `TRUNCATE` can be executed, before being reinstated once finished. The whole process is run as a `$transaction`
+
+
+
+
+
+```ts
+const tablenames = await prisma.$queryRaw<
+ Array<{ tablename: string }>
+>`SELECT tablename FROM pg_tables WHERE schemaname='public'`
+
+const tables = tablenames
+ .map(({ tablename }) => tablename)
+ .filter((name) => name !== '_prisma_migrations')
+ .map((name) => `"public"."${name}"`)
+ .join(', ')
+
+try {
+ await prisma.$executeRawUnsafe(`TRUNCATE TABLE ${tables} CASCADE;`)
+} catch (error) {
+ console.log({ error })
+}
+```
+
+
+
+
+
+```ts
+const transactions: PrismaPromise[] = []
+transactions.push(prisma.$executeRaw`SET FOREIGN_KEY_CHECKS = 0;`)
+
+const tablenames = await prisma.$queryRaw<
+ Array<{ TABLE_NAME: string }>
+>`SELECT TABLE_NAME from information_schema.TABLES WHERE TABLE_SCHEMA = 'tests';`
+
+for (const { TABLE_NAME } of tablenames) {
+ if (TABLE_NAME !== '_prisma_migrations') {
+ try {
+ transactions.push(prisma.$executeRawUnsafe(`TRUNCATE ${TABLE_NAME};`))
+ } catch (error) {
+ console.log({ error })
+ }
+ }
+}
+
+transactions.push(prisma.$executeRaw`SET FOREIGN_KEY_CHECKS = 1;`)
+
+try {
+ await prisma.$transaction(transactions)
+} catch (error) {
+ console.log({ error })
+}
+```
+
+
+
+
+
+✅ **Pros**:
+
+- Scalable
+- Very fast
+
+❌ **Cons**:
+
+- Can't undo the operation
+- Using reserved SQL key words as tables names can cause issues when trying to run a raw query
+
+#### Deleting all records with Prisma Migrate
+
+If you use Prisma Migrate, you can use `migrate reset`, this will:
+
+1. Drop the database
+2. Create a new database
+3. Apply migrations
+4. Seed the database with data
+
+## Advanced query examples
+
+### Create a deeply nested tree of records
+
+- A single `User`
+- Two new, related `Post` records
+- Connect or create `Category` per post
+
+```ts
+const u = await prisma.user.create({
+ include: {
+ posts: {
+ include: {
+ categories: true,
+ },
+ },
+ },
+ data: {
+ email: 'emma@prisma.io',
+ posts: {
+ create: [
+ {
+ title: 'My first post',
+ categories: {
+ connectOrCreate: [
+ {
+ create: { name: 'Introductions' },
+ where: {
+ name: 'Introductions',
+ },
+ },
+ {
+ create: { name: 'Social' },
+ where: {
+ name: 'Social',
+ },
+ },
+ ],
+ },
+ },
+ {
+ title: 'How to make cookies',
+ categories: {
+ connectOrCreate: [
+ {
+ create: { name: 'Social' },
+ where: {
+ name: 'Social',
+ },
+ },
+ {
+ create: { name: 'Cooking' },
+ where: {
+ name: 'Cooking',
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+})
+```
diff --git a/docs/200-orm/200-prisma-client/100-queries/035-select-fields.mdx b/docs/200-orm/200-prisma-client/100-queries/035-select-fields.mdx
new file mode 100644
index 0000000000..19297b3bc6
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/035-select-fields.mdx
@@ -0,0 +1,321 @@
+---
+title: 'Select fields'
+metaTitle: 'Select fields (Concepts)'
+metaDescription: 'This page explains how to select only a subset of a model''s fields and/or include relations ("eager loading") in a Prisma Client query.'
+tocDepth: 3
+---
+
+
+
+By default, when a query returns records (as opposed to a count), the result includes the **default selection set**:
+
+- **All** scalar fields defined in the Prisma schema (including enums)
+- **None** of the relations
+
+To customize the result:
+
+- Use [`select`](/orm/reference/prisma-client-reference#select) to return specific fields - [you can also use a nested `select` to include relation fields](relation-queries#select-specific-relation-fields)
+- Use [`include`](/orm/reference/prisma-client-reference#include) to explicitly [include relations](relation-queries#nested-reads)
+
+Selecting only the fields and relations that you require rather than relying on the default selection set can ✔ reduce the size of the response and ✔ improve query speed.
+
+Since version [5.9.0](https://github.com/prisma/prisma/releases/tag/5.9.0), when doing a relation query with `include` or by using `select` on a relation field, you can also specify the `relationLoadStrategy` to decide whether you want to use a database-level JOIN or perform multiple queries and merge the data on the application level. This feature is currently in [Preview](/orm/more/releases#preview), you can learn more about it [here](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview).
+
+
+
+## Example schema
+
+All examples are based on the following schema:
+
+
+
+Expand for sample schema
+
+
+
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model ExtendedProfile {
+ id Int @id @default(autoincrement())
+ biography String
+ user User @relation(fields: [userId], references: [id])
+ userId Int @unique
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ email String @unique
+ profileViews Int @default(0)
+ role Role @default(USER)
+ coinflips Boolean[]
+ posts Post[]
+ profile ExtendedProfile?
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ published Boolean @default(true)
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ comments Json?
+ views Int @default(0)
+ likes Int @default(0)
+ categories Category[]
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ name String @unique
+ posts Post[]
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+```prisma
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model ExtendedProfile {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ biography String
+ user User @relation(fields: [userId], references: [id])
+ userId String @unique @db.ObjectId
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String?
+ email String @unique
+ profileViews Int @default(0)
+ role Role @default(USER)
+ coinflips Boolean[]
+ posts Post[]
+ profile ExtendedProfile?
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ published Boolean @default(true)
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ comments Json?
+ views Int @default(0)
+ likes Int @default(0)
+ categories Category[]
+}
+
+model Category {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String @unique
+ posts Post[]
+}
+
+enum Role {
+ USER
+ ADMIN
+}
+```
+
+
+
+
+
+
+For **relational databases**, use `db push` command to push the example schema to your own database
+
+```terminal
+npx prisma db push
+```
+
+For **MongoDB**, ensure your data is in a uniform shape and matches the model defined in the Prisma schema.
+
+## Return the default selection set
+
+The following query returns the default selection set (all scalar fields, no relations):
+
+
+
+
+```ts
+// Query returns User or null
+const getUser: User | null = await prisma.user.findUnique({
+ where: {
+ id: 22,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 22,
+ name: "Alice",
+ email: "alice@prisma.io",
+ profileViews: 0,
+ role: "ADMIN",
+ coinflips: [true, false],
+}
+```
+
+
+
+
+## Select specific fields
+
+Use `select` to return a limited subset of fields instead of all fields. The following example returns the `email` and `name` fields only:
+
+
+
+
+```ts
+// Returns an object or null
+const getUser: object | null = await prisma.user.findUnique({
+ where: {
+ id: 22,
+ },
+ select: {
+ email: true,
+ name: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ name: "Alice",
+ email: "alice@prisma.io",
+}
+```
+
+
+
+
+## Include relations and select relation fields
+
+To return **specific relation fields**, you can:
+
+- Use a nested `select`
+- Use a `select` within an `include`
+
+> To return _all_ relation fields, use `include` only - for example, `{ include: { posts: true } }`.
+
+The following query uses a nested `select` to select each user's `name` and the `title` of each related post:
+
+
+
+
+```ts highlight=normal;2,5
+const users = await prisma.user.findMany({
+ select: {
+ name: true,
+ posts: {
+ select: {
+ title: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "name":"Sabelle",
+ "posts":[
+ {
+ "title":"Getting started with Azure Functions"
+ },
+ {
+ "title":"All about databases"
+ }
+ ]
+}
+```
+
+
+
+
+The following query uses `select` within an `include`, and returns _all_ user fields and each post's `title` field:
+
+
+
+
+```ts highlight=normal;2,5
+const users = await prisma.user.findMany({
+ // Returns all user fields
+ include: {
+ posts: {
+ select: {
+ title: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 9
+ "name": "Sabelle",
+ "email": "sabelle@prisma.io",
+ "profileViews": 90,
+ "role": "USER",
+ "profile": null,
+ "coinflips": [],
+ "posts":[
+ {
+ "title":"Getting started with Azure Functions"
+ },
+ {
+ "title":"All about databases"
+ }
+ ]
+}
+```
+
+
+
+
+For more information about querying relations, refer to the following documentation:
+
+- [Include a relation (including all fields)](relation-queries#include-all-fields-for-a-specific-relation)
+- [Select specific relation fields](relation-queries#select-specific-relation-fields)
+
+## Relation count
+
+In [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later, you can [`include` or `select` a count of relations](aggregation-grouping-summarizing#count-relations) alongside fields - for example, a user's post count.
diff --git a/docs/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx b/docs/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx
new file mode 100644
index 0000000000..4bddafa2c5
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/037-relation-queries.mdx
@@ -0,0 +1,1315 @@
+---
+title: 'Relation queries'
+metaTitle: 'Relation queries (Concepts)'
+metaDescription: 'Prisma Client provides convenient queries for working with relations, such as a fluent API, nested writes (transactions), nested reads and relation filters.'
+tocDepth: 4
+---
+
+
+
+A key feature of Prisma Client is the ability to query [relations](/orm/prisma-schema/data-model/relations) between two or more models. Relation queries include:
+
+- [Nested reads](#nested-reads) (sometimes referred to as _eager loading_) via [`select`](/orm/reference/prisma-client-reference#select) and [`include`](/orm/reference/prisma-client-reference#include)
+- [Nested writes](#nested-writes) with [transactional](transactions) guarantees
+- [Filtering on related records](#relation-filters)
+
+Prisma Client also has a [fluent API for traversing relations](#fluent-api).
+
+
+
+## Nested reads
+
+Nested reads allow you to read related data from multiple tables in your database - such as a user and that user's posts. You can:
+
+- Use [`include`](/orm/reference/prisma-client-reference#include) to include related records, such as a user's posts or profile, in the query response.
+- Use a nested [`select`](/orm/reference/prisma-client-reference#select) to include specific fields from a related record. You can also nest `select` inside an `include`.
+
+### Relation load strategies (Preview)
+
+Since version [5.9.0](https://github.com/prisma/prisma/releases/tag/5.9.0), you can decide on a per-query-level _how_ you want Prisma Client to execute a relation query (i.e. what _load strategy_ should be applied) via the `relationLoadStrategy` option.
+
+Because the `relationLoadStrategy` option is currently in Preview, you need to enable it via the `relationJoins` preview feature flag in your Prisma schema file:
+
+```prisma file=schema.prisma
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["relationJoins"]
+}
+```
+
+After adding this flag, you need to run `prisma generate` again to re-generate Prisma Client. Also note that this feature is currently only available on PostgreSQL and CockroachDB for now.
+
+Prisma Client supports two load strategies for relations:
+
+- `join` (default): Uses a database-level `LATERAL JOIN` and fetches all data with a single query to the database.
+- `query`: Sends multiple queries to the database (one per table) and joins them on the application level.
+
+Another important difference between these two options is that the `join` strategy uses JSON aggregation on the database level. That means that it creates the JSON structures returned by Prisma Client already in the database which saves computation resources on the application level.
+
+> **Note**: Once `relationLoadStrategy` moves from [Preview](/orm/more/releases#preview) into [General Availability](/orm/more/releases/#generally-available-ga), `join` will universally become the default for all relation queries.
+
+#### Examples
+
+You can use the `relationLoadStrategy` option on the top-level in any query that supports `include` or `select`.
+
+Here is an example with `include`:
+
+```ts
+const users = await prisma.user.findMany({
+ relationLoadStrategy: 'join', // or 'query'
+ include: {
+ posts: true,
+ },
+})
+```
+
+And here is another example with `select`:
+
+```ts
+const users = await prisma.user.findMany({
+ relationLoadStrategy: 'join', // or 'query'
+ select: {
+ posts: true,
+ },
+})
+```
+
+#### When to use which load strategy?
+
+- The `join` strategy will be more effective in most scenarios. It uses a combination of `LATERAL JOINs` and JSON aggregation to reduce redundancy in result sets and delegate the work of transforming the query results into the expected JSON structures on the database server.
+- There may be edge cases where `query` could be more performant depending on the characteristics of the dataset and query. We recommend that you profile your database queries to identify these situations.
+- Use `query` if you want to save resources on the database server and do heavy-lifting of merging and transforming data in the application server which might be easier to scale.
+- Older database versions that don’t implement the `LATERAL` keyword may struggle require query complexity and data redundancy so that sending individual queries could be more performant.
+
+### Include a relation
+
+The following example returns a single user and that user's posts:
+
+
+
+
+```ts
+const user = await prisma.user.findFirst({
+ include: {
+ posts: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 19,
+ name: null,
+ email: 'emma@prisma.io',
+ profileViews: 0,
+ role: 'USER',
+ coinflips: [],
+ posts: [
+ {
+ id: 20,
+ title: 'My first post',
+ published: true,
+ authorId: 19,
+ comments: null,
+ views: 0,
+ likes: 0
+ },
+ {
+ id: 21,
+ title: 'How to make cookies',
+ published: true,
+ authorId: 19,
+ comments: null,
+ views: 0,
+ likes: 0
+ }
+ ]
+}
+```
+
+
+
+
+### Include all fields for a specific relation
+
+The following example returns a post and its author:
+
+
+
+
+```ts
+const post = await prisma.post.findFirst({
+ include: {
+ author: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 17,
+ title: 'How to make cookies',
+ published: true,
+ authorId: 16,
+ comments: null,
+ views: 0,
+ likes: 0,
+ author: {
+ id: 16,
+ name: null,
+ email: 'orla@prisma.io',
+ profileViews: 0,
+ role: 'USER',
+ coinflips: [],
+ },
+}
+```
+
+
+
+
+### Include deeply nested relations
+
+You can nest `include` options to include relations of relations. The following example returns a user's posts, and each post's categories:
+
+
+
+
+```ts
+const user = await prisma.user.findFirst({
+ include: {
+ posts: {
+ include: {
+ categories: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 40,
+ "name": "Yvette",
+ "email": "yvette@prisma.io",
+ "profileViews": 0,
+ "role": "USER",
+ "coinflips": [],
+ "testing": [],
+ "city": null,
+ "country": "Sweden",
+ "posts": [
+ {
+ "id": 66,
+ "title": "How to make an omelette",
+ "published": true,
+ "authorId": 40,
+ "comments": null,
+ "views": 0,
+ "likes": 0,
+ "categories": [
+ {
+ "id": 3,
+ "name": "Easy cooking"
+ }
+ ]
+ },
+ {
+ "id": 67,
+ "title": "How to eat an omelette",
+ "published": true,
+ "authorId": 40,
+ "comments": null,
+ "views": 0,
+ "likes": 0,
+ "categories": []
+ }
+ ]
+}
+```
+
+
+
+
+### Select specific relation fields
+
+You can use a nested `select` to choose a subset of relation fields to return. For example, the following query returns the user's `name` and the `title` of each related post:
+
+
+
+
+```ts
+const user = await prisma.user.findFirst({
+ select: {
+ name: true,
+ posts: {
+ select: {
+ title: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ name: "Elsa",
+ posts: [ { title: 'My first post' }, { title: 'How to make cookies' } ]
+}
+```
+
+
+
+
+You can also nest a `select` inside an `include` - the following example returns _all_ `User` fields and the `title` field of each post:
+
+
+
+
+```ts
+const user = await prisma.user.findFirst({
+ include: {
+ posts: {
+ select: {
+ title: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 1,
+ "name": null,
+ "email": "martina@prisma.io",
+ "profileViews": 0,
+ "role": "USER",
+ "coinflips": [],
+ "posts": [
+ { "title": "How to grow salad" },
+ { "title": "How to ride a horse" }
+ ]
+}
+```
+
+
+
+
+Note that you **cannot** use `select` and `include` _on the same level_. This means that if you choose to `include` a user's post and `select` each post's title, you cannot `select` only the users' `email`:
+
+
+
+
+```ts highlight=3,6;delete
+// The following query returns an exception
+const user = await prisma.user.findFirst({
+ select: { // This won't work!
+ email: true
+ }
+ include: { // This won't work!
+ posts: {
+ select: {
+ title: true
+ }
+ }
+ },
+})
+```
+
+
+
+
+```code no-copy
+Invalid `prisma.user.findUnique()` invocation:
+
+{
+ where: {
+ id: 19
+ },
+ select: {
+ ~~~~~~
+ email: true
+ },
+ include: {
+ ~~~~~~~
+ posts: {
+ select: {
+ title: true
+ }
+ }
+ }
+}
+
+
+Please either use `include` or `select`, but not both at the same time.
+```
+
+
+
+
+Instead, use nested `select` options:
+
+```ts
+const user = await prisma.user.findFirst({
+ select: {
+ // This will work!
+ email: true,
+ posts: {
+ select: {
+ title: true,
+ },
+ },
+ },
+})
+```
+
+## Relation count
+
+In [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later, you can [`include` or `select` a count of relations](aggregation-grouping-summarizing#count-relations) alongside fields - for example, a user's post count.
+
+
+
+
+```ts
+const relationCount = await prisma.user.findMany({
+ include: {
+ _count: {
+ select: { posts: true },
+ },
+ },
+})
+```
+
+
+
+
+```code no-copy
+{ id: 1, _count: { posts: 3 } },
+{ id: 2, _count: { posts: 2 } },
+{ id: 3, _count: { posts: 2 } },
+{ id: 4, _count: { posts: 0 } },
+{ id: 5, _count: { posts: 0 } }
+```
+
+
+
+
+## Filter a list of relations
+
+When you use `select` or `include` to return a subset of the related data, you can **filter and sort the list of relations** inside the `select` or `include`.
+
+For example, the following query returns all users and a list of titles of the unpublished posts associated with each user:
+
+```ts
+const result = await prisma.user.findFirst({
+ select: {
+ posts: {
+ where: {
+ published: false,
+ },
+ orderBy: {
+ title: 'asc',
+ },
+ select: {
+ title: true,
+ },
+ },
+ },
+})
+```
+
+You can also write the same query using `include` as follows:
+
+```ts
+const result = await prisma.user.findFirst({
+ include: {
+ posts: {
+ where: {
+ published: true,
+ },
+ orderBy: {
+ title: 'asc',
+ },
+ },
+ },
+})
+```
+
+## Nested writes
+
+A nested write allows you to write **relational data** to your database in **a single transaction**.
+
+Nested writes:
+
+- Provide **transactional guarantees** for creating, updating or deleting data across multiple tables in a single Prisma Client query. If any part of the query fails (for example, creating a user succeeds but creating posts fails), Prisma Client rolls back all changes.
+- Support any level of nesting supported by the data model.
+- Are available for [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) when using the model's create or update query. The following section shows the nested write options that are available per query.
+
+### Create a related record
+
+You can create a record and one or more related records at the same time. The following query creates a `User` record and two related `Post` records:
+
+
+
+
+```ts highlight=5-10;normal
+const result = await prisma.user.create({
+ data: {
+ email: 'elsa@prisma.io',
+ name: 'Elsa Prisma',
+ posts: {
+ create: [
+ { title: 'How to make an omelette' },
+ { title: 'How to eat an omelette' },
+ ],
+ },
+ },
+ include: {
+ posts: true, // Include all posts in the returned object
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 29,
+ name: 'Elsa',
+ email: 'elsa@prisma.io',
+ profileViews: 0,
+ role: 'USER',
+ coinflips: [],
+ posts: [
+ {
+ id: 22,
+ title: 'How to make an omelette',
+ published: true,
+ authorId: 29,
+ comments: null,
+ views: 0,
+ likes: 0
+ },
+ {
+ id: 23,
+ title: 'How to eat an omelette',
+ published: true,
+ authorId: 29,
+ comments: null,
+ views: 0,
+ likes: 0
+ }
+ ]
+}
+```
+
+
+
+
+### Create a single record and multiple related records
+
+There are two ways to create or update a single record and multiple related records - for example, a user with multiple posts:
+
+- Use a nested [`create`](/orm/reference/prisma-client-reference#create-1) query
+- Use a nested [`createMany`](/orm/reference/prisma-client-reference#createmany-1) query
+
+Each technique has pros and cons:
+
+| Feature | `create` | `createMany` | Notes |
+| :------------------------------------ | :------- | :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Creates one record at a time | ✔ | ✘ | Potentially less performant. |
+| Creates all records in one query | ✘ | ✔ | Potentially more performant. |
+| Supports nesting additional relations | ✔ | ✘ \* | For example, you can create a user, several posts, and several comments per post in one query. \* You can manually set a foreign key in a has-one relation - for example: `{ authorId: 9}` |
+| Supports skipping duplicate records | ✘ | ✔ | Use `skipDuplicates` query option. |
+| Supports has-many relations | ✔ | ✔ | For example, you can create a user and multiple posts (one user has many posts) |
+| Supports many-to-many relations | ✔ | ✘ | For example, you can create a post and several categories (one post can have many categories, and one category can have many posts) |
+
+The following query uses nested [`create`](/orm/reference/prisma-client-reference#create) to create:
+
+- One user
+- Two posts
+- One post category
+
+The example uses a nested `include` to include all posts and post categories.
+
+
+
+
+```ts highlight=5-17;normal
+const result = await prisma.user.create({
+ data: {
+ email: 'yvette@prisma.io',
+ name: 'Yvette',
+ posts: {
+ create: [
+ {
+ title: 'How to make an omelette',
+ categories: {
+ create: {
+ name: 'Easy cooking',
+ },
+ },
+ },
+ { title: 'How to eat an omelette' },
+ ],
+ },
+ },
+ include: {
+ // Include posts
+ posts: {
+ include: {
+ categories: true, // Include post categories
+ },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 40,
+ "name": "Yvette",
+ "email": "yvette@prisma.io",
+ "profileViews": 0,
+ "role": "USER",
+ "coinflips": [],
+ "testing": [],
+ "city": null,
+ "country": "Sweden",
+ "posts": [
+ {
+ "id": 66,
+ "title": "How to make an omelette",
+ "published": true,
+ "authorId": 40,
+ "comments": null,
+ "views": 0,
+ "likes": 0,
+ "categories": [
+ {
+ "id": 3,
+ "name": "Easy cooking"
+ }
+ ]
+ },
+ {
+ "id": 67,
+ "title": "How to eat an omelette",
+ "published": true,
+ "authorId": 40,
+ "comments": null,
+ "views": 0,
+ "likes": 0,
+ "categories": []
+ }
+ ]
+}
+```
+
+
+
+
+The following query uses a nested [`createMany`](/orm/reference/prisma-client-reference#create) to create:
+
+- One user
+- Two posts
+
+The example uses a nested `include` to include all posts.
+
+
+
+
+```ts highlight=4-8;normal
+const result = await prisma.user.create({
+ data: {
+ email: 'saanvi@prisma.io',
+ posts: {
+ createMany: {
+ data: [{ title: 'My first post' }, { title: 'My second post' }],
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ "id": 43,
+ "name": null,
+ "email": "saanvi@prisma.io",
+ "profileViews": 0,
+ "role": "USER",
+ "coinflips": [],
+ "testing": [],
+ "city": null,
+ "country": "India",
+ "posts": [
+ {
+ "id": 70,
+ "title": "My first post",
+ "published": true,
+ "authorId": 43,
+ "comments": null,
+ "views": 0,
+ "likes": 0
+ },
+ {
+ "id": 71,
+ "title": "My second post",
+ "published": true,
+ "authorId": 43,
+ "comments": null,
+ "views": 0,
+ "likes": 0
+ }
+ ]
+}
+```
+
+
+
+
+
+
+**Note**: It is **not possible** to nest an additional `create` or `createMany` inside the highlighted query, which means that you cannot create a user, posts, and post categories at the same time.
+
+
+
+### Create multiple records and multiple related records
+
+You cannot access relations in a `createMany` query, which means that you cannot create multiple users and multiple posts in a single nested write. The following is **not** possible:
+
+```ts highlight=6-8,13-15;delete
+const createMany = await prisma.user.createMany({
+ data: [
+ {
+ name: 'Yewande',
+ email: 'yewande@prisma.io',
+ posts: {
+ // Not possible to create posts!
+ },
+ },
+ {
+ name: 'Noor',
+ email: 'noor@prisma.io',
+ posts: {
+ // Not possible to create posts!
+ },
+ },
+ ],
+})
+```
+
+### Connect multiple records
+
+The following query creates ([`create`](/orm/reference/prisma-client-reference#create) ) a new `User` record and connects that record ([`connect`](/orm/reference/prisma-client-reference#connect) ) to three existing posts:
+
+
+
+
+```ts highlight=4-6;normal
+const result = await prisma.user.create({
+ data: {
+ email: 'vlad@prisma.io',
+ posts: {
+ connect: [{ id: 8 }, { id: 9 }, { id: 10 }],
+ },
+ },
+ include: {
+ posts: true, // Include all posts in the returned object
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 27,
+ name: null,
+ email: 'vlad@prisma.io',
+ profileViews: 0,
+ role: 'USER',
+ coinflips: [],
+ posts: [
+ {
+ id: 10,
+ title: 'An existing post',
+ published: true,
+ authorId: 27,
+ comments: {},
+ views: 0,
+ likes: 0
+ }
+ ]
+}
+```
+
+
+
+
+> **Note**: Prisma Client throws an exception if any of the post records cannot be found: `connect: [{ id: 8 }, { id: 9 }, { id: 10 }]`
+
+### Connect a single record
+
+You can [`connect`](/orm/reference/prisma-client-reference#connect) an existing record to a new or existing user. The following query connects an existing post (`id: 11`) to an existing user (`id: 9`)
+
+```ts highlight=6-9;normal
+const result = await prisma.user.update({
+ where: {
+ id: 9,
+ },
+ data: {
+ posts: {
+ connect: {
+ id: 11,
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+### Connect _or_ create a record
+
+If a related record may or may not already exist, use [`connectOrCreate`](/orm/reference/prisma-client-reference#connectorcreate) to connect the related record:
+
+- Connect a `User` with the email address `viola@prisma.io` _or_
+- Create a new `User` with the email address `viola@prisma.io` if the user does not already exist
+
+
+
+
+```ts highlight=4-14;normal
+const result = await prisma.post.create({
+ data: {
+ title: 'How to make croissants',
+ author: {
+ connectOrCreate: {
+ where: {
+ email: 'viola@prisma.io',
+ },
+ create: {
+ email: 'viola@prisma.io',
+ name: 'Viola',
+ },
+ },
+ },
+ },
+ include: {
+ author: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 26,
+ title: 'How to make croissants',
+ published: true,
+ authorId: 43,
+ views: 0,
+ likes: 0,
+ author: {
+ id: 43,
+ name: 'Viola',
+ email: 'viola@prisma.io',
+ profileViews: 0,
+ role: 'USER',
+ coinflips: []
+ }
+}
+```
+
+
+
+
+### Disconnect a related record
+
+To `disconnect` one out of a list of records (for example, a specific blog post) provide the ID or unique identifier of the record(s) to disconnect:
+
+
+
+
+```ts highlight=6-8;normal
+const result = await prisma.user.update({
+ where: {
+ id: 16,
+ },
+ data: {
+ posts: {
+ disconnect: [{ id: 12 }, { id: 19 }],
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 16,
+ name: null,
+ email: 'orla@prisma.io',
+ profileViews: 0,
+ role: 'USER',
+ coinflips: [],
+ posts: []
+}
+```
+
+
+
+
+To `disconnect` _one_ record (for example, a post's author), use `disconnect: true`:
+
+
+
+
+```ts highlight=6-8;normal
+const result = await prisma.post.update({
+ where: {
+ id: 23,
+ },
+ data: {
+ author: {
+ disconnect: true,
+ },
+ },
+ include: {
+ author: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 23,
+ title: 'How to eat an omelette',
+ published: true,
+ authorId: null,
+ comments: null,
+ views: 0,
+ likes: 0,
+ author: null
+}
+```
+
+
+
+
+### Disconnect all related records
+
+To [`disconnect`](/orm/reference/prisma-client-reference#disconnect) _all_ related records in a one-to-many relation (a user has many posts), `set` the relation to an empty list as shown:
+
+
+
+
+```ts highlight=6-8;normal
+const result = await prisma.user.update({
+ where: {
+ id: 16,
+ },
+ data: {
+ posts: {
+ set: [],
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ id: 16,
+ name: null,
+ email: 'orla@prisma.io',
+ profileViews: 0,
+ role: 'USER',
+ coinflips: [],
+ posts: []
+}
+```
+
+
+
+
+### Delete all related records
+
+Delete all related `Post` records:
+
+```ts highlight=6-8;normal
+const result = await prisma.user.update({
+ where: {
+ id: 11,
+ },
+ data: {
+ posts: {
+ deleteMany: {},
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+### Delete specific related records
+
+Update a user by deleting all unpublished posts:
+
+```ts highlight=6-10;normal
+const result = await prisma.user.update({
+ where: {
+ id: 11,
+ },
+ data: {
+ posts: {
+ deleteMany: {
+ published: false,
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+Update a user by deleting specific posts:
+
+```ts highlight=6-8;normal
+const result = await prisma.user.update({
+ where: {
+ id: 6,
+ },
+ data: {
+ posts: {
+ deleteMany: [{ id: 7 }],
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+### Update all related records (or filter)
+
+You can use a nested `updateMany` to update _all_ related records for a particular user. The following query unpublishes all posts for a specific user:
+
+```ts highlight=6-15;normal
+const result = await prisma.user.update({
+ where: {
+ id: 6,
+ },
+ data: {
+ posts: {
+ updateMany: {
+ where: {
+ published: true,
+ },
+ data: {
+ published: false,
+ },
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+### Update a specific related record
+
+```ts highlight=6-15;normal
+const result = await prisma.user.update({
+ where: {
+ id: 6,
+ },
+ data: {
+ posts: {
+ update: {
+ where: {
+ id: 9,
+ },
+ data: {
+ title: 'My updated title',
+ },
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+### Update _or_ create a related record
+
+The following query uses a nested `upsert` to update `"bob@prisma.io"` if that user exists, or create the user if they do not exist:
+
+```ts highlight=6-17;normal
+const result = await prisma.post.update({
+ where: {
+ id: 6,
+ },
+ data: {
+ author: {
+ upsert: {
+ create: {
+ email: 'bob@prisma.io',
+ name: 'Bob the New User',
+ },
+ update: {
+ email: 'bob@prisma.io',
+ name: 'Bob the existing user',
+ },
+ },
+ },
+ },
+ include: {
+ author: true,
+ },
+})
+```
+
+### Add new related records to an existing record
+
+You can nest `create` or `createMany` inside an `update` to add new related records to an existing record. The following query adds two posts to a user with an `id` of 9:
+
+```ts highlight=6-10;normal
+const result = await prisma.user.update({
+ where: {
+ id: 9,
+ },
+ data: {
+ posts: {
+ createMany: {
+ data: [{ title: 'My first post' }, { title: 'My second post' }],
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+## Relation filters
+
+### Filter on "-to-many" relations
+
+Prisma Client provides the [`some`](/orm/reference/prisma-client-reference#some), [`every`](/orm/reference/prisma-client-reference#every), and [`none`](/orm/reference/prisma-client-reference#none) options to filter records by the properties of related records on the "-to-many" side of the relation. For example, filtering users based on properties of their posts.
+
+For example:
+
+| Requirement | Query option to use |
+| --------------------------------------------------------------------------------- | ----------------------------------- |
+| "I want a list of every `User` that has _at least one_ unpublished `Post` record" | `some` posts are unpublished |
+| "I want a list of every `User` that has _no_ unpublished `Post` records" | `none` of the posts are unpublished |
+| "I want a list of every `User` that has _only_ unpublished `Post` records" | `every` post is unpublished |
+
+For example, the following query returns `User` that meet the following criteria:
+
+- No posts with more than 100 views
+- All posts have less than, or equal to 50 likes
+
+```ts highlight=3-14;normal
+const users = await prisma.user.findMany({
+ where: {
+ posts: {
+ none: {
+ views: {
+ gt: 100,
+ },
+ },
+ every: {
+ likes: {
+ lte: 50,
+ },
+ },
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+### Filter on "-to-one" relations
+
+Prisma Client provides the [`is`](/orm/reference/prisma-client-reference#is) and [`isNot`](/orm/reference/prisma-client-reference#isnot) options to filter records by the properties of related records on the "-to-one" side of the relation. For example, filtering posts based on properties of their author.
+
+For example, the following query returns `Post` records that meet the following criteria:
+
+- Author's name is not Bob
+- Author is older than 40
+
+```ts highlight=3-13;normal
+const users = await prisma.post.findMany({
+ where: {
+ author: {
+ isNot: {
+ name: 'Bob',
+ },
+ is: {
+ age: {
+ gt: 40,
+ },
+ },
+ },
+ },
+ include: {
+ author: true,
+ },
+})
+```
+
+### Filter on absence of "-to-many" records
+
+For example, the following query uses `none` to return all users that have zero posts:
+
+```ts highlight=3-5;normal
+const usersWithZeroPosts = await prisma.user.findMany({
+ where: {
+ posts: {
+ none: {},
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+### Filter on absence of "-to-one" relations
+
+The following query returns all posts that don't have an author relation:
+
+```js highlight=3;normal
+const postsWithNoAuthor = await prisma.post.findMany({
+ where: {
+ author: null, // or author: { }
+ },
+ include: {
+ author: true,
+ },
+})
+```
+
+### Filter on presence of related records
+
+The following query returns all users with at least one post:
+
+```ts highlight=3-5;normal
+const usersWithSomePosts = await prisma.user.findMany({
+ where: {
+ posts: {
+ some: {},
+ },
+ },
+ include: {
+ posts: true,
+ },
+})
+```
+
+## Fluent API
+
+The fluent API lets you _fluently_ traverse the [relations](/orm/prisma-schema/data-model/relations) of your models via function calls. Note that the _last_ function call determines the return type of the entire query (the respective type annotations are added in the code snippets below to make that explicit).
+
+This query returns all `Post` records by a specific `User`:
+
+```ts
+const postsByUser: Post[] = await prisma.user
+ .findUnique({ where: { email: 'alice@prisma.io' } })
+ .posts()
+```
+
+This is equivalent to the following `findMany` query:
+
+```ts
+const postsByUser = await prisma.post.findMany({
+ where: {
+ author: {
+ email: 'alice@prisma.io',
+ },
+ },
+})
+```
+
+The main difference between the queries is that the fluent API call is translated into two separate database queries while the other one only generates a single query (see this [GitHub issue](https://github.com/prisma/prisma/issues/1984))
+
+> **Note**: You can use the fact that `.findUnique({ where: { email: 'alice@prisma.io' } }).posts()` queries are automatically batched by the Prisma dataloader to [avoid the n+1 problem in GraphQL resolvers](/orm/prisma-client/queries/query-optimization-performance#solving-n1-in-graphql-with-findunique-and-prismas-dataloader).
+
+This request returns all categories by a specific post:
+
+```ts
+const categoriesOfPost: Category[] = await prisma.post
+ .findUnique({ where: { id: 1 } })
+ .categories()
+```
+
+Note that you can chain as many queries as you like. In this example, the chaining starts at `Profile` and goes over `User` to `Post`:
+
+```ts
+const posts: Post[] = await prisma.profile
+ .findUnique({ where: { id: 1 } })
+ .user()
+ .posts()
+```
+
+The only requirement for chaining is that the previous function call must return only a _single object_ (e.g. as returned by a `findUnique` query or a "to-one relation" like `profile.user()`).
+
+The following query is **not possible** because `findMany` does not return a single object but a _list_:
+
+```ts
+// This query is illegal
+const posts = await prisma.user.findMany().posts()
+```
diff --git a/docs/200-orm/200-prisma-client/100-queries/050-filtering-and-sorting.mdx b/docs/200-orm/200-prisma-client/100-queries/050-filtering-and-sorting.mdx
new file mode 100644
index 0000000000..b40960888b
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/050-filtering-and-sorting.mdx
@@ -0,0 +1,452 @@
+---
+title: 'Filtering and Sorting'
+metaTitle: 'Filtering and Sorting (Concepts)'
+metaDescription: 'Use Prisma Client API to filter records by any combination of fields or related record fields, and/or sort query results.'
+tocDepth: 3
+---
+
+
+
+Prisma Client supports [filtering](#filtering) with the `where` query option, and [sorting](#sorting) with the `orderBy` query option.
+
+
+
+## Filtering
+
+Prisma Client allows you to filter records on any combination of model fields, [including related models](#filter-on-relations), and supports a variety of [filter conditions](#filter-conditions-and-operators).
+
+
+
+Some filter conditions use the SQL operators `LIKE` and `ILIKE` which may cause unexpected behavior in your queries. Please refer to [our filtering FAQs](#filtering-faqs) for more information.
+
+
+
+The following query:
+
+- Returns all `User` records with:
+ - an email address that ends with `prisma.io` _and_
+ - at least one published post (a relation query)
+- Returns all `User` fields
+- Includes all related `Post` records where `published` equals `true`
+
+
+
+
+```ts
+const result = await prisma.user.findMany({
+ where: {
+ email: {
+ endsWith: 'prisma.io',
+ },
+ posts: {
+ some: {
+ published: true,
+ },
+ },
+ },
+ include: {
+ posts: {
+ where: {
+ published: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```json5 no-copy
+[
+ {
+ id: 1,
+ name: 'Ellen',
+ email: 'ellen@prisma.io',
+ role: 'USER',
+ posts: [
+ {
+ id: 1,
+ title: 'How to build a house',
+ published: true,
+ authorId: 1,
+ },
+ {
+ id: 2,
+ title: 'How to cook kohlrabi',
+ published: true,
+ authorId: 1,
+ },
+ ],
+ },
+]
+```
+
+
+
+
+### Filter conditions and operators
+
+Refer to Prisma Client's reference documentation for [a full list of operators](/orm/reference/prisma-client-reference#filter-conditions-and-operators) , such as `startsWith` and `contains`.
+
+#### Combining operators
+
+You can use operators (such as [`NOT`](/orm/reference/prisma-client-reference#not-1) and [`OR`](/orm/reference/prisma-client-reference#or) ) to filter by a combination of conditions. The following query returns all users with an `email` that ends in `"prisma.io"` or `"gmail.com"`, but not `"hotmail.com"`:
+
+
+
+
+```ts
+const result = await prisma.user.findMany({
+ where: {
+ OR: [
+ {
+ email: {
+ endsWith: 'prisma.io',
+ },
+ },
+ { email: { endsWith: 'gmail.com' } },
+ ],
+ NOT: {
+ email: {
+ endsWith: 'hotmail.com',
+ },
+ },
+ },
+ select: {
+ email: true,
+ },
+})
+```
+
+
+
+
+```json5 no-copy
+[{ email: 'yewande@prisma.io' }, { email: `raheem@gmail.com` }]
+```
+
+
+
+
+### Filter on null fields
+
+The following query returns all posts whose `content` field is `null`:
+
+```ts
+const posts = await prisma.post.findMany({
+ where: {
+ content: null,
+ },
+})
+```
+
+### Filter for non-null fields
+
+The following query returns all posts whose `content` field is **not** `null`:
+
+```ts
+const posts = await prisma.post.findMany({
+ where: {
+ content: { not: null },
+ },
+})
+```
+
+### Filter on relations
+
+Prisma Client supports [filtering on related records](relation-queries#relation-filters). For example, in the following schema, a user can have many blog posts:
+
+```prisma highlight=5,12-13;normal
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ email String @unique
+ posts Post[] // User can have many posts
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ published Boolean @default(true)
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+}
+```
+
+The one-to-many relation between `User` and `Post` allows you to query users based on their posts - for example, the following query returns all users where _at least one_ post (`some`) has more than 10 views:
+
+```ts
+const result = await prisma.user.findMany({
+ where: {
+ posts: {
+ some: {
+ views: {
+ gt: 10,
+ },
+ },
+ },
+ },
+})
+```
+
+You can also query posts based on the properties of the author. For example, the following query returns all posts where the author's `email` contains `"prisma.io"`:
+
+```ts
+const res = await prisma.post.findMany({
+ where: {
+ author: {
+ email: {
+ contains: 'prisma.io',
+ },
+ },
+ },
+})
+```
+
+### Filter on scalar lists / arrays
+
+Scalar lists (for example, `String[]`) have a special set of [filter conditions](/orm/reference/prisma-client-reference#scalar-list-filters) - for example, the following query returns all posts where the `tags` array contains `databases`:
+
+```ts
+const posts = await client.post.findMany({
+ where: {
+ tags: {
+ has: 'databases',
+ },
+ },
+})
+```
+
+### Case-insensitive filtering
+
+Case-insensitive filtering [is available as a feature for the PostgreSQL and MongoDB providers](case-sensitivity#options-for-case-insensitive-filtering). MySQL, MariaDB and Microsoft SQL Server are case-insensitive by default, and do not require a Prisma Client feature to make case-insensitive filtering possible.
+
+To use case-insensitive filtering, add the `mode` property to a particular filter and specify `insensitive`:
+
+```ts highlight=5;normal
+const users = await prisma.user.findMany({
+ where: {
+ email: {
+ endsWith: 'prisma.io',
+ mode: 'insensitive', // Default value: default
+ },
+ name: {
+ equals: 'Archibald', // Default mode
+ },
+ },
+})
+```
+
+See also: [Case sensitivity](case-sensitivity)
+
+### Filtering FAQs
+
+#### How does filtering work at the database level?
+
+For MySQL and PostgreSQL, Prisma Client utilizes the [`LIKE`](https://www.w3schools.com/sql/sql_like.asp) (and [`ILIKE`](https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE)) operator to search for a given pattern. The operators have built-in pattern matching using symbols unique to `LIKE`. The pattern-matching symbols include `%` for zero or more characters (similar to `*` in other regex implementations) and `_` for one character (similar to `.`)
+
+To match the literal characters, `%` or `_`, make sure you escape those characters. For example:
+
+
+```ts
+const users = await prisma.user.findMany({
+ where: {
+ name: {
+ startsWith: '_benny',
+ },
+ },
+})
+```
+
+
+The above query will match any user whose name starts with a character followed by `benny` such as `7benny` or `&benny`. If you instead wanted to find any user whose name starts with the literal string `_benny`, you could do:
+
+
+```ts highlight=4
+const users = await prisma.user.findMany({
+ where: {
+ name: {
+ startsWith: '\\_benny', // note that the `_` character is escaped, preceding `\` with `\` when included in a string
+ },
+ },
+})
+```
+
+
+## Sorting
+
+Use [`orderBy`](/orm/reference/prisma-client-reference#orderby) to sort a list of records or a nested list of records by a particular field or set of fields. For example, the following query returns all `User` records sorted by `role` and `name`, **and** each user's posts sorted by `title`:
+
+
+
+
+
+```ts
+const usersWithPosts = await prisma.user.findMany({
+ orderBy: [
+ {
+ role: 'desc',
+ },
+ {
+ name: 'desc',
+ },
+ ],
+ include: {
+ posts: {
+ orderBy: {
+ title: 'desc',
+ },
+ select: {
+ title: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+
+```json no-copy
+[
+ {
+ "email": "kwame@prisma.io",
+ "id": 2,
+ "name": "Kwame",
+ "role": "USER",
+ "posts": [
+ {
+ "title": "Prisma in five minutes"
+ },
+ {
+ "title": "Happy Table Friends: Relations in Prisma"
+ }
+ ]
+ },
+ {
+ "email": "emily@prisma.io",
+ "id": 5,
+ "name": "Emily",
+ "role": "USER",
+ "posts": [
+ {
+ "title": "Prisma Day 2020"
+ },
+ {
+ "title": "My first day at Prisma"
+ },
+ {
+ "title": "All about databases"
+ }
+ ]
+ }
+]
+```
+
+
+
+
+
+> **Note**: You can also [sort lists of nested records](relation-queries#filter-a-list-of-relations)
+> to retrieve a single record by ID.
+
+### Sort by relation
+
+You can also sort by properties of a relation. For example, the following query sorts all posts by the author's email address:
+
+```ts
+const posts = await prisma.post.findMany({
+ orderBy: {
+ author: {
+ email: 'asc',
+ },
+ },
+})
+```
+
+### Sort by relation aggregate value
+
+In [2.19.0](https://github.com/prisma/prisma/releases/2.19.0) and later, you can sort by the **count of related records**.
+
+For example, the following query sorts users by the number of related posts:
+
+```ts
+const getActiveUsers = await prisma.user.findMany({
+ take: 10,
+ orderBy: {
+ posts: {
+ _count: 'desc',
+ },
+ },
+})
+```
+
+> **Note**: It is not currently possible to [return the count of a relation](https://github.com/prisma/prisma/issues/5079).
+
+### Sort by relevance (PostgreSQL)
+
+In [3.5.0](https://github.com/prisma/prisma/releases/3.5.0) and later, when using PostgreSQL you can sort records by relevance to the query using the `_relevance` keyword. This uses the relevance ranking functions from PostgreSQL's full text search feature, which are explained further in [the PostgreSQL documentation](https://www.postgresql.org/docs/12/textsearch-controls.html).
+
+Enable order by relevance with the `fullTextSearch` [preview feature](/orm/prisma-client/queries/full-text-search):
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["fullTextSearch"]
+}
+```
+
+Ordering by relevance can be used either separately from or together with the `search` filter: `_relevance` is used to order the list, while `search` filters the unordered list. For example, the following query uses `_relevance` to order the list of users by relevance to the search term `'developer'` in their bio, and `search` to filter the list:
+
+```ts
+const getUsersByRelevance = await prisma.user.findMany({
+ take: 10,
+ orderBy: {
+ _relevance: {
+ fields: ['bio'],
+ search: 'developer',
+ sort: 'asc',
+ },
+ },
+})
+```
+
+### Sort with null records first or last
+
+
+
+This feature is generally available in version `4.16.0` and later. To use this feature in versions [`4.1.0`](https://github.com/prisma/prisma/releases/tag/4.1.0) to [`4.15.0`](https://github.com/prisma/prisma/releases/tag/4.15.0) the [Preview feature](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `orderByNulls` will need to be enabled.
+
+
+
+
+
+Note: Prisma Client does not support this feature for MongoDB.
+
+
+
+You can sort the results so that records with `null` fields appear either first or last.
+
+
+
+**Note:** You can only sort by nulls on optional [scalar](/orm/prisma-schema/data-model/models#scalar-fields) fields. If you try to sort by nulls on a required or [relation](/orm/prisma-schema/data-model/models#relation-fields) field, Prisma Client throws a [P2009 error](/orm/reference/error-reference#p2009).
+
+
+
+Example: If `updatedAt` is an optional field, then the following query sorts posts by `updatedAt`, with null records at the end:
+
+```ts
+const posts = await prisma.post.findMany({
+ orderBy: {
+ updatedAt: { sort: 'asc', nulls: 'last' },
+ },
+})
+```
+
+### Sorting FAQs
+
+#### Can I perform case-insensitive sorting?
+
+Follow [issue #841 on GitHub](https://github.com/prisma/prisma-client-js/issues/841).
diff --git a/docs/200-orm/200-prisma-client/100-queries/055-pagination.mdx b/docs/200-orm/200-prisma-client/100-queries/055-pagination.mdx
new file mode 100644
index 0000000000..315509255a
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/055-pagination.mdx
@@ -0,0 +1,224 @@
+---
+title: 'Pagination'
+metaTitle: 'Pagination (Reference)'
+metaDescription: 'Prisma Client supports both offset pagination and cursor-based pagination. Learn more about the pros and cons of different pagination approaches and how to implement them.'
+---
+
+
+
+Prisma Client supports both offset pagination and cursor-based pagination.
+
+
+
+## Offset pagination
+
+Offset pagination uses `skip` and `take` to skip a certain number of results and select a limited range. The following query skips the first 3 `Post` records and returns records 4 - 7:
+
+```ts line-number
+const results = await prisma.post.findMany({
+ skip: 3,
+ take: 4,
+})
+```
+
+
+
+To implement pages of results, you would just `skip` the number of pages multiplied by the number of results you show per page.
+
+### ✔ Pros of offset pagination
+
+- You can jump to any page immediately. For example, you can `skip` 200 records and `take` 10, which simulates jumping straight to page 21 of the result set (the underlying SQL uses `OFFSET`). This is not possible with cursor-based pagination.
+- You can paginate the same result set in any sort order. For example, you can jump to page 21 of a list of `User` records sorted by first name. This is not possible with cursor-based pagination, which requires sorting by a unique, sequential column.
+
+### ✘ Cons of offset pagination
+
+- Offset pagination **does not scale** at a database level. For example, if you skip 200,000 records and take the first 10, the database still has to traverse the first 200,000 records before returning the 10 that you asked for - this negatively affects performance.
+
+### Use cases for offset pagination
+
+- Shallow pagination of a small result set. For example, a blog interface that allows you to filter `Post` records by author and paginate the results.
+
+### Example: Filtering and offset pagination
+
+The following query returns all records where the `email` field contains `prisma.io`. The query skips the first 40 records and returns records 41 - 50.
+
+```ts line-number
+const results = await prisma.post.findMany({
+ skip: 40,
+ take: 10,
+ where: {
+ email: {
+ contains: 'prisma.io',
+ },
+ },
+})
+```
+
+### Example: Sorting and offset pagination
+
+The following query returns all records where the `email` field contains `Prisma`, and sorts the result by the `title` field. The query skips the first 200 records and returns records 201 - 220.
+
+```ts line-number
+const results = await prisma.post.findMany({
+ skip: 200,
+ take: 20,
+ where: {
+ email: {
+ contains: 'Prisma',
+ },
+ },
+ orderBy: {
+ title: 'desc',
+ },
+})
+```
+
+## Cursor-based pagination
+
+Cursor-based pagination uses `cursor` and `take` to return a limited set of results before or after a given **cursor**. A cursor bookmarks your location in a result set and must be a unique, sequential column - such as an ID or a timestamp.
+
+The following example returns the first 4 `Post` records that contain the word `"Prisma"` and saves the ID of the last record as `myCursor`:
+
+> **Note**: Since this is the first query, there is no cursor to pass in.
+
+```ts line-number
+const firstQueryResults = await prisma.post.findMany({
+ take: 4,
+ where: {
+ title: {
+ contains: 'Prisma' /* Optional filter */,
+ },
+ },
+ orderBy: {
+ id: 'asc',
+ },
+})
+
+// Bookmark your location in the result set - in this
+// case, the ID of the last post in the list of 4.
+
+|const lastPostInResults = firstQueryResults[3] // Remember: zero-based index! :)
+|const myCursor = lastPostInResults.id // Example: 29
+```
+
+The following diagram shows the IDs of the first 4 results - or page 1. The cursor for the next query is **29**:
+
+
+
+The second query returns the first 4 `Post` records that contain the word `"Prisma"` **after the supplied cursor** (in other words - IDs that are larger than **29**):
+
+```ts line-number
+const secondQueryResults = await prisma.post.findMany({
+ take: 4,
+ skip: 1, // Skip the cursor
+| cursor: {
+| id: myCursor,
+| },
+ where: {
+ title: {
+ contains: 'Prisma' /* Optional filter */,
+ },
+ },
+ orderBy: {
+ id: 'asc',
+ },
+})
+
+const lastPostInResults = secondQueryResults[3] // Remember: zero-based index! :)
+const myCursor = lastPostInResults.id // Example: 52
+```
+
+The following diagram shows the first 4 `Post` records **after** the record with ID **29**. In this example, the new cursor is **52**:
+
+
+
+### FAQ
+
+#### Do I always have to skip: 1?
+
+If you do not `skip: 1`, your result set will include your previous cursor. The first query returns four results and the cursor is **29**:
+
+
+
+Without `skip: 1`, the second query returns 4 results after (and _including_) the cursor:
+
+
+
+If you `skip: 1`, the cursor is not included:
+
+
+
+You can choose to `skip: 1` or not depending on the pagination behavior that you want.
+
+#### Can I guess the value of the cursor?
+
+If you guess the value of the next cursor, you will page to an unknown location in your result set. Although IDs are sequential, you cannot predict the rate of increment (`2`, `20`, `32` is more likely than `1`, `2`, `3`, particularly in a filtered result set).
+
+#### Does cursor-based pagination use the concept of a cursor in the underlying database?
+
+No, cursor pagination does not use cursors in the underlying database ([e.g. PostgreSQL](https://www.postgresql.org/docs/9.2/plpgsql-cursors.html)).
+
+#### What happens if the cursor value does not exist?
+
+Using a nonexistent cursor returns `null`. Prisma does not try to locate adjacent values.
+
+### ✔ Pros of cursor-based pagination
+
+- Cursor-based pagination **scales**. The underlying SQL does not use `OFFSET`, but instead queries all `Post` records with an ID greater than the value of `cursor`.
+
+### ✘ Cons of cursor-based pagination
+
+- You must sort by your cursor, which has to be a unique, sequential column.
+- You cannot jump to a specific page using only a cursor. For example, you cannot accurately predict which cursor represents the start of page 400 (page size 20) without first requesting pages 1 - 399.
+
+### Use cases for cursor-based pagination
+
+- Infinite scroll - for example, sort blog posts by date/time descending and request 10 blog posts at a time.
+- Paging through an entire result set in batches - for example, as part of a long-running data export.
+
+### Example: Filtering and cursor-based pagination
+
+```ts line-number
+const secondQuery = await prisma.post.findMany({
+ take: 4,
+ cursor: {
+ id: myCursor,
+ },
+| where: {
+| title: {
+| contains: 'Prisma' /* Optional filter */,
+| },
+ },
+ orderBy: {
+ id: 'asc',
+ },
+})
+```
+
+### Sorting and cursor-based pagination
+
+Cursor-based pagination requires you to sort by a sequential, unique column such as an ID or a timestamp. This value - known as a cursor - bookmarks your place in the result set and allows you to request the next set.
+
+### Example: Paging backwards with cursor-based pagination
+
+To page backwards, set `take` to a negative value. The following query returns 4 `Post` records with an `id` of less than 200, excluding the cursor:
+
+```ts line-number
+const myOldCursor = 200
+
+const firstQueryResults = await prisma.post.findMany({
+ take: -4,
+ skip: 1,
+ cursor: {
+ id: myOldCursor,
+ },
+ where: {
+ title: {
+ contains: 'Prisma' /* Optional filter */,
+ },
+ },
+ orderBy: {
+ id: 'asc',
+ },
+})
+```
diff --git a/docs/200-orm/200-prisma-client/100-queries/056-aggregation-grouping-summarizing.mdx b/docs/200-orm/200-prisma-client/100-queries/056-aggregation-grouping-summarizing.mdx
new file mode 100644
index 0000000000..789f63b9f8
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/056-aggregation-grouping-summarizing.mdx
@@ -0,0 +1,725 @@
+---
+title: 'Aggregation, grouping, and summarizing'
+metaTitle: 'Aggregation, grouping, and summarizing (Concepts)'
+metaDescription: 'Use Prisma Client to aggregate, group by, count, and select distinct.'
+tocDepth: 4
+---
+
+
+
+Prisma Client allows you to count records, aggregate number fields, and select distinct field values.
+
+
+
+## Aggregate
+
+Prisma Client allows you to [`aggregate`](/orm/reference/prisma-client-reference#aggregate) on the **number** fields (such as `Int` and `Float`) of a model. The following query returns the average age of all users:
+
+```ts
+const aggregations = await prisma.user.aggregate({
+ _avg: {
+ age: true,
+ },
+})
+
+console.log('Average age:' + aggregations._avg.age)
+```
+
+You can combine aggregation with filtering and ordering. For example, the following query returns the average age of users:
+
+- Ordered by `age` ascending
+- Where `email` contains `prisma.io`
+- Limited to the 10 users
+
+```ts
+const aggregations = await prisma.user.aggregate({
+ _avg: {
+ age: true,
+ },
+ where: {
+ email: {
+ contains: 'prisma.io',
+ },
+ },
+ orderBy: {
+ age: 'asc',
+ },
+ take: 10,
+})
+
+console.log('Average age:' + aggregations._avg.age)
+```
+
+### Aggregate values are nullable
+
+In [2.21.0](https://github.com/prisma/prisma/releases/tag/2.21.0) and later, aggregations on **nullable fields** can return a `number` or `null`. This excludes `count`, which always returns 0 if no records are found.
+
+Consider the following query, where `age` is nullable in the schema:
+
+
+
+
+```ts
+const aggregations = await prisma.user.aggregate({
+ _avg: {
+ age: true,
+ },
+ _count: {
+ age: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ _avg: {
+ age: null
+ },
+ _count: {
+ age: 9
+ }
+}
+```
+
+
+
+
+The query returns `{ _avg: { age: null } }` in either of the following scenarios:
+
+- There are no users
+- The value of every user's `age` field is `null`
+
+This allows you to differentiate between the true aggregate value (which could be zero) and no data.
+
+## Group by
+
+Prisma Client's [`groupBy`](/orm/reference/prisma-client-reference#groupby) allows you to **group records** by one or more field values - such as `country`, or `country` and `city` and **perform aggregations** on each group, such as finding the average age of people living in a particular city. `groupBy` is a GA in [2.20.0](https://github.com/prisma/prisma/releases/2.20.0) and later.
+
+The following video uses `groupBy` to summarize total COVID-19 cases by continent:
+
+
+
+
+
+
+
+The following example groups all users by the `country` field and returns the total number of profile views for each country:
+
+
+
+
+```ts
+const groupUsers = await prisma.user.groupBy({
+ by: ['country'],
+ _sum: {
+ profileViews: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+;[
+ { country: 'Germany', _sum: { profileViews: 126 } },
+ { country: 'Sweden', _sum: { profileViews: 0 } },
+]
+```
+
+
+
+
+If you have a single element in the `by` option, you can use the following shorthand syntax to express your query:
+
+```ts
+const groupUsers = await prisma.user.groupBy({
+ by: 'country',
+})
+```
+
+### `groupBy` and filtering
+
+`groupBy` supports two levels of filtering: `where` and `having`.
+
+#### Filter records with `where`
+
+Use `where` to filter all records **before grouping**. The following example groups users by country and sums profile views, but only includes users where the email address contains `prisma.io`:
+
+```ts highlight=3-7;normal
+const groupUsers = await prisma.user.groupBy({
+ by: ['country'],
+ where: {
+ email: {
+ contains: 'prisma.io',
+ },
+ },
+ _sum: {
+ profileViews: true,
+ },
+})
+```
+
+#### Filter groups with `having`
+
+Use `having` to filter **entire groups** by an aggregate value such as the sum or average of a field, not individual records - for example, only return groups where the _average_ `profileViews` is greater than 100:
+
+```ts highlight=11-17;normal
+const groupUsers = await prisma.user.groupBy({
+ by: ['country'],
+ where: {
+ email: {
+ contains: 'prisma.io',
+ },
+ },
+ _sum: {
+ profileViews: true,
+ },
+ having: {
+ profileViews: {
+ _avg: {
+ gt: 100,
+ },
+ },
+ },
+})
+```
+
+##### Use case for `having`
+
+The primary use case for `having` is to filter on aggregations. We recommend that you use `where` to reduce the size of your data set as far as possible _before_ grouping, because doing so ✔ reduces the number of records the database has to return and ✔ makes use of indices.
+
+For example, the following query groups all users that are _not_ from Sweden or Ghana:
+
+```ts highlight=4-6;normal
+const fd = await prisma.user.groupBy({
+ by: ['country'],
+ where: {
+ country: {
+ notIn: ['Sweden', 'Ghana'],
+ },
+ },
+ _sum: {
+ profileViews: true,
+ },
+ having: {
+ profileViews: {
+ _min: {
+ gte: 10,
+ },
+ },
+ },
+})
+```
+
+The following query technically achieves the same result, but excludes users from Ghana _after_ grouping. This does not confer any benefit and is not recommended practice.
+
+```ts highlight=4-6,12-14;normal
+const groupUsers = await prisma.user.groupBy({
+ by: ['country'],
+ where: {
+ country: {
+ not: 'Sweden',
+ },
+ },
+ _sum: {
+ profileViews: true,
+ },
+ having: {
+ country: {
+ not: 'Ghana',
+ },
+ profileViews: {
+ _min: {
+ gte: 10,
+ },
+ },
+ },
+})
+```
+
+> **Note**: Within `having`, you can only filter on aggregate values _or_ fields available in `by`.
+
+### `groupBy` and ordering
+
+The following constraints apply when you combine `groupBy` and `orderBy`:
+
+- You can `orderBy` fields that are present in `by`
+- You can `orderBy` aggregate (Preview in 2.21.0 and later)
+- If you use `skip` and/or `take` with `groupBy`, you must also include `orderBy` in the query
+
+#### Order by aggregate group
+
+You can **order by aggregate group**. Prisma added support for using `orderBy with aggregated groups in relational databases in version [2.21.0](https://github.com/prisma/prisma/releases/2.21.0) and support for MongoDB in [3.4.0](https://github.com/prisma/prisma/releases/3.4.0).
+
+The following example sorts each `city` group by the number of users in that group (largest group first):
+
+
+
+
+```ts
+const groupBy = await prisma.user.groupBy({
+ by: ['city'],
+ _count: {
+ city: true,
+ },
+ orderBy: {
+ _count: {
+ city: 'desc',
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+;[
+ { city: 'Berlin', count: { city: 3 } },
+ { city: 'Paris', count: { city: 2 } },
+ { city: 'Amsterdam', count: { city: 1 } },
+]
+```
+
+
+
+
+#### Order by field
+
+The following query orders groups by country, skips the first two groups, and returns the 3rd and 4th group:
+
+```ts
+const groupBy = await prisma.user.groupBy({
+ by: ['country'],
+ _sum: {
+ profileViews: true,
+ },
+ orderBy: {
+ country: 'desc',
+ },
+ skip: 2,
+ take: 2,
+})
+```
+
+### `groupBy` FAQ
+
+#### Can I use `select` with `groupBy`?
+
+You cannot use `select` with `groupBy`. However, all fields included in `by` are automatically returned.
+
+#### What is the difference between using `where` and `having` with `groupBy`?
+
+`where` filters all records before grouping, and `having` filters entire groups and supports filtering on an aggregate field value, such as the average or sum of a particular field in that group.
+
+#### What is the difference between `groupBy` and `distinct`?
+
+Both `distinct` and `groupBy` group records by one or more unique field values. `groupBy` allows you to aggregate data within each group - for example, return the average number of views on posts from Denmark - whereas distinct does not.
+
+## Count
+
+Use [`count`](/orm/reference/prisma-client-reference#count) to count the number of records or non-`null` field values. The following example query counts all users:
+
+```ts
+const userCount = await prisma.user.count()
+```
+
+### Count relations
+
+The ability to count relations is available in version [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later.
+
+
+
+**For versions before 3.0.1**
+You need to add the [preview feature](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `selectRelationCount` and then run `prisma generate`.
+
+
+
+To return a count of relations (for example, a user's post count), use the `_count` parameter with a nested `select` as shown:
+
+
+
+
+```ts
+const usersWithCount = await prisma.user.findMany({
+ include: {
+ _count: {
+ select: { posts: true },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{ id: 1, _count: { posts: 3 } },
+{ id: 2, _count: { posts: 2 } },
+{ id: 3, _count: { posts: 2 } },
+{ id: 4, _count: { posts: 0 } },
+{ id: 5, _count: { posts: 0 } }
+```
+
+
+
+
+The `_count` parameter:
+
+- Can be used inside a top-level `include` _or_ `select`
+- Can be used with any query that returns records (including `delete`, `update`, and `findFirst`)
+- Can return [multiple relation counts](#return-multiple-relation-counts)
+- From version 4.3.0, can [filter relation counts](#filter-the-relation-count)
+
+#### Return a relations count with `include`
+
+The following query includes each user's post count in the results:
+
+
+
+
+```ts
+const usersWithCount = await prisma.user.findMany({
+ include: {
+ _count: {
+ select: { posts: true },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{ id: 1, _count: { posts: 3 } },
+{ id: 2, _count: { posts: 2 } },
+{ id: 3, _count: { posts: 2 } },
+{ id: 4, _count: { posts: 0 } },
+{ id: 5, _count: { posts: 0 } }
+```
+
+
+
+
+#### Return a relations count with `select`
+
+The following query uses `select` to return each user's post count and no other fields:
+
+
+
+
+```ts
+const usersWithCount = await prisma.user.findMany({
+ select: {
+ _count: {
+ select: { posts: true },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ _count: {
+ posts: 3
+ }
+}
+```
+
+
+
+
+#### Return multiple relation counts
+
+The following query returns a count of each user's `posts` and `recipes` and no other fields:
+
+
+
+
+```ts
+const usersWithCount = await prisma.user.findMany({
+ select: {
+ _count: {
+ select: {
+ posts: true,
+ recipes: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ _count: {
+ posts: 3,
+ recipes: 9
+ }
+}
+```
+
+
+
+
+#### Filter the relation count
+
+
+
+This feature is generally available in version `4.16.0` and later. To use this feature in versions [`4.3.0`](https://github.com/prisma/prisma/releases/tag/4.3.0) to [`4.15.0`](https://github.com/prisma/prisma/releases/tag/4.15.0) the [Preview feature](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `filteredRelationCount` will need to be enabled.
+
+
+
+Use `where` to filter the fields returned by the `_count` output type. You can do this on [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields), [relation fields](/orm/prisma-schema/data-model/models#relation-fields) and fields of a [composite type](/orm/prisma-schema/data-model/models#defining-composite-types).
+
+For example, the following query returns all user posts with the title "Hello!":
+
+```ts
+// Count all user posts with the title "Hello!"
+await prisma.user.findMany({
+ select: {
+ _count: {
+ select: {
+ posts: { where: { title: 'Hello!' } },
+ },
+ },
+ },
+})
+```
+
+The following query finds all user posts with comments from an author named "Alice":
+
+```ts
+// Count all user posts that have comments
+// whose author is named "Alice"
+await prisma.user.findMany({
+ select: {
+ _count: {
+ select: {
+ posts: {
+ where: { comments: { some: { author: { is: { name: 'Alice' } } } } },
+ },
+ },
+ },
+ },
+})
+```
+
+### Count non-`null` field values
+
+In [2.15.0](https://github.com/prisma/prisma/releases/2.15.0) and later, you can count all records as well as all instances of non-`null` field values. The following query returns a count of:
+
+- All `User` records (`_all`)
+- All non-`null` `name` values (not distinct values, just values that are not `null`)
+
+
+
+
+```ts
+const userCount = await prisma.user.count({
+ select: {
+ _all: true, // Count all records
+ name: true, // Count all non-null field values
+ },
+})
+```
+
+
+
+
+```js no-copy
+{ _all: 30, name: 10 }
+```
+
+
+
+
+### Filtered count
+
+`count` supports filtering. The following example query counts all users with more than 100 profile views:
+
+```ts
+const userCount = await prisma.user.count({
+ where: {
+ profileViews: {
+ gte: 100,
+ },
+ },
+})
+```
+
+The following example query counts a particular user's posts:
+
+```ts
+const postCount = await prisma.post.count({
+ where: {
+ authorId: 29,
+ },
+})
+```
+
+## Select distinct
+
+Prisma Client allows you to filter duplicate rows from a Prisma Query response to a [`findMany`](/orm/reference/prisma-client-reference#findmany) query using [`distinct`](/orm/reference/prisma-client-reference#distinct) . `distinct` is often used in combination with [`select`](/orm/reference/prisma-client-reference#select) to identify certain unique combinations of values in the rows of your table.
+
+The following example returns all fields for all `User` records with distinct `name` field values:
+
+```ts
+const result = await prisma.user.findMany({
+ where: {},
+ distinct: ['name'],
+})
+```
+
+The following example returns distinct `role` field values (for example, `ADMIN` and `USER`):
+
+
+
+
+```ts
+const distinctRoles = await prisma.user.findMany({
+ distinct: ['role'],
+ select: {
+ role: true,
+ },
+})
+```
+
+
+
+
+```js no-copy
+;[
+ {
+ role: 'USER',
+ },
+ {
+ role: 'ADMIN',
+ },
+]
+```
+
+
+
+
+### `distinct` under the hood
+
+Prisma's `distinct` option does not use SQL `SELECT DISTINCT`. Instead, `distinct` uses:
+
+- A `SELECT` query
+- In-memory post-processing to select distinct
+
+It was designed in this way in order to **support `select` and `include`** as part of `distinct` queries.
+
+The following example selects distinct on `gameId` and `playerId`, ordered by `score`, in order to return **each player's highest score per game**. The query uses `include` and `select` to include additional data:
+
+- Select `score` (field on `Play`)
+- Select related player name (relation between `Play` and `User`)
+- Select related game name (relation between `Play` and `Game`)
+
+
+
+Expand for sample schema
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ play Play[]
+}
+
+model Game {
+ id Int @id @default(autoincrement())
+ name String?
+ play Play[]
+}
+
+model Play {
+ id Int @id @default(autoincrement())
+ score Int? @default(0)
+ playerId Int?
+ player User? @relation(fields: [playerId], references: [id])
+ gameId Int?
+ game Game? @relation(fields: [gameId], references: [id])
+}
+```
+
+
+
+
+
+
+```ts
+const distinctScores = await prisma.play.findMany({
+ distinct: ['playerId', 'gameId'],
+ orderBy: {
+ score: 'desc',
+ },
+ select: {
+ score: true,
+ game: {
+ select: {
+ name: true,
+ },
+ },
+ player: {
+ select: {
+ name: true,
+ },
+ },
+ },
+})
+```
+
+
+
+
+```code no-copy
+[
+ {
+ score: 900,
+ game: { name: 'Pacman' },
+ player: { name: 'Bert Bobberton' }
+ },
+ {
+ score: 400,
+ game: { name: 'Pacman' },
+ player: { name: 'Nellie Bobberton' }
+ }
+]
+```
+
+
+
+
+Without `select` and `distinct`, the query would return:
+
+```
+[
+ {
+ gameId: 2,
+ playerId: 5
+ },
+ {
+ gameId: 2,
+ playerId: 10
+ }
+]
+```
diff --git a/docs/200-orm/200-prisma-client/100-queries/058-transactions.mdx b/docs/200-orm/200-prisma-client/100-queries/058-transactions.mdx
new file mode 100644
index 0000000000..3afed0a1fa
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/058-transactions.mdx
@@ -0,0 +1,1334 @@
+---
+title: 'Transactions and batch queries'
+metaTitle: 'Transactions and batch queries (Reference)'
+metaDescription: 'This page explains the transactions API of Prisma Client.'
+tocDepth: 3
+---
+
+
+
+A database transaction refers to a sequence of read/write operations that are _guaranteed_ to either succeed or fail as a whole. This section describes the ways in which the Prisma Client API supports transactions.
+
+- For more in-depth examples and use cases, refer to the 📖 [transactions guide](/orm/prisma-client/queries/transactions).
+- For information about transactions in general and the reasoning behind Prisma's current solutions, see [Blog: How Prisma supports transactions](https://www.prisma.io/blog/how-prisma-supports-transactions-x45s1d5l0ww1).
+
+
+
+## Transactions overview
+
+
+
+Before Prisma version 4.4.0, you could not set isolation levels on transactions. The isolation level in your database configuration always applied.
+
+
+
+Developers take advantage of the safety guarantees provided by the database by wrapping the operations in a transaction. These guarantees are often summarized using the ACID acronym:
+
+- **Atomic**: Ensures that either _all_ or _none_ operations of the transactions succeed. The transaction is either _committed_ successfully or _aborted_ and _rolled back_.
+- **Consistent**: Ensures that the states of the database before and after the transaction are _valid_ (i.e. any existing invariants about the data are maintained).
+- **Isolated**: Ensures that concurrently running transactions have the same effect as if they were running in serial.
+- **Durability**: Ensures that after the transaction succeeded, any writes are being stored persistently.
+
+While there's a lot of ambiguity and nuance to each of these properties (for example, consistency could actually be considered an _application-level responsibility_ rather than a database property or isolation is typically guaranteed in terms of stronger and weaker _isolation levels_), overall they serve as a good high-level guideline for expectations developers have when thinking about database transactions.
+
+> "Transactions are an abstraction layer that allows an application to pretend that certain concurrency problems and certain kinds of hardware and software faults don’t exist. A large class of errors is reduced down to a simple transaction abort, and the application just needs to try again." [Designing Data-Intensive Applications](https://dataintensive.net/), [Martin Kleppmann](https://twitter.com/martinkl)
+
+Prisma Client supports six different ways of handling transactions for three different scenarios:
+
+| Scenario | Available techniques |
+| :------------------ | :-------------------------------------------------------------------------------------------------------------- |
+| Dependent writes |
Nested writes
|
+| Independent writes |
`$transaction([])` API
Batch operations
|
+| Read, modify, write |
Idempotent operations
Optimistic concurrency control
Interactive transactions
|
+
+The technique you choose depends on your particular use case.
+
+> **Note**: For the purposes of this guide, _writing_ to a database encompasses creating, updating, and deleting data.
+
+## About transactions in Prisma
+
+Prisma provides the following options for using transactions:
+
+- [Nested writes](#nested-writes): use the Prisma Client API to process multiple operations on one or more related records inside the same transaction.
+- [Batch / bulk transactions](#batchbulk-operations): process one or more operations in bulk with `updateMany`, `deleteMany`, and `createMany`.
+- The `$transaction` API in Prisma Client:
+ - [Sequential operations](#sequential-prisma-client-operations): pass an array of Prisma Client queries to be executed sequentially inside a transaction, using `$transaction(queries: PrismaPromise[]): Promise`.
+ - [Interactive transactions](#interactive-transactions): pass a function that can contain user code including Prisma Client queries, non-Prisma code and other control flow to be executed in a transaction, using `$transaction(fn: (prisma: PrismaClient) => R, options?: object): R`
+
+## Nested writes
+
+A [nested write](relation-queries#nested-writes) lets you perform a single Prisma Client API call with multiple _operations_ that touch multiple [_related_](/orm/prisma-schema/data-model/relations) records. For example, creating a _user_ together with a _post_ or updating an _order_ together with an _invoice_. Prisma Client ensures that all operations succeed or fail as a whole.
+
+The following example demonstrates a nested write with `create`:
+
+```ts
+// Create a new user with two posts in a
+// single transaction
+const newUser: User = await prisma.user.create({
+ data: {
+ email: 'alice@prisma.io',
+ posts: {
+ create: [
+ { title: 'Join the Prisma Slack on https://slack.prisma.io' },
+ { title: 'Follow @prisma on Twitter' },
+ ],
+ },
+ },
+})
+```
+
+The following example demonstrates a nested write with `update`:
+
+```ts
+// Change the author of a post in a single transaction
+const updatedPost: Post = await prisma.post.update({
+ where: { id: 42 },
+ data: {
+ author: {
+ connect: { email: 'alice@prisma.io' },
+ },
+ },
+})
+```
+
+> Refer to the 📖 [transactions guide](/orm/prisma-client/queries/transactions#nested-writes) for more examples.
+
+## Batch/bulk operations
+
+The following bulk operations run as transactions:
+
+- `deleteMany`
+- `updateMany`
+- `createMany`
+
+> Refer to the 📖 [transactions guide](/orm/prisma-client/queries/transactions#bulk-operations) for more examples.
+
+## The `$transaction` API
+
+The `$transaction` API can be used in two ways:
+
+- [Sequential operations](#sequential-prisma-client-operations): Pass an array of Prisma Client queries to be executed sequentially inside of a transaction.
+
+ `$transaction(queries: PrismaPromise[]): Promise`
+
+- [Interactive transactions](#interactive-transactions): Pass a function that can contain user code including Prisma Client queries, non-Prisma code and other control flow to be executed in a transaction.
+
+ `$transaction(fn: (prisma: PrismaClient) => R): R`
+
+### Sequential Prisma Client operations
+
+The following query returns all posts that match the provided filter as well as a count of all posts:
+
+```ts
+const [posts, totalPosts] = await prisma.$transaction([
+ prisma.post.findMany({ where: { title: { contains: 'prisma' } } }),
+ prisma.post.count(),
+])
+```
+
+You can also use raw queries inside of a `$transaction`:
+
+
+
+
+
+```ts
+const [userList, updateUser] = await prisma.$transaction([
+ prisma.$queryRaw`SELECT 'title' FROM User`,
+ prisma.$executeRaw`UPDATE User SET name = 'Hello' WHERE id = 2;`,
+])
+```
+
+
+
+
+
+```ts
+const [findRawData, aggregateRawData, commandRawData] =
+ await prisma.$transaction([
+ prisma.user.findRaw({
+ filter: { age: { $gt: 25 } },
+ }),
+ prisma.user.aggregateRaw({
+ pipeline: [
+ { $match: { status: 'registered' } },
+ { $group: { _id: '$country', total: { $sum: 1 } } },
+ ],
+ }),
+ prisma.$runCommandRaw({
+ aggregate: 'User',
+ pipeline: [
+ { $match: { name: 'Bob' } },
+ { $project: { email: true, _id: false } },
+ ],
+ explain: false,
+ }),
+ ])
+```
+
+
+
+
+
+Instead of immediately awaiting the result of each operation when it's performed, the operation itself is stored in a variable first which later is submitted to the database with a method called `$transaction`. Prisma Client will ensure that either all three `create` operations succeed or none of them succeed.
+
+> **Note**: Operations are executed according to the order they are placed in the transaction. Using a query in a transaction does not influence the order of operations in the query itself.
+>
+> Refer to the 📖 [transactions guide](/orm/prisma-client/queries/transactions#transaction-api) for more examples.
+
+From version 4.4.0, the sequential operations transaction API has a second parameter. You can use the following optional configuration option in this parameter:
+
+- `isolationLevel`: Sets the [transaction isolation level](#transaction-isolation-level). By default this is set to the value currently configured in your database.
+
+For example:
+
+```ts
+await prisma.$transaction(
+ [
+ prisma.resource.deleteMany({ where: { name: 'name' } }),
+ prisma.resource.createMany({ data }),
+ ],
+ {
+ isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // optional, default defined by database configuration
+ }
+)
+```
+
+### Interactive transactions
+
+Sometimes you need more control over what queries execute within a transaction. Interactive transactions are meant to provide you with an escape hatch.
+
+
+
+Interactive transactions have been generally available from version 4.7.0.
+
+If you use interactive transactions in preview from version 2.29.0 to 4.6.1 (included), you need to add the `interactiveTransactions` preview feature to the generator block of your Prisma schema.
+
+
+
+To use interactive transactions, you can pass an async function into [`$transaction`](/orm/prisma-client/queries/transactions#transaction-api).
+
+The first argument passed into this async function is an instance of Prisma Client. Below, we will call this instance `tx`. Any Prisma call invoked on this `tx` instance is encapsulated into the transaction.
+
+Let's look at an example:
+
+Imagine that you are building an online banking system. One of the actions to perform is to send money from one person to another.
+
+As experienced developers, we want to make sure that during the transfer,
+
+- the amount doesn't disappear
+- the amount isn't doubled
+
+This is a great use-case for interactive transactions because we need to perform logic in-between the writes to check the balance.
+
+In the example below, Alice and Bob each have $100 in their account. If they try to send more money than they have, the transfer is rejected.
+
+Alice is expected to be able to make 1 transfer for $100 while the other transfer would be rejected. This would result in Alice having $0 and Bob having $200.
+
+```tsx
+import { PrismaClient } from '@prisma/client'
+const prisma = new PrismaClient()
+
+function transfer(from: string, to: string, amount: number) {
+ return prisma.$transaction(async (tx) => {
+ // 1. Decrement amount from the sender.
+ const sender = await tx.account.update({
+ data: {
+ balance: {
+ decrement: amount,
+ },
+ },
+ where: {
+ email: from,
+ },
+ })
+
+ // 2. Verify that the sender's balance didn't go below zero.
+ if (sender.balance < 0) {
+ throw new Error(`${from} doesn't have enough to send ${amount}`)
+ }
+
+ // 3. Increment the recipient's balance by amount
+ const recipient = await tx.account.update({
+ data: {
+ balance: {
+ increment: amount,
+ },
+ },
+ where: {
+ email: to,
+ },
+ })
+
+ return recipient
+ })
+}
+
+async function main() {
+ // This transfer is successful
+ await transfer('alice@prisma.io', 'bob@prisma.io', 100)
+ // This transfer fails because Alice doesn't have enough funds in her account
+ await transfer('alice@prisma.io', 'bob@prisma.io', 100)
+}
+
+main()
+```
+
+In the example above, both `update` queries run within a database transaction. When the application reaches the end of the function, the transaction is **committed** to the database.
+
+If your application encounters an error along the way, the async function will throw an exception and automatically **rollback** the transaction.
+
+To catch the exception, you can wrap `$transaction` in a try-catch block:
+
+```js
+try {
+ await prisma.$transaction(async (tx) => {
+ // Code running in a transaction...
+ })
+} catch (err) {
+ // Handle the rollback...
+}
+```
+
+The transaction API has a second parameter. For interactive transactions, you can use the following optional configuration options in this parameter:
+
+- `maxWait`: The maximum amount of time Prisma Client will wait to acquire a transaction from the database. The default value is 2 seconds.
+- `timeout`: The maximum amount of time the interactive transaction can run before being canceled and rolled back. The default value is 5 seconds.
+- `isolationLevel`: Sets the [transaction isolation level](#transaction-isolation-level). By default this is set to the value currently configured in your database.
+
+For example:
+
+```jsx
+await prisma.$transaction(
+ async (tx) => {
+ // Code running in a transaction...
+ },
+ {
+ maxWait: 5000, // default: 2000
+ timeout: 10000, // default: 5000
+ isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // optional, default defined by database configuration
+ }
+)
+```
+
+
+
+**Use interactive transactions with caution**. Keeping transactions
+open for a long time hurts database performance and can even cause deadlocks.
+Try to avoid performing network requests and executing slow queries inside your
+transaction functions. We recommend you get in and out as quick as possible!
+
+
+
+### Transaction isolation level
+
+
+
+This feature is not available on MongoDB, because MongoDB does not support isolation levels.
+
+
+
+You can set the transaction [isolation level](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels) for transactions.
+
+
+
+This is available in the following Prisma versions for interactive transactions from version 4.2.0, for sequential operations from version 4.4.0.
+
+In versions before 4.2.0 (for interactive transactions), or 4.4.0 (for sequential operations), you cannot configure the transaction isolation level at a Prisma level. Prisma does not explicitly set the isolation level, so the [isolation level configured in your database](#database-specific-information-on-isolation-levels) is used.
+
+
+
+#### Set the isolation level
+
+To set the transaction isolation level, use the `isolationLevel` option in the second parameter of the API.
+
+For sequential operations:
+
+```ts
+await prisma.$transaction(
+ [
+ // Prisma Client operations running in a transaction...
+ ],
+ {
+ isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // optional, default defined by database configuration
+ }
+)
+```
+
+For an interactive transaction:
+
+```jsx
+await prisma.$transaction(
+ async (prisma) => {
+ // Code running in a transaction...
+ },
+ {
+ isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // optional, default defined by database configuration
+ maxWait: 5000, // default: 2000
+ timeout: 10000, // default: 5000
+ }
+)
+```
+
+#### Supported isolation levels
+
+Prisma Client supports the following isolation levels if they are available in the underlying database:
+
+- `ReadUncommitted`
+- `ReadCommitted`
+- `RepeatableRead`
+- `Snapshot`
+- `Serializable`
+
+The isolation levels available for each database connector are as follows:
+
+| Database | `ReadUncommitted` | `ReadCommitted` | `RepeatableRead` | `Snapshot` | `Serializable` |
+| ----------- | ----------------- | --------------- | ---------------- | ---------- | -------------- |
+| PostgreSQL | ✔️ | ✔️ | ✔️ | No | ✔️ |
+| MySQL | ✔️ | ✔️ | ✔️ | No | ✔️ |
+| SQL Server | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
+| CockroachDB | No | No | No | No | ✔️ |
+| SQLite | No | No | No | No | ✔️ |
+
+By default, Prisma Client sets the isolation level to the value currently configured in your database.
+
+The isolation levels configured by default in each database are as follows:
+
+| Database | Default |
+| ----------- | ---------------- |
+| PostgreSQL | `ReadCommitted` |
+| MySQL | `RepeatableRead` |
+| SQL Server | `ReadCommitted` |
+| CockroachDB | `Serializable` |
+| SQLite | `Serializable` |
+
+#### Database-specific information on isolation levels
+
+See the following resources:
+
+- [Transaction isolation levels in PostgreSQL](https://www.postgresql.org/docs/9.3/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-ISOLATION)
+- [Transaction isolation levels in Microsoft SQL Server](https://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-ver15)
+- [Transaction isolation levels in MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html)
+
+CockroachDB and SQLite only support the `Serializable` isolation level.
+
+### Transaction timing issues
+
+
+
+- The solution in this section does not apply to MongoDB, because MongoDB does not support [isolation levels](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels).
+- The timing issues discussed in this section do not apply to CockroachDB and SQLite, because these databases only support the highest `Serializable` isolation level.
+
+
+
+When two or more transactions run concurrently in certain [isolation levels](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels), timing issues can cause write conflicts or deadlocks, such as the violation of unique constraints. For example, consider the following sequence of events where Transaction A and Transaction B both attempt to execute a `deleteMany` and a `createMany` operation:
+
+1. Transaction B: `createMany` operation creates a new set of rows.
+1. Transaction B: The application commits transaction B.
+1. Transaction A: `createMany` operation.
+1. Transaction A: The application commits transaction A. The new rows conflict with the rows that transaction B added at step 2.
+
+This conflict can occur at the isolation level `ReadCommited`, which is the default isolation level in PostgreSQL and Microsoft SQL Server. To avoid this problem, you can set a higher isolation level (`RepeatableRead` or `Serializable`). You can set the isolation level on a transaction. This overrides your database isolation level for that transaction.
+
+To avoid transaction write conflicts and deadlocks on a transaction:
+
+1. On your transaction, use the `isolationLevel` parameter to `Prisma.TransactionIsolationLevel.Serializable`.
+
+ This ensures that your application commits multiple concurrent or parallel transactions as if they were run serially. When a transaction fails due to a write conflict or deadlock, Prisma Client returns a [P2034 error](/orm/reference/error-reference#p2034).
+
+2. In your application code, add a retry around your transaction to handle any P2034 errors, as shown in this example:
+
+ ```ts
+ import { Prisma, PrismaClient } from '@prisma/client'
+
+ const prisma = new PrismaClient()
+ async function main() {
+ const MAX_RETRIES = 5
+ let retries = 0
+
+ let result
+ while (retries < MAX_RETRIES) {
+ try {
+ result = await prisma.$transaction(
+ [
+ prisma.user.deleteMany({
+ where: {
+ /** args */
+ },
+ }),
+ prisma.post.createMany({
+ data: {
+ /** args */
+ },
+ }),
+ ],
+ {
+ isolationLevel: Prisma.TransactionIsolationLevel.Serializable,
+ }
+ )
+ break
+ } catch (error) {
+ if (error.code === 'P2034') {
+ retries++
+ continue
+ }
+ throw error
+ }
+ }
+ }
+ ```
+
+## Dependent writes
+
+Writes are considered **dependent** on each other if:
+
+- Operations depend on the result of a preceding operation (for example, the database generating an ID)
+
+The most common scenario is creating a record and using the generated ID to create or update a related record. Examples include:
+
+- Creating a user and two related blog posts (a one-to-many relationship) - the author ID must be known before creating blog posts
+- Creating a team and assigning members (a many-to-many relationship) - the team ID must be known before assigning members
+
+Dependent writes must succeed together in order to maintain data consistency and prevent unexpected behavior, such as blog post without an author or a team without members.
+
+### Nested writes
+
+Prisma's solution to dependent writes is the **nested writes** feature, which is supported by `create` and `update`. The following nested write creates one user and two blog posts:
+
+```ts
+const nestedWrite = await prisma.user.create({
+ data: {
+ email: 'imani@prisma.io',
+ posts: {
+ create: [
+ { title: 'My first day at Prisma' },
+ { title: 'How to configure a unique constraint in PostgreSQL' },
+ ],
+ },
+ },
+})
+```
+
+If any operation fails, Prisma rolls back the entire transaction. Nested writes are not currently supported by top-level bulk operations like `client.user.deleteMany` and `client.user.updateMany`.
+
+#### When to use nested writes
+
+Consider using nested writes if:
+
+- ✔ You want to create two or more records related by ID at the same time (for example, create a blog post and a user)
+- ✔ You want to update and create records related by ID at the same time (for example, change a user's name and create a new blog post)
+
+:::tip
+
+If you [pre-compute your IDs, you can choose between a nested write or using the `$transaction([])` API](#scenario-pre-computed-ids-and-the-transaction-api).
+
+:::
+
+#### Scenario: Sign-up flow
+
+Consider the Slack sign-up flow, which:
+
+1. Creates a team
+2. Adds one user to that team, which automatically becomes that team's administrator
+
+This scenario can be represented by the following schema - note that users can belong to many teams, and teams can have many users (a many-to-many relationship):
+
+```prisma
+model Team {
+ id Int @id @default(autoincrement())
+ name String
+ members User[] // Many team members
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ teams Team[] // Many teams
+}
+```
+
+The most straightforward approach is to create a team, then create and attach a user to that team:
+
+```ts
+// Create a team
+const team = await prisma.team.create({
+ data: {
+ name: 'Aurora Adventures',
+ },
+})
+
+// Create a user and assign them to the team
+const user = await prisma.user.create({
+ data: {
+ email: 'alice@prisma.io',
+ team: {
+ connect: {
+ id: team.id,
+ },
+ },
+ },
+})
+```
+
+However, this code has a problem - consider the following scenario:
+
+1. Creating the team succeeds - "Aurora Adventures" is now taken
+2. Creating and connecting the user fails - the team "Aurora Adventures" exists, but has no users
+3. Going through the sign-up flow again and attempting to recreate "Aurora Adventures" fails - the team already exists
+
+Creating a team and adding a user should be one atomic operation that **succeeds or fails as a whole**.
+
+To implement atomic writes in a low-level database clients, you must wrap your inserts in `BEGIN`, `COMMIT` and `ROLLBACK` statements. Prisma Client solves the problem with [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes). The following query creates a team, creates a user, and connects the records in a single transaction:
+
+```ts
+const team = await prisma.team.create({
+ data: {
+ name: 'Aurora Adventures',
+ members: {
+ create: {
+ email: 'alice@prisma.io',
+ },
+ },
+ },
+})
+```
+
+Furthermore, if an error occurs at any point, Prisma Client rolls back the entire transaction.
+
+#### Nested writes FAQs
+
+##### Why can't I use the `$transaction([])` API to solve the same problem?
+
+The `$transaction([])` API does not allow you to pass IDs between distinct operations. In the following example, `createUserOperation.id` is not available yet:
+
+```ts highlight=12;delete
+const createUserOperation = prisma.user.create({
+ data: {
+ email: 'ebony@prisma.io',
+ },
+})
+
+const createTeamOperation = prisma.team.create({
+ data: {
+ name: 'Aurora Adventures',
+ members: {
+ connect: {
+ id: createUserOperation.id, // Not possible, ID not yet available
+ },
+ },
+ },
+})
+
+await prisma.$transaction([createUserOperation, createTeamOperation])
+```
+
+##### Nested writes support nested updates, but updates are not dependent writes - should I use the `$transaction([])` API?
+
+It is correct to say that because you know the ID of the team, you can update the team and its team members independently within a `$transaction([])`. The following example performs both operations in a `$transaction([])`:
+
+```ts
+const updateTeam = prisma.team.update({
+ where: {
+ id: 1,
+ },
+ data: {
+ name: 'Aurora Adventures Ltd',
+ },
+})
+
+const updateUsers = prisma.user.updateMany({
+ where: {
+ teams: {
+ some: {
+ id: 1,
+ },
+ },
+ name: {
+ equals: null,
+ },
+ },
+ data: {
+ name: 'Unknown User',
+ },
+})
+
+await prisma.$transaction([updateUsers, updateTeam])
+```
+
+However, you can achieve the same result with a nested write:
+
+```ts
+const updateTeam = await prisma.team.update({
+ where: {
+ id: 1,
+ },
+ data: {
+ name: 'Aurora Adventures Ltd', // Update team name
+ members: {
+ updateMany: {
+ // Update team members that do not have a name
+ data: {
+ name: 'Unknown User',
+ },
+ where: {
+ name: {
+ equals: null,
+ },
+ },
+ },
+ },
+ },
+})
+```
+
+##### Can I perform multiple nested writes - for example, create two new teams and assign users?
+
+Yes, but this is a combination of scenarios and techniques:
+
+- Creating a team and assigning users is a dependent write - use nested writes
+- Creating all teams and users at the same time is an independent write because team/user combination #1 and team/user combination #2 are unrelated writes - use the `$transaction([])` API
+
+```ts
+// Nested write
+const createOne = prisma.team.create({
+ data: {
+ name: 'Aurora Adventures',
+ members: {
+ create: {
+ email: 'alice@prisma.io',
+ },
+ },
+ },
+})
+
+// Nested write
+const createTwo = prisma.team.create({
+ data: {
+ name: 'Cool Crew',
+ members: {
+ create: {
+ email: 'elsa@prisma.io',
+ },
+ },
+ },
+})
+
+// $transaction([]) API
+await prisma.$transaction([createTwo, createOne])
+```
+
+## Independent writes
+
+Writes are considered **independent** if they do not rely on the result of a previous operation. The following groups of independent writes can occur in any order:
+
+- Updating the status field of a list of orders to "Dispatched"
+- Marking a list of emails as "Read"
+
+> **Note**: Independent writes may have to occur in a specific order if constraints are present - for example, you must delete blog posts before the blog author if the post have a mandatory `authorId` field. However, they are still considered independent writes because no operations depend on the _result_ of a previous operation, such as the database returning a generated ID.
+
+Depending on your requirements, Prisma Client has four options for handling independent writes that should succeed or fail together.
+
+### Bulk operations
+
+Bulk writes allow you to write multiple records of the same type in a single transaction - if any operation fails, Prisma rolls back the entire transaction. Prisma currently supports:
+
+- `updateMany`
+- `deleteMany`
+- `createMany`
+
+#### When to use bulk operations
+
+Consider bulk operations as a solution if:
+
+- ✔ You want to update a batch of the _same type_ of record, like a batch of emails
+
+#### Scenario: Marking emails as read
+
+You are building a service like gmail.com, and your customer wants a **"Mark as read"** feature that allows users to mark all emails as read. Each update to the status of an email is an independent write because the emails do not depend on one another - for example, the "Happy Birthday! 🍰" email from your aunt is unrelated to the promotional email from IKEA.
+
+In the following schema, a `User` can have many received emails (a one-to-many relationship):
+
+```ts
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ receivedEmails Email[] // Many emails
+}
+
+model Email {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userId], references: [id])
+ userId Int
+ subject String
+ body String
+ unread Boolean
+}
+```
+
+Based on this schema, you can use `updateMany` to mark all unread emails as read:
+
+```ts
+await prisma.email.updateMany({
+ where: {
+ user: {
+ id: 10,
+ },
+ unread: true,
+ },
+ data: {
+ unread: false,
+ },
+})
+```
+
+#### Can I use nested writes with bulk operations?
+
+No - neither `updateMany` nor `deleteMany` currently supports nested writes. For example, you cannot delete multiple teams and all of their members (a cascading delete):
+
+```ts highlight=8;delete
+await prisma.team.deleteMany({
+ where: {
+ id: {
+ in: [2, 99, 2, 11],
+ },
+ },
+ data: {
+ members: {}, // Cannot access members here
+ },
+})
+```
+
+#### Can I use bulk operations with the `$transaction([])` API?
+
+Yes - for example, you can include multiple `deleteMany` operations inside a `$transaction([])`.
+
+### `$transaction([])` API
+
+The `$transaction([])` API is generic solution to independent writes that allows you to run multiple operations as a single, atomic operation - if any operation fails, Prisma rolls back the entire transaction.
+
+Its also worth noting that operations are executed according to the order they are placed in the transaction.
+
+```ts
+await prisma.$transaction([iRunFirst, iRunSecond, iRunThird])
+```
+
+> **Note**: Using a query in a transaction does not influence the order of operations in the query itself.
+
+As Prisma Client evolves, use cases for the `$transaction([])` API will increasingly be replaced by more specialized bulk operations (such as `createMany`) and nested writes.
+
+#### When to use the `$transaction([])` API
+
+Consider the `$transaction([])` API if:
+
+- ✔ You want to update a batch that includes different types of records, such as emails and users. The records do not need to be related in any way.
+- ✔ You want to batch raw SQL queries (`$executeRaw`) - for example, for features that Prisma Client does not yet support.
+
+#### Scenario: Privacy legislation
+
+GDPR and other privacy legislation give users the right to request that an organization deletes all of their personal data. In the following example schema, a `User` can have many posts and private messages:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ posts Post[]
+ privateMessages PrivateMessage[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userId], references: [id])
+ userId Int
+ title String
+ content String
+}
+
+model PrivateMessage {
+ id Int @id @default(autoincrement())
+ user User @relation(fields: [userId], references: [id])
+ userId Int
+ message String
+}
+```
+
+If a user invokes the right to be forgotten, we must delete three records: the user record, private messages, and posts. It is critical that _all_ delete operations succeed together or not at all, which makes this a use case for a transaction. However, using a single bulk operation like `deleteMany` is not possible in this scenario because we need to delete across three models. Instead, we can use the `$transaction([])` API to run three operations together - two `deleteMany` and one `delete`:
+
+```ts
+const id = 9 // User to be deleted
+
+const deletePosts = prisma.post.deleteMany({
+ where: {
+ userId: id,
+ },
+})
+
+const deleteMessages = prisma.privateMessage.deleteMany({
+ where: {
+ userId: id,
+ },
+})
+
+const deleteUser = prisma.user.delete({
+ where: {
+ id: id,
+ },
+})
+
+await prisma.$transaction([deletePosts, deleteMessages, deleteUser]) // Operations succeed or fail together
+```
+
+#### Scenario: Pre-computed IDs and the `$transaction([])` API
+
+Dependent writes are not supported by the `$transaction([])` API - if operation A relies on the ID generated by operation B, use [nested writes](#nested-writes). However, if you _pre-computed_ IDs (for example, by generating GUIDs), your writes become independent. Consider the sign-up flow from the nested writes example:
+
+```ts
+await prisma.team.create({
+ data: {
+ name: 'Aurora Adventures',
+ members: {
+ create: {
+ email: 'alice@prisma.io',
+ },
+ },
+ },
+})
+```
+
+Instead of auto-generating IDs, change the `id` fields of `Team` and `User` to a `String` (if you do not provide a value, a UUID is generated automatically). This example uses UUIDs:
+
+```prisma highlight=2,9;delete|3,10;add
+model Team {
+ id Int @id @default(autoincrement())
+ id String @id @default(uuid())
+ name String
+ members User[]
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ id String @id @default(uuid())
+ email String @unique
+ teams Team[]
+}
+```
+
+Refactor the sign-up flow example to use the `$transaction([])` API instead of nested writes:
+
+```ts
+import { v4 } from 'uuid'
+
+const teamID = v4()
+const userID = v4()
+
+await prisma.$transaction([
+ prisma.user.create({
+ data: {
+ id: userID,
+ email: 'alice@prisma.io',
+ team: {
+ id: teamID,
+ },
+ },
+ }),
+ prisma.team.create({
+ data: {
+ id: teamID,
+ name: 'Aurora Adventures',
+ },
+ }),
+])
+```
+
+Technically you can still use nested writes with pre-computed APIs if you prefer that syntax:
+
+```ts
+import { v4 } from 'uuid'
+
+const teamID = v4()
+const userID = v4()
+
+await prisma.team.create({
+ data: {
+ id: teamID,
+ name: 'Aurora Adventures',
+ members: {
+ create: {
+ id: userID,
+ email: 'alice@prisma.io',
+ team: {
+ id: teamID,
+ },
+ },
+ },
+ },
+})
+```
+
+There's no compelling reason to switch to manually generated IDs and the `$transaction([])` API if you are already using auto-generated IDs and nested writes.
+
+## Read, modify, write
+
+In some cases you may need to perform custom logic as part of an atomic operation - also known as the [read-modify-write pattern](https://en.wikipedia.org/wiki/Read%E2%80%93modify%E2%80%93write). The following is an example of the read-modify-write pattern:
+
+- Read a value from the database
+- Run some logic to manipulate that value (for example, contacting an external API)
+- Write the value back to the database
+
+All operations should **succeed or fail together** without making unwanted changes to the database, but you do not necessarily need to use an actual database transaction. This section of the guide describes two ways to work with Prisma Client and the read-modify-write pattern:
+
+- Designing idempotent APIs
+- Optimistic concurrency control
+
+### Idempotent APIs
+
+Idempotency is the ability to run the same logic with the same parameters multiple times with the same result: the **effect on the database** is the same whether you run the logic once or one thousand times. For example:
+
+- **NOT IDEMPOTENT**: Upsert (update-or-insert) a user in the database with email address `"letoya@prisma.io"`. The `User` table **does not** enforce unique email addresses. The effect on the database is different if you run the logic once (one user created) or ten times (ten users created).
+- **IDEMPOTENT**: Upsert (update-or-insert) a user in the database with the email address `"letoya@prisma.io"`. The `User` table **does** enforce unique email addresses. The effect on the database is the same if you run the logic once (one user created) or ten times (existing user is updated with the same input).
+
+Idempotency is something you can and should actively design into your application wherever possible.
+
+#### When to design an idempotent API
+
+- ✔ You need to be able to retry the same logic without creating unwanted side-effects in the databases
+
+#### Scenario: Upgrading a Slack team
+
+You are creating an upgrade flow for Slack that allows teams to unlock paid features. Teams can choose between different plans and pay per user, per month. You use Stripe as your payment gateway, and extend your `Team` model to store a `stripeCustomerId`. Subscriptions are managed in Stripe.
+
+```prisma highlight=5;normal
+model Team {
+ id Int @id @default(autoincrement())
+ name String
+ User User[]
+ stripeCustomerId String?
+}
+```
+
+The upgrade flow looks like this:
+
+1. Count the number of users
+2. Create a subscription in Stripe that includes the number of users
+3. Associate the team with the Stripe customer ID to unlock paid features
+
+```ts
+const teamId = 9
+const planId = 'plan_id'
+
+// Count team members
+const numTeammates = await prisma.user.count({
+ where: {
+ teams: {
+ some: {
+ id: teamId,
+ },
+ },
+ },
+})
+
+// Create a customer in Stripe for plan-9454549
+const customer = await stripe.customers.create({
+ externalId: teamId,
+ plan: planId,
+ quantity: numTeammates,
+})
+
+// Update the team with the customer id to indicate that they are a customer
+// and support querying this customer in Stripe from our application code.
+await prisma.team.update({
+ data: {
+ customerId: customer.id,
+ },
+ where: {
+ id: teamId,
+ },
+})
+```
+
+This example has a problem: you can only run the logic _once_. Consider the following scenario:
+
+1. Stripe creates a new customer and subscription, and returns a customer ID
+2. Updating the team **fails** - the team is not marked as a customer in the Slack database
+3. The customer is charged by Stripe, but paid features are not unlocked in Slack because the team lacks a valid `customerId`
+4. Running the same code again either:
+
+ - Results in an error because the team (defined by `externalId`) already exists - Stripe never returns a customer ID
+ - If `externalId` is not subject to a unique constraint, Stripe creates yet another subscription (**not idempotent**)
+
+You cannot re-run this code in case of an error and you cannot change to another plan without being charged twice.
+
+The following refactor (highlighted) introduces a mechanism that checks if a subscription already exists, and either creates the description or updates the existing subscription (which will remain unchanged if the input is identical):
+
+```ts highlight=12-27;normal
+// Calculate the number of users times the cost per user
+const numTeammates = await prisma.user.count({
+ where: {
+ teams: {
+ some: {
+ id: teamId,
+ },
+ },
+ },
+})
+
+// Find customer in Stripe
+let customer = await stripe.customers.get({ externalId: teamID })
+
+if (customer) {
+ // If team already exists, update
+ customer = await stripe.customers.update({
+ externalId: teamId,
+ plan: 'plan_id',
+ quantity: numTeammates,
+ })
+} else {
+ customer = await stripe.customers.create({
+ // If team does not exist, create customer
+ externalId: teamId,
+ plan: 'plan_id',
+ quantity: numTeammates,
+ })
+}
+
+// Update the team with the customer id to indicate that they are a customer
+// and support querying this customer in Stripe from our application code.
+await prisma.team.update({
+ data: {
+ customerId: customer.id,
+ },
+ where: {
+ id: teamId,
+ },
+})
+```
+
+You can now retry the same logic multiple times with the same input without adverse effect. To further enhance this example, you can introduce a mechanism whereby the subscription is cancelled or temporarily deactivated if the update does not succeed after a set number of attempts.
+
+### Optimistic concurrency control
+
+Optimistic concurrency control (OCC) is a model for handling concurrent operations on a single entity that does not rely on 🔒 locking. Instead, we **optimistically** assume that a record will remain unchanged in between reading and writing, and use a concurrency token (a timestamp or version field) to detect changes to a record.
+
+If a ❌ conflict occurs (someone else has changed the record since you read it), you cancel the transaction. Depending on your scenario, you can then:
+
+- Re-try the transaction (book another cinema seat)
+- Throw an error (alert the user that they are about to overwrite changes made by someone else)
+
+This section describes how to build your own optimistic concurrency control. See also: Plans for [application-level optimistic concurrency control on GitHub](https://github.com/prisma/prisma/issues/4988)
+
+
+
+- If you use version 4.4.0 or earlier, you cannot use optimistic concurrency control on `update` operations, because you cannot filter on non-unique fields. The `version` field you need to use with optimistic concurrency control is a non-unique field.
+
+- Since version 5.0.0 you are able to [filter on non-unique fields in `update` operations](/orm/reference/prisma-client-reference#filter-on-non-unique-fields-with-userwhereuniqueinput) so that optimistic concurrency control is being used. The feature was also available via the Preview flag `extendedWhereUnique` from versions 4.5.0 to 4.16.2.
+
+
+
+#### When to use optimistic concurrency control
+
+- ✔ You anticipate a high number of concurrent requests (multiple people booking cinema seats)
+- ✔ You anticipate that conflicts between those concurrent requests will be rare
+
+Avoiding locks in a application with a high number of concurrent requests makes the application more resilient to load and more scalable overall. Although locking is not inherently bad, locking in a high concurrency environment can lead to unintended consequences - even if you are locking individual rows, and only for a short amount of time. For more information, see:
+
+- [Why ROWLOCK Hints Can Make Queries Slower and Blocking Worse in SQL Server](https://littlekendra.com/2016/02/04/why-rowlock-hints-can-make-queries-slower-and-blocking-worse-in-sql-server/)
+- [The High Concurrency strategy](https://www.ibm.com/developerworks/library/j-ts5/index.html)
+
+#### Scenario: Reserving a seat at the cinema
+
+You are creating a booking system for a cinema. Each movie has a set number of seats. The following schema models movies and seats:
+
+```ts
+model Seat {
+ id Int @id @default(autoincrement())
+ userId Int?
+ claimedBy User? @relation(fields: [userId], references: [id])
+ movieId Int
+ movie Movie @relation(fields: [movieId], references: [id])
+}
+
+model Movie {
+ id Int @id @default(autoincrement())
+ name String @unique
+ seats Seat[]
+}
+```
+
+The following sample code finds the first available seat and assigns that seat to a user:
+
+```ts
+const movieName = 'Hidden Figures'
+
+// Find first available seat
+const availableSeat = await prisma.seat.findFirst({
+ where: {
+ movie: {
+ name: movieName,
+ },
+ claimedBy: null,
+ },
+})
+
+// Throw an error if no seats are available
+if (!availableSeat) {
+ throw new Error(`Oh no! ${movieName} is all booked.`)
+}
+
+// Claim the seat
+await prisma.seat.update({
+ data: {
+ claimedBy: userId,
+ },
+ where: {
+ id: availableSeat.id,
+ },
+})
+```
+
+However, this code suffers from the "double-booking problem" - it is possible for two people to book the same seats:
+
+1. Seat 3A returned to Sorcha (`findFirst`)
+2. Seat 3A returned to Ellen (`findFirst`)
+3. Seat 3A claimed by Sorcha (`update`)
+4. Seat 3A claimed by Ellen (`update` - overwrites Sorcha's claim)
+
+Even though Sorcha has successfully booked the seat, the system ultimately stores Ellen's claim. To solve this problem with optimistic concurrency control, add a `version` field to the seat:
+
+```prisma highlight=7;normal
+model Seat {
+ id Int @id @default(autoincrement())
+ userId Int?
+ claimedBy User? @relation(fields: [userId], references: [id])
+ movieId Int
+ movie Movie @relation(fields: [movieId], references: [id])
+ version Int
+}
+```
+
+Next, adjust the code to check the `version` field before updating:
+
+```ts highlight=19-38;normal
+const userEmail = 'alice@prisma.io'
+const movieName = 'Hidden Figures'
+
+// Find the first available seat
+// availableSeat.version might be 0
+const availableSeat = await client.seat.findFirst({
+ where: {
+ Movie: {
+ name: movieName,
+ },
+ claimedBy: null,
+ },
+})
+
+if (!availableSeat) {
+ throw new Error(`Oh no! ${movieName} is all booked.`)
+}
+
+// Only mark the seat as claimed if the availableSeat.version
+// matches the version we're updating. Additionally, increment the
+// version when we perform this update so all other clients trying
+// to book this same seat will have an outdated version.
+const seats = await client.seat.updateMany({
+ data: {
+ claimedBy: userEmail,
+ version: {
+ increment: 1,
+ },
+ },
+ where: {
+ id: availableSeat.id,
+ version: availableSeat.version, // This version field is the key; only claim seat if in-memory version matches database version, indicating that the field has not been updated
+ },
+})
+
+if (seats.count === 0) {
+ throw new Error(`That seat is already booked! Please try again.`)
+}
+```
+
+It is now impossible for two people to book the same seat:
+
+1. Seat 3A returned to Sorcha (`version` is 0)
+2. Seat 3A returned to Ellen (`version` is 0)
+3. Seat 3A claimed by Sorcha (`version` is incremented to 1, booking succeeds)
+4. Seat 3A claimed by Ellen (in-memory `version` (0) does not match database `version` (1) - booking does not succeed)
+
+### Interactive transactions
+
+If you have an existing application, it can be a significant undertaking to refactor your application to use optimistic concurrency control. Interactive Transactions offers a useful escape hatch for cases like this.
+
+To create an interactive transaction, pass an async function into [$transaction](#transaction-api).
+
+The first argument passed into this async function is an instance of Prisma Client. Below, we will call this instance `tx`. Any Prisma call invoked on this `tx` instance is encapsulated into the transaction.
+
+In the example below, Alice and Bob each have $100 in their account. If they try to send more money than they have, the transfer is rejected.
+
+The expected outcome would be for Alice to make 1 transfer for $100 and the other transfer would be rejected. This would result in Alice having $0 and Bob having $200.
+
+```ts
+import { PrismaClient } from '@prisma/client'
+const prisma = new PrismaClient()
+
+async function transfer(from: string, to: string, amount: number) {
+ return await prisma.$transaction(async (tx) => {
+ // 1. Decrement amount from the sender.
+ const sender = await tx.account.update({
+ data: {
+ balance: {
+ decrement: amount,
+ },
+ },
+ where: {
+ email: from,
+ },
+ })
+
+ // 2. Verify that the sender's balance didn't go below zero.
+ if (sender.balance < 0) {
+ throw new Error(`${from} doesn't have enough to send ${amount}`)
+ }
+
+ // 3. Increment the recipient's balance by amount
+ const recipient = tx.account.update({
+ data: {
+ balance: {
+ increment: amount,
+ },
+ },
+ where: {
+ email: to,
+ },
+ })
+
+ return recipient
+ })
+}
+
+async function main() {
+ // This transfer is successful
+ await transfer('alice@prisma.io', 'bob@prisma.io', 100)
+ // This transfer fails because Alice doesn't have enough funds in her account
+ await transfer('alice@prisma.io', 'bob@prisma.io', 100)
+}
+
+main()
+```
+
+In the example above, both `update` queries run within a database transaction. When the application reaches the end of the function, the transaction is **committed** to the database.
+
+If the application encounters an error along the way, the async function will throw an exception and automatically **rollback** the transaction.
+
+You can learn more about interactive transactions in our [Transactions and Batch Queries documentation](/orm/prisma-client/queries/transactions#interactive-transactions).
+
+
+
+**Use interactive transactions with caution**. Keeping transactions
+open for a long time hurts database performance and can even cause deadlocks.
+Try to avoid performing network requests and executing slow queries inside your
+transaction functions. We recommend you get in and out as quick as possible!
+
+
+
+## Conclusion
+
+Prisma supports multiple ways of handling transactions, either directly through the API or by supporting your ability to introduce optimistic concurrency control and idempotency into your application. If you feel like you have use cases in your application that are not covered by any of the suggested options, please open a [GitHub issue](https://github.com/prisma/prisma/issues/new/choose) to start a discussion.
diff --git a/docs/200-orm/200-prisma-client/100-queries/060-full-text-search.mdx b/docs/200-orm/200-prisma-client/100-queries/060-full-text-search.mdx
new file mode 100644
index 0000000000..40eba5ca4f
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/060-full-text-search.mdx
@@ -0,0 +1,245 @@
+---
+title: 'Full-text search'
+metaTitle: 'Full-text search (Preview)'
+metaDescription: 'This page explains how to search for text within a field.'
+preview: true
+---
+
+
+
+Prisma Client supports full-text search for **PostgreSQL** databases in versions 2.30.0 and later, and **MySQL** databases in versions 3.8.0 and later. With full-text search enabled, you can add search functionality to your application by searching for text within a database column.
+
+
+
+## Enabling full-text search
+
+The full-text search API is currently a Preview feature. To enable this feature, carry out the following steps:
+
+1. Update the [`previewFeatures`](/orm/reference/preview-features) block in your schema to include the `fullTextSearch` preview feature flag:
+
+ ```prisma file=schema.prisma
+ generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["fullTextSearch"]
+ }
+ ```
+
+ For MySQL, you will also need to include the `fullTextIndex` preview feature flag:
+
+ ```prisma file=schema.prisma highlight=3;add
+ generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["fullTextSearch", "fullTextIndex"]
+ }
+ ```
+
+2. Generate Prisma Client:
+
+ ```terminal copy
+ npx prisma generate
+ ```
+
+After you regenerate your client, a new `search` field will be available on any `String` fields created on your models. For example, the following search will return all posts that contain the word 'cat'.
+
+```ts
+// All posts that contain the word 'cat'.
+const result = await prisma.posts.findMany({
+ where: {
+ body: {
+ search: 'cat',
+ },
+ },
+})
+```
+
+## Querying the database
+
+The `search` field uses the database's native querying capabilities under the hood. This means that the exact [query operators](https://www.postgresql.org/docs/14/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES) available are also database-specific.
+
+### PostgreSQL
+
+The following examples demonstrate the use of the PostgreSQL 'and' (`&`) and 'or' (`|`) operators:
+
+```ts
+// All posts that contain the words 'cat' or 'dog'.
+const result = await prisma.posts.findMany({
+ where: {
+ body: {
+ search: 'cat | dog',
+ },
+ },
+})
+
+// All drafts that contain the words 'cat' and 'dog'.
+const result = await prisma.posts.findMany({
+ where: {
+ status: 'Draft',
+ body: {
+ search: 'cat & dog',
+ },
+ },
+})
+```
+
+To get a sense of how the query format works, consider the following text:
+
+**"The quick brown fox jumps over the lazy dog"**
+
+Here's how the following queries would match that text:
+
+| Query | Match? | Description |
+| :-------------------------------------- | :----- | :-------------------------------------- |
+| `fox & dog` | Yes | The text contains 'fox' and 'dog' |
+| `dog & fox` | Yes | The text contains 'dog' and 'fox' |
+| `dog & cat` | No | The text contains 'dog' but not 'cat' |
+| `!cat` | Yes | 'cat' is not in the text |
+| `fox | cat` | Yes | The text contains 'fox' or 'cat' |
+| `cat | pig` | No | The text doesn't contain 'cat' or 'pig' |
+| `fox <-> dog` | Yes | 'dog' follows 'fox' in the text |
+| `dog <-> fox` | No | 'fox' doesn't follow 'dog' in the text |
+
+For the full range of supported operations, see the [PostgreSQL full text search documentation](https://www.postgresql.org/docs/12/functions-textsearch.html).
+
+### MySQL
+
+The following examples demonstrate use of the MySQL 'and' (`+`) and 'not' (`-`) operators:
+
+```ts
+// All posts that contain the words 'cat' or 'dog'.
+const result = await prisma.posts.findMany({
+ where: {
+ body: {
+ search: 'cat dog',
+ },
+ },
+})
+
+// All posts that contain the words 'cat' and not 'dog'.
+const result = await prisma.posts.findMany({
+ where: {
+ body: {
+ search: '+cat -dog',
+ },
+ },
+})
+
+// All drafts that contain the words 'cat' and 'dog'.
+const result = await prisma.posts.findMany({
+ where: {
+ status: 'Draft',
+ body: {
+ search: '+cat +dog',
+ },
+ },
+})
+```
+
+To get a sense of how the query format works, consider the following text:
+
+**"The quick brown fox jumps over the lazy dog"**
+
+Here's how the following queries would match that text:
+
+| Query | Match? | Description |
+| :------------- | :----- | :----------------------------------------------------- |
+| `+fox +dog` | Yes | The text contains 'fox' and 'dog' |
+| `+dog +fox` | Yes | The text contains 'dog' and 'fox' |
+| `+dog -cat` | Yes | The text contains 'dog' but not 'cat' |
+| `-cat` | Yes | 'cat' is not in the text |
+| `fox dog` | Yes | The text contains 'fox' or 'dog' |
+| `-cat -pig` | No | The text does not contain 'cat' or 'pig' |
+| `quic*` | Yes | The text contains a word starting with 'quic' |
+| `quick fox @2` | Yes | 'fox' starts within a 2 word distance of 'quick' |
+| `fox dog @2` | No | 'dog' does not start within a 2 word distance of 'fox' |
+| `"jumps over"` | Yes | The text contains the whole phrase 'jumps over' |
+
+MySQL also has `>`, `<` and `~` operators for altering the ranking order of search results. As an example, consider the following two records:
+
+**1. "The quick brown fox jumps over the lazy dog"**
+
+**2. "The quick brown fox jumps over the lazy cat"**
+
+| Query | Result | Description |
+| :---------------- | :----------------------- | :------------------------------------------------------------------------------------------------------ |
+| `fox ~cat` | Return 1. first, then 2. | Return all records containing 'fox', but rank records containing 'cat' lower |
+| `fox (dog)` | Return 1. first, then 2. | Return all records containing 'fox', but rank records containing 'cat' lower than rows containing 'dog' |
+
+For the full range of supported operations, see the [MySQL full text search documentation](https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html).
+
+## Sorting results by `\_relevance`
+
+
+
+Sorting by relevance is only available for PostgreSQL and MySQL.
+
+
+
+In addition to [Prisma's default `orderBy` behavior](/orm/reference/prisma-client-reference#orderby), full-text search also adds sorting by relevance to a given string or strings. As an example, if you wanted to order posts by their relevance to the term `'database'` in their title, you could use the following:
+
+```ts
+const posts = await prisma.post.findMany({
+ orderBy: {
+ _relevance: {
+ fields: ['title'],
+ search: 'database',
+ sort: 'asc'
+ },
+})
+```
+
+## Adding indexes
+
+### PostgreSQL
+
+Prisma Client does not currently support using indexes to speed up full text search. There is an existing [GitHub Issue](https://github.com/prisma/prisma/issues/8950) for this.
+
+### MySQL
+
+For MySQL, it is necessary to add indexes to any columns you search using the `@@fulltext` argument in the `schema.prisma` file. To do this, the `"fullTextIndex"` preview feature must be enabled.
+
+In the following example, one full text index is added to the `content` field of the `Blog` model, and another is added to both the `content` and `title` fields together:
+
+```prisma file=schema.prisma
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["fullTextSearch", "fullTextIndex"]
+}
+
+model Blog {
+ id Int @unique
+ content String
+ title String
+
+ @@fulltext([content])
+ @@fulltext([content, title])
+}
+```
+
+The first index allows searching the `content` field for occurrences of the word 'cat':
+
+```ts
+const result = await prisma.blogs.findMany({
+ where: {
+ content: {
+ search: 'cat',
+ },
+ },
+})
+```
+
+The second index allows searching both the `content` and `title` fields for occurrences of the word 'cat' in the `content` and 'food' in the `title`:
+
+```ts
+const result = await prisma.blogs.findMany({
+ where: {
+ content: {
+ search: 'cat',
+ },
+ title: {
+ search: 'food',
+ },
+ },
+})
+```
+
+However, if you try to search on `title` alone, the search will fail with the error "Cannot find a fulltext index to use for the search" and the message code is `P2030`, because the index requires a search on both fields.
diff --git a/docs/200-orm/200-prisma-client/100-queries/061-custom-validation.mdx b/docs/200-orm/200-prisma-client/100-queries/061-custom-validation.mdx
new file mode 100644
index 0000000000..2184204496
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/061-custom-validation.mdx
@@ -0,0 +1,190 @@
+---
+title: 'Custom validation'
+metaTitle: 'Custom validation'
+metaDescription: 'This page explains how to add custom validation to Prisma Client'
+---
+
+
+
+You can add runtime validation for your user input for Prisma Client queries in one of the following ways:
+
+- [Prisma Client extensions](/orm/prisma-client/client-extensions)
+- A custom function
+
+You can use any validation library you'd like. The Node.js ecosystem offers a number of high-quality, easy-to-use validation libraries to choose from including: [joi](https://github.com/sideway/joi), [validator.js](https://github.com/validatorjs/validator.js), [Yup](https://github.com/jquense/yup), [Zod](https://github.com/colinhacks/zod) and [Superstruct](https://github.com/ianstormtaylor/superstruct).
+
+
+
+## Input validation with Prisma Client extensions
+
+This example adds runtime validation when creating and updating values using a Zod schema to check that the data passed to Prisma Client is valid.
+
+
+
+Query extensions do not currently work for nested operations. In this example, validations are only run on the top level data object passed to methods such as `prisma.product.create()`. Validations implemented this way do not automatically run for [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes).
+
+
+
+
+
+
+
+```ts copy
+import { PrismaClient, Prisma } from '@prisma/client'
+import { z } from 'zod'
+
+/**
+ * Zod schema
+ */
+export const ProductCreateInput = z.object({
+ slug: z
+ .string()
+ .max(100)
+ .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
+ name: z.string().max(100),
+ description: z.string().max(1000),
+ price: z
+ .instanceof(Prisma.Decimal)
+ .refine((price) => price.gte('0.01') && price.lt('1000000.00')),
+}) satisfies z.Schema
+
+/**
+ * Prisma Client Extension
+ */
+const prisma = new PrismaClient().$extends({
+ query: {
+ product: {
+ create({ args, query }) {
+ args.data = ProductCreateInput.parse(args.data)
+ return query(args)
+ },
+ update({ args, query }) {
+ args.data = ProductCreateInput.partial().parse(args.data)
+ return query(args)
+ },
+ updateMany({ args, query }) {
+ args.data = ProductCreateInput.partial().parse(args.data)
+ return query(args)
+ },
+ upsert({ args, query }) {
+ args.create = ProductCreateInput.parse(args.create)
+ args.update = ProductCreateInput.partial().parse(args.update)
+ return query(args)
+ },
+ },
+ },
+})
+
+async function main() {
+ /**
+ * Example usage
+ */
+ // Valid product
+ const product = await prisma.product.create({
+ data: {
+ slug: 'example-product',
+ name: 'Example Product',
+ description: 'Lorem ipsum dolor sit amet',
+ price: new Prisma.Decimal('10.95'),
+ },
+ })
+
+ // Invalid product
+ try {
+ await prisma.product.create({
+ data: {
+ slug: 'invalid-product',
+ name: 'Invalid Product',
+ description: 'Lorem ipsum dolor sit amet',
+ price: new Prisma.Decimal('-1.00'),
+ },
+ })
+ } catch (err: any) {
+ console.log(err?.cause?.issues)
+ }
+}
+
+main()
+```
+
+
+
+
+
+```prisma copy
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model Product {
+ id String @id @default(cuid())
+ slug String
+ name String
+ description String
+ price Decimal
+ reviews Review[]
+}
+
+model Review {
+ id String @id @default(cuid())
+ body String
+ stars Int
+ product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
+ productId String
+}
+```
+
+
+
+
+
+The above example uses a Zod schema to validate and parse data provided in a query at runtime before a record is written to the database.
+
+## Input validation with a custom validation function
+
+Here's an example using [Superstruct](https://github.com/ianstormtaylor/superstruct) to validate that the data needed to signup a new user is correct:
+
+```tsx
+import { PrismaClient, Prisma, User } from '@prisma/client'
+import { assert, object, string, size, refine } from 'superstruct'
+import isEmail from 'isemail'
+
+const prisma = new PrismaClient()
+
+// Runtime validation
+const Signup = object({
+ // string and a valid email address
+ email: refine(string(), 'email', (v) => isEmail.validate(v)),
+ // password is between 7 and 30 characters long
+ password: size(string(), 7, 30),
+ // first name is between 2 and 50 characters long
+ firstName: size(string(), 2, 50),
+ // last name is between 2 and 50 characters long
+ lastName: size(string(), 2, 50),
+})
+
+type Signup = Omit
+
+// Signup function
+async function signup(input: Signup): Promise {
+ // Assert that input conforms to Signup, throwing with a helpful
+ // error message if input is invalid.
+ assert(input, Signup)
+ return prisma.user.create({
+ data: input.user,
+ })
+}
+```
+
+The example above shows how you can create a custom type-safe `signup` function that ensures the input is valid before creating a user.
+
+## Going further
+
+- Learn how you can use [Prisma Client extensions](/orm/prisma-client/client-extensions) to add input validation for your queries — [example](https://github.com/prisma/prisma-client-extensions/tree/main/input-validation).
+- Learn how you can organize your code better by moving the `signup` function into [a custom model](/orm/prisma-client/queries/custom-models).
+- There's an [outstanding feature request](https://github.com/prisma/prisma/issues/3528) to bake user validation into Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case!
diff --git a/docs/200-orm/200-prisma-client/100-queries/062-computed-fields.mdx b/docs/200-orm/200-prisma-client/100-queries/062-computed-fields.mdx
new file mode 100644
index 0000000000..8947a1a5c3
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/062-computed-fields.mdx
@@ -0,0 +1,174 @@
+---
+title: 'Computed fields'
+metaTitle: 'Computed fields'
+metaDescription: 'This page explains how to add computed fields to Prisma Client'
+---
+
+
+
+Computed fields allow you to derive a new field based on existing data. A common example is when you compute a full name from a first and last name. In your database, you may only store the first and last name, but you can define a function that computes a full name by combining the first and last name. This field is read-only and stored in your application's memory, not in your database.
+
+
+
+## Using a Prisma Client extension
+
+The following example illustrates how to create a [Prisma Client extension](/orm/prisma-client/client-extensions) that adds a `fullName` computed field at runtime to the `User` model in a Prisma schema.
+
+
+
+
+
+
+
+
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient().$extends({
+ result: {
+ user: {
+ fullName: {
+ needs: { firstName: true, lastName: true },
+ compute(user) {
+ return `${user.firstName} ${user.lastName}`
+ },
+ },
+ },
+ },
+})
+
+async function main() {
+ /**
+ * Example query containing the `fullName` computed field in the response
+ */
+ const user = await prisma.user.findFirst()
+}
+
+main()
+```
+
+
+
+
+```js no-copy
+{
+ id: 1,
+ firstName: 'Aurelia',
+ lastName: 'Schneider',
+ email: 'Jalen_Berge40@hotmail.com',
+ fullName: 'Aurelia Schneider',
+}
+```
+
+
+
+
+
+
+
+
+
+```prisma copy
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ firstName String
+ lastName String
+ posts Post[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ published Boolean @default(true)
+ content String?
+ authorId Int?
+ author User? @relation(fields: [authorId], references: [id])
+}
+```
+
+
+
+
+
+The computed fields are type-safe and can return anything from a concatenated value to complex objects or functions that can act as an instance method for your models.
+
+## Using a computation function
+
+Prisma Client does not yet natively support computed fields, but, you can define a function that accepts a generic type as an input then extend that generic to ensure it conforms to a specific structure. Finally, you can return that generic with additional computed fields. Let's see how that might look:
+
+
+
+
+
+```tsx
+// Define a type that needs a first and last name
+type FirstLastName = {
+ firstName: string
+ lastName: string
+}
+
+// Extend the T generic with the fullName attribute
+type WithFullName = T & {
+ fullName: string
+}
+
+// Take objects that satisfy FirstLastName and computes a full name
+function computeFullName(
+ user: User
+): WithFullName {
+ return {
+ ...user,
+ fullName: user.firstName + ' ' + user.lastName,
+ }
+}
+
+async function main() {
+ const user = await prisma.user.findUnique({ where: 1 })
+ const userWithFullName = computeFullName(user)
+}
+```
+
+
+
+
+
+```js
+function computeFullName(user) {
+ return {
+ ...user,
+ fullName: user.firstName + ' ' + user.lastName,
+ }
+}
+
+async function main() {
+ const user = await prisma.user.findUnique({ where: 1 })
+ const userWithFullName = computeFullName(user)
+}
+```
+
+
+
+
+
+In the TypeScript example above, a `User` generic has been defined that extends the `FirstLastName` type. This means that whatever you pass into `computeFullName` must contain `firstName` and `lastName` keys.
+
+A `WithFullName` return type has also been defined, which takes whatever `User` is and tacks on a `fullName` string attribute.
+
+With this function, any object that contains `firstName` and `lastName` keys can compute a `fullName`. Pretty neat, right?
+
+## Going further
+
+- Learn how you can use [Prisma Client extensions](/orm/prisma-client/client-extensions) to add a computed field to your schema — [example](https://github.com/prisma/prisma-client-extensions/tree/main/computed-fields).
+- Learn how you can move the `computeFullName` function into [a custom model](/orm/prisma-client/queries/custom-models).
+- There's an [outstanding feature request](https://github.com/prisma/prisma/issues/3394) to add native support to Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case!
diff --git a/docs/200-orm/200-prisma-client/100-queries/063-excluding-fields.mdx b/docs/200-orm/200-prisma-client/100-queries/063-excluding-fields.mdx
new file mode 100644
index 0000000000..aaf10c471d
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/063-excluding-fields.mdx
@@ -0,0 +1,70 @@
+---
+title: 'Excluding fields'
+metaTitle: 'Excluding fields'
+metaDescription: 'This page explains how to exclude sensitive fields from Prisma Client'
+---
+
+
+
+By default Prisma Client returns all fields from a model. You can use `select` to narrow the result set, but that can be unwieldy if you have a large model and you only want to exclude one or two fields.
+
+Prisma Client doesn't have a native way of excluding fields yet, but it's easy to create a function that you can use to exclude certain fields in a type-safe way.
+
+
+
+## Excluding the password field
+
+The following is a type-safe `exclude` function returns a user without the `password` field.
+
+
+
+
+
+```tsx
+// Exclude keys from user
+function exclude(
+ user: User,
+ keys: Key[]
+): Omit {
+ return Object.fromEntries(
+ Object.entries(user).filter(([key]) => !keys.includes(key))
+ )
+}
+
+function main() {
+ const user = await prisma.user.findUnique({ where: 1 })
+ const userWithoutPassword = exclude(user, ['password'])
+}
+```
+
+
+
+
+
+```js
+// Exclude keys from user
+function exclude(user, keys) {
+ return Object.fromEntries(
+ Object.entries(user).filter(([key]) => !keys.includes(key))
+ );
+}
+
+function main() {
+ const user = await prisma.user.findUnique({ where: 1 })
+ const userWithoutPassword = exclude(user, ['password'])
+}
+```
+
+
+
+
+
+In the TypeScript example, we've provided two generics: `User` and `Key`. The `Key` generic is defined as the keys of a `User` (e.g. `email`, `password`, `firstName`, etc.).
+
+These generics flow through the logic, returning a `User` that omits the list of `Key`s provided.
+
+## Going further
+
+- Learn how you can move the `exclude` function into [a custom model](/orm/prisma-client/queries/custom-models).
+- Instead of excluding fields, another option is to [obfuscate the field](https://github.com/prisma/prisma-client-extensions/tree/main/obfuscated-fields).
+- There's an [outstanding feature request](https://github.com/prisma/prisma/issues/5042) to add exclude support natively in Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case!
diff --git a/docs/200-orm/200-prisma-client/100-queries/064-custom-models.mdx b/docs/200-orm/200-prisma-client/100-queries/064-custom-models.mdx
new file mode 100644
index 0000000000..1edd76569e
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/064-custom-models.mdx
@@ -0,0 +1,176 @@
+---
+title: 'Custom models'
+metaTitle: 'Custom models'
+metaDescription: 'This page explains how to wrap Prisma Client in custom models'
+---
+
+
+
+As your application grows, you may find the need to group related logic together. We suggest either:
+
+- Creating static methods using a [Prisma Client extension](/orm/prisma-client/client-extensions)
+- Wrapping a model in a class
+- Extending Prisma Client model object
+
+
+
+## Static methods with Prisma Client extensions
+
+The following example demonstrates how to create a Prisma Client extension that adds a `signUp` and `findManyByDomain` methods to a User model.
+
+
+
+
+
+```tsx
+import bcrypt from 'bcryptjs'
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient().$extends({
+ model: {
+ user: {
+ async signUp(email: string, password: string) {
+ const hash = await bcrypt.hash(password, 10)
+ return prisma.user.create({
+ data: {
+ email,
+ password: {
+ create: {
+ hash,
+ },
+ },
+ },
+ })
+ },
+
+ async findManyByDomain(domain: string) {
+ return prisma.user.findMany({
+ where: { email: { endsWith: `@${domain}` } },
+ })
+ },
+ },
+ },
+})
+
+async function main() {
+ // Example usage
+ await prisma.user.signUp('user2@example2.com', 's3cret')
+
+ await prisma.user.findManyByDomain('example2.com')
+}
+```
+
+
+
+
+
+```prisma file="prisma/schema.prisma" copy
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id String @id @default(cuid())
+ email String
+ password Password?
+}
+
+model Password {
+ hash String
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+ userId String @unique
+}
+```
+
+
+
+
+
+## Wrap a model in a class
+
+In the example below, you'll see how you can wrap the `user` model in the Prisma Client within a `Users` class.
+
+```tsx
+import { PrismaClient, User } from '@prisma/client'
+
+type Signup = {
+ email: string
+ firstName: string
+ lastName: string
+}
+
+class Users {
+ constructor(private readonly prismaUser: PrismaClient['user']) {}
+
+ // Signup a new user
+ async signup(data: Signup): Promise {
+ // do some custom validation...
+ return this.prismaUser.create({ data })
+ }
+}
+
+async function main() {
+ const prisma = new PrismaClient()
+ const users = new Users(prisma.user)
+ const user = await users.signup({
+ email: 'alice@prisma.io',
+ firstName: 'Alice',
+ lastName: 'Prisma',
+ })
+}
+```
+
+With this new `Users` class, you can define custom functions like `signup`:
+
+Note that in the example above, you're only exposing a `signup` method from Prisma Client. The Prisma Client is hidden within the `Users` class, so you're no longer be able to call methods like `findMany` and `upsert`.
+
+This approach works well when you have a large application and you want to intentionally limit what your models can do.
+
+## Extending Prisma Client model object
+
+But what if you don't want to hide existing functionality but still want to group custom functions together? In this case, you can use `Object.assign` to extend Prisma Client without limiting its functionality:
+
+```tsx
+import { PrismaClient, User } from '@prisma/client'
+
+type Signup = {
+ email: string
+ firstName: string
+ lastName: string
+}
+
+function Users(prismaUser: PrismaClient['user']) {
+ return Object.assign(prismaUser, {
+ /**
+ * Signup the first user and create a new team of one. Return the User with
+ * a full name and without a password
+ */
+ async signup(data: Signup): Promise {
+ return prismaUser.create({ data })
+ },
+ })
+}
+
+async function main() {
+ const prisma = new PrismaClient()
+ const users = Users(prisma.user)
+ const user = await users.signup({
+ email: 'alice@prisma.io',
+ firstName: 'Alice',
+ lastName: 'Prisma',
+ })
+ const numUsers = await users.count()
+ console.log(user, numUsers)
+}
+```
+
+Now you can use your custom `signup` method alongside `count`, `updateMany`, `groupBy` and all of the other wonderful methods that Prisma Client provides. Best of all, it's all type-safe!
+
+## Going further
+
+We recommend using [Prisma Client extensions](/orm/prisma-client/client-extensions) to extend your models with [custom model methods](https://github.com/prisma/prisma-client-extensions/tree/main/instance-methods).
diff --git a/docs/200-orm/200-prisma-client/100-queries/070-case-sensitivity.mdx b/docs/200-orm/200-prisma-client/100-queries/070-case-sensitivity.mdx
new file mode 100644
index 0000000000..d512cc35b3
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/070-case-sensitivity.mdx
@@ -0,0 +1,187 @@
+---
+title: 'Case sensitivity'
+metaTitle: 'Case sensitivity (Reference)'
+metaDescription: 'How Prisma Client handles case sensitivity when filtering and sorting.'
+preview: false
+---
+
+
+
+Case sensitivity affects **filtering** and **sorting** of data, and is determined by your [database collation](#database-collation-and-case-sensitivity). Sorting and filtering data yields different results depending on your settings:
+
+| Action | Case sensitive | Case insensitive |
+| --------------- | -------------------------------------------- | -------------------------------------------- |
+| Sort ascending | `Apple`, `Banana`, `apple pie`, `banana pie` | `Apple`, `apple pie`, `Banana`, `banana pie` |
+| Match `"apple"` | `apple` | `Apple`, `apple` |
+
+If you use a **relational database connector**, [Prisma Client](/orm/prisma-client) respects your database collation. Options and recommendations for supporting **case-insensitive** filtering and sorting with Prisma Client depend on your [database provider](#options-for-case-insensitive-filtering).
+
+If you use the MongoDB connector, [Prisma Client](.) uses RegEx rules to enable case-insensitive filtering. The connector _does not_ use [MongoDB collation](https://docs.mongodb.com/manual/reference/collation/).
+
+> **Note**: Follow the progress of [case-insensitive sorting on GitHub](https://github.com/prisma/prisma-client-js/issues/841).
+
+
+
+## Database collation and case sensitivity
+
+
+
+In the context of Prisma Client, the following section refers to relational database connectors only.
+
+
+
+Collation specifies how data is **sorted and compared** in a database, which includes casing. Collation is something you choose when you set up a database.
+
+The following example demonstrates how to view the collation of a MySQL database:
+
+
+
+
+
+```sql no-lines
+SELECT @@character_set_database, @@collation_database;
+```
+
+
+
+
+
+```no-lines no-copy
+ +--------------------------+----------------------+
+ | @@character_set_database | @@collation_database |
+ +--------------------------+----------------------+
+ | utf8mb4 | utf8mb4_0900_ai_ci |
+ +--------------------------+----------------------+
+```
+
+
+
+
+
+The example collation, [`utf8mb4_0900_ai_ci`](https://dev.mysql.com/doc/refman/8.0/en/charset-collation-names.html), is:
+
+- Accent-insensitive (`ai`)
+- Case-insensitive (`ci`).
+
+This means that `prisMa` will match `prisma`, `PRISMA`, `priSMA`, and so on:
+
+
+
+
+
+```sql no-lines
+SELECT id, email FROM User WHERE email LIKE "%prisMa%"
+```
+
+
+
+
+
+```no-lines no-copy
+ +----+-----------------------------------+
+ | id | email |
+ +----+-----------------------------------+
+ | 61 | alice@prisma.io |
+ | 49 | birgitte@prisma.io |
+ +----+-----------------------------------+
+```
+
+
+
+
+
+The same query with Prisma Client:
+
+```ts
+const users = await prisma.user.findMany({
+ where: {
+ email: {
+ contains: 'prisMa',
+ },
+ },
+ select: {
+ id: true,
+ name: true,
+ },
+})
+```
+
+## Options for case-insensitive filtering
+
+The recommended way to support case-insensitive filtering with Prisma Client depends on your underlying provider.
+
+### PostgreSQL provider
+
+PostgreSQL uses [deterministic collation](https://www.postgresql.org/docs/current/collation.html#COLLATION-NONDETERMINISTIC) by default, which means that filtering is **case-sensitive**. To support case-insensitive filtering, use the `mode: 'insensitive'` property on a per-field basis.
+
+Use the `mode` property on a filter as shown:
+
+```ts highlight=5;normal
+const users = await prisma.user.findMany({
+ where: {
+ email: {
+ endsWith: 'prisma.io',
+ mode: 'insensitive', // Default value: default
+ },
+ },
+})
+```
+
+See also: [Filtering (Case-insensitive filtering)](filtering-and-sorting#case-insensitive-filtering)
+
+#### Caveats
+
+- You cannot use case-insensitive filtering with C collation
+- [`citext`](https://www.postgresql.org/docs/12/citext.html) columns are always case-insensitive and are not affected by `mode`
+
+#### Performance
+
+If you rely heavily on case-insensitive filtering, consider [creating indexes in the PostgreSQL database](https://www.postgresql.org/docs/current/indexes.html) to improve performance:
+
+- [Create an expression index](https://www.postgresql.org/docs/current/indexes-expressional.html) for Prisma Client queries that use `equals` or `not`
+- Use the `pg_trgm` module to [create a trigram-based index](https://www.postgresql.org/docs/12/pgtrgm.html#id-1.11.7.40.7) for Prisma Client queries that use `startsWith`, `endsWith`, `contains` (maps to`LIKE` / `ILIKE` in PostgreSQL)
+
+### MySQL provider
+
+MySQL uses **case-insensitive collation** by default. Therefore, filtering with Prisma Client and MySQL is case-insensitive by default.
+
+`mode: 'insensitive'` property is not required and therefore not available in the generated Prisma Client API.
+
+#### Caveats
+
+- You _must_ use a case-insensitive (`_ci`) collation in order to support case-insensitive filtering. Prisma Client does no support the `mode` filter property for the MySQL provider.
+
+### MongoDB provider
+
+To support case-insensitive filtering, use the `mode: 'insensitive'` property on a per-field basis:
+
+```ts highlight=5;normal
+const users = await prisma.user.findMany({
+ where: {
+ email: {
+ endsWith: 'prisma.io',
+ mode: 'insensitive', // Default value: default
+ },
+ },
+})
+```
+
+The MongoDB uses a RegEx rule for case-insensitive filtering.
+
+### SQLite provider
+
+By default, SQLite itself only [supports case-insensitive comparisons of ASCII characters](https://www.sqlite.org/faq.html#q18). Therefore, Prisma Client does not offer support for case-insensitive filtering with SQLite.
+
+To enable limited support (ASCII only) for case-insensitive filtering on a per-column basis, use `COLLATE NOCASE` when you define table columns:
+
+```sql
+CREATE TABLE mytable (
+ sample TEXT COLLATE NOCASE /* collating sequence NOCASE */
+);
+```
+
+### Microsoft SQL Server provider
+
+Microsoft SQL Server uses **case-insensitive collation** by default. Therefore, filtering with Prisma Client and Microsoft SQL Server is case-insensitive by default.
+
+`mode: 'insensitive'` property is not required and therefore not available in the generated Prisma Client API.
diff --git a/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/050-raw-queries.mdx b/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/050-raw-queries.mdx
new file mode 100644
index 0000000000..1fe7089993
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/050-raw-queries.mdx
@@ -0,0 +1,689 @@
+---
+title: 'Raw queries'
+metaTitle: 'Raw queries'
+metaDescription: 'Learn how you can send raw SQL and MongoDB queries to your database using the raw() methods from the Prisma Client API.'
+tocDepth: 3
+---
+
+
+
+Prisma Client supports the option of sending raw queries to your database. You may wish to use raw queries if:
+
+- you want to run a heavily optimized query
+- you require a feature that Prisma Client does not yet support (please [consider raising an issue](https://github.com/prisma/prisma/issues/new/choose))
+
+Raw queries are available for all relational databases Prisma supports. In addition, from version `3.9.0` raw queries are supported in MongoDB. For more details, see the relevant sections:
+
+- [Raw queries with relational databases](#raw-queries-with-relational-databases)
+- [Raw queries with MongoDB](#raw-queries-with-mongodb)
+
+
+
+## Raw queries with relational databases
+
+For relational databases, Prisma Client exposes four methods that allow you to send raw queries. You can use:
+
+- `$queryRaw` to return actual records (for example, using `SELECT`)
+- `$executeRaw` to return a count of affected rows (for example, after an `UPDATE` or `DELETE`)
+- `$queryRawUnsafe` to return actual records (for example, using `SELECT`) using a raw string. **Potential SQL injection risk**
+- `$executeRawUnsafe` to return a count of affected rows (for example, after an `UPDATE` or `DELETE`) using a raw string. **Potential SQL injection risk**
+
+### `$queryRaw`
+
+`$queryRaw` returns actual database records. For example, the following `SELECT` query returns all fields for each record in the `User` table:
+
+```ts no-lines
+const result = await prisma.$queryRaw`SELECT * FROM User`
+```
+
+The method is implemented as a [tagged template](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates), which allows you to pass a template literal where you can easily insert your [variables](#using-variables). In turn, Prisma creates prepared statements that are safe from SQL injections:
+
+```ts no-lines
+const email = 'emelie@prisma.io'
+const result = await prisma.$queryRaw`SELECT * FROM User WHERE email = ${email}`
+```
+
+You can also use the [`Prisma.sql`](#tagged-template-helpers) helper, in fact, the `$queryRaw` method will **only accept** a template string or the `Prisma.sql` helper:
+
+```ts no-lines
+const email = 'emelie@prisma.io'
+const result = await prisma.$queryRaw(
+ Prisma.sql`SELECT * FROM User WHERE email = ${email}`
+)
+```
+
+#### Considerations
+
+Be aware that:
+
+- Template variables cannot be used inside SQL string literals. For example, the following query would **not** work:
+
+ ```ts no-lines
+ const name = 'Bob'
+ await prisma.$queryRaw`SELECT 'My name is ${name}';`
+ ```
+
+ Instead, you can either pass the whole string as a variable, or use string concatenation:
+
+ ```ts no-lines
+ const name = 'My name is Bob'
+ await prisma.$queryRaw`SELECT ${name};`
+ ```
+
+ ```ts no-lines
+ const name = 'Bob'
+ await prisma.$queryRaw`SELECT 'My name is ' || ${name};`
+ ```
+
+- Template variables can only be used for data values (such as `email` in the example above). Variables cannot be used for identifiers such as column names, table names or database names, or for SQL keywords. For example, the following two queries would **not** work:
+
+ ```ts no-lines
+ const myTable = 'user'
+ await prisma.$queryRaw`SELECT * FROM ${myTable};`
+ ```
+
+ ```ts no-lines
+ const ordering = 'desc'
+ await prisma.$queryRaw`SELECT * FROM Table ORDER BY ${ordering};`
+ ```
+
+- Prisma maps any database values returned by `$queryRaw` and `$queryRawUnsafe` to their corresponding JavaScript types. [Learn more](#raw-query-type-mapping).
+
+- `$queryRaw` does not support dynamic table names in PostgreSQL databases. [Learn more](#dynamic-table-names-in-postgresql)
+
+#### Return type
+
+`$queryRaw` returns an array. Each object corresponds to a database record:
+
+```json5
+[
+ { id: 1, email: 'emelie@prisma.io', name: 'Emelie' },
+ { id: 2, email: 'yin@prisma.io', name: 'Yin' },
+]
+```
+
+You can also [type the results of `$queryRaw`](#typing-queryraw-results).
+
+#### Signature
+
+```ts no-lines
+$queryRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): PrismaPromise;
+```
+
+#### Typing `$queryRaw` results
+
+`PrismaPromise` uses a [generic type parameter `T`](https://www.typescriptlang.org/docs/handbook/generics.html). You can determine the type of `T` when you invoke the `$queryRaw` method. In the following example, `$queryRaw` returns `User[]`:
+
+```ts
+// import the generated `User` type from the `@prisma/client` module
+import { User } from '@prisma/client'
+
+const result = await prisma.$queryRaw`SELECT * FROM User`
+// result is of type: `User[]`
+```
+
+> **Note**: If you do not provide a type, `$queryRaw` defaults to `unknown`.
+
+If you are selecting **specific fields** of the model or want to include relations, refer to the documentation about [leveraging Prisma Client's generated types](/orm/prisma-client/type-safety) if you want to make sure that the results are properly typed.
+
+#### Type caveats when using raw SQL
+
+When you type the results of `$queryRaw`, the raw data might not always match the suggested TypeScript type. For example, the following Prisma model includes a `Boolean` field named `published`:
+
+```prisma highlight=3;normal
+model Post {
+ id Int @id @default(autoincrement())
+ published Boolean @default(false)
+ title String
+ content String?
+}
+```
+
+The following query returns all posts. It then prints out the value of the `published` field for each `Post`:
+
+```ts
+const result = await prisma.$queryRaw`SELECT * FROM Post`
+
+result.forEach((x) => {
+ console.log(x.published)
+})
+```
+
+> **Note**: The Prisma Client query engine standardizes the return type for all databases. **Using the raw queries does not**. If the database provider is MySQL, the values are `1` or `0`. However, if the database provider is PostgreSQL, the values are `true`, `false`, or `NULL`.
+
+> **Note**: Prisma sends JavaScript integers to PostgreSQL as `INT8`. This might conflict with your user-defined functions that accept only `INT4` as input. If you use `$queryRaw` in conjunction with a PostgreSQL database, update the input types to `INT8`, or cast your query parameters to `INT4`.
+
+#### Dynamic table names in PostgreSQL
+
+[It is not possible to interpolate table names](#considerations). This means that you cannot use dynamic table names with `$queryRaw`. Instead, you must use [`$queryRawUnsafe`](#queryrawunsafe), as follows:
+
+```ts
+let userTable = 'User'
+let result = await prisma.$queryRawUnsafe(`SELECT * FROM ${userTable}`)
+```
+
+Note that if you use `$queryRawUnsafe` in conjunction with user inputs, you risk SQL injection attacks. [Learn more](#queryrawunsafe).
+
+### `$queryRawUnsafe`
+
+The `$queryRawUnsafe` method allows you to pass a raw string (or template string) to the database.
+
+
+
+If you use this method with user inputs (in other words, `SELECT * FROM table WHERE columnx = ${userInput}`), then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion.
+
+We strongly advise that you use the `$queryRaw` query instead. For more information on SQL injection attacks, see the [OWASP SQL Injection guide](https://www.owasp.org/index.php/SQL_Injection).
+
+
+
+The following query returns all fields for each record in the `User` table:
+
+```ts
+// import the generated `User` type from the `@prisma/client` module
+import { User } from '@prisma/client'
+
+const result = await prisma.$queryRawUnsafe('SELECT * FROM User')
+```
+
+You can also run a parameterized query. The following example returns all users whose email contains the string `emelie@prisma.io`:
+
+```ts
+prisma.$queryRawUnsafe(
+ 'SELECT * FROM users WHERE email = $1',
+ 'emelie@prisma.io'
+)
+```
+
+> **Note**: Prisma sends JavaScript integers to PostgreSQL as `INT8`. This might conflict with your user-defined functions that accept only `INT4` as input. If you use a parameterized `$queryRawUnsafe` query in conjunction with a PostgreSQL database, update the input types to `INT8`, or cast your query parameters to `INT4`.
+
+#### Signature
+
+```ts no-lines
+$queryRawUnsafe(query: string, ...values: any[]): PrismaPromise;
+```
+
+#### Parameterized queries
+
+As an alternative to tagged templates, `$queryRawUnsafe` supports standard parameterized queries where each variable is represented by a symbol (`?` for mySQL, `$1`, `$2`, and so on for PostgreSQL). The following example uses a MySQL query:
+
+```ts
+const userName = 'Sarah'
+const email = 'sarah@prisma.io'
+const result = await prisma.$queryRawUnsafe(
+ 'SELECT * FROM User WHERE (name = ? OR email = ?)',
+ userName,
+ email
+)
+```
+
+> **Note**: MySQL variables are represented by `?`
+
+The following example uses a PostgreSQL query:
+
+```ts
+const userName = 'Sarah'
+const email = 'sarah@prisma.io'
+const result = await prisma.$queryRawUnsafe(
+ 'SELECT * FROM User WHERE (name = $1 OR email = $2)',
+ userName,
+ email
+)
+```
+
+> **Note**: PostgreSQL variables are represented by `$1` and `$2`
+
+As with tagged templates, Prisma Client escapes all variables.
+
+> **Note**: You cannot pass a table or column name as a variable into a parameterized query. For example, you cannot `SELECT ?` and pass in `*` or `id, name` based on some condition.
+
+##### Parameterized PostgreSQL `ILIKE` query
+
+When you use `ILIKE`, the `%` wildcard character(s) should be included in the variable itself, not the query (`string`):
+
+```ts
+const userName = 'Sarah'
+const emailFragment = 'prisma.io'
+const result = await prisma.$queryRawUnsafe(
+ 'SELECT * FROM "User" WHERE (name = $1 OR email ILIKE $2)',
+ userName,
+ `%${emailFragment}`
+)
+```
+
+> **Note**: Using `%$2` as an argument would not work
+
+### `$executeRaw`
+
+`$executeRaw` returns the _number of rows affected by a database operation_, such as `UPDATE` or `DELETE`. This function does **not** return database records. The following query updates records in the database and returns a count of the number of records that were updated:
+
+```ts
+const result: number =
+ await prisma.$executeRaw`UPDATE User SET active = true WHERE emailValidated = true`
+```
+
+The method is implemented as a [tagged template](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates), which allows you to pass a template literal where you can easily insert your [variables](#using-variables). In turn, Prisma creates prepared statements that are safe from SQL injections:
+
+```ts
+const emailValidated = true
+const active = true
+
+const result: number =
+ await prisma.$executeRaw`UPDATE User SET active = ${active} WHERE emailValidated = ${emailValidated};`
+```
+
+Be aware that:
+
+- `$executeRaw` does not support multiple queries in a single string (for example, `ALTER TABLE` and `CREATE TABLE` together).
+- Prisma Client submits prepared statements, and prepared statements only allow a subset of SQL statements. For example, `START TRANSACTION` is not permitted. You can learn more about [the syntax that MySQL allows in Prepared Statements here](https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html).
+- [`PREPARE` does not support `ALTER`](https://www.postgresql.org/docs/current/sql-prepare.html) - see the [workaround](#alter-limitation-postgresql).
+- Template variables cannot be used inside SQL string literals. For example, the following query would **not** work:
+
+ ```ts no-lines
+ const name = 'Bob'
+ await prisma.$queryRaw`UPDATE user SET greeting = 'My name is ${name}';`
+ ```
+
+ Instead, you can either pass the whole string as a variable, or use string concatenation:
+
+ ```ts no-lines
+ const name = 'My name is Bob'
+ await prisma.$queryRaw`UPDATE user SET greeting = ${name};`
+ ```
+
+ ```ts no-lines
+ const name = 'Bob'
+ await prisma.$queryRaw`UPDATE user SET greeting = 'My name is ' || ${name};`
+ ```
+
+- Template variables can only be used for data values (such as `email` in the example above). Variables cannot be used for identifiers such as column names, table names or database names, or for SQL keywords. For example, the following two queries would **not** work:
+
+ ```ts no-lines
+ const myTable = 'user'
+ await prisma.$queryRaw`UPDATE ${myTable} SET active = true;`
+ ```
+
+ ```ts no-lines
+ const ordering = 'desc'
+ await prisma.$queryRaw`UPDATE User SET active = true ORDER BY ${desc};`
+ ```
+
+#### Return type
+
+`$executeRaw` returns a `number`.
+
+#### Signature
+
+```ts
+$executeRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): PrismaPromise;
+```
+
+### `$executeRawUnsafe`
+
+The `$executeRawUnsafe` method allows you to pass a raw string (or template string) to the database. Like `$executeRaw`, it does **not** return database records, but returns the number of rows affected.
+
+> **Note**: `$executeRawUnsafe` can only run **one** query at a time. You cannot append a second query - for example, adding `DROP bobby_tables` to the end of an `ALTER`.
+
+
+
+If you use this method with user inputs (in other words, `SELECT * FROM table WHERE columnx = ${userInput}`), then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion.
+
+We strongly advise that you use the `$executeRaw` query instead. For more information on SQL injection attacks, see the [OWASP SQL Injection guide](https://www.owasp.org/index.php/SQL_Injection).
+
+
+
+The following example uses a template string to update records in the database. It then returns a count of the number of records that were updated:
+
+```ts
+const emailValidated = true
+const active = true
+
+const result = await prisma.$executeRawUnsafe(
+ `UPDATE User SET active = ${active} WHERE emailValidated = ${emailValidated}`
+)
+```
+
+The same can be written as a parameterized query:
+
+```ts
+const result = prisma.$executeRawUnsafe(
+ 'UPDATE User SET active = $1 WHERE emailValidated = $2',
+ 'yin@prisma.io',
+ true
+)
+```
+
+#### Signature
+
+```ts no-lines
+$executeRawUnsafe(query: string, ...values: any[]): PrismaPromise;
+```
+
+### Raw query type mapping
+
+Prisma maps any database values returned by `$queryRaw` and `$queryRawUnsafe`to their corresponding [JavaScript types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures). This behavior is the same as for regular Prisma query methods like `findMany`.
+
+
+
+**Feature availability:**
+
+- In v3.14.x and v3.15.x, raw query type mapping was available with the preview feature `improvedQueryRaw`. We made raw query type mapping [Generally Available](/orm/more/releases#generally-available-ga) in version 4.0.0, so you do not need to use `improvedQueryRaw` in version 4.0.0 or later.
+- Before version 4.0.0, raw query type mapping was not available for SQLite.
+
+
+
+As an example, take a raw query that selects columns with `BigInt`, `Bytes`, `Decimal` and `Date` types from a table:
+
+
+
+
+
+```ts
+const result =
+ await prisma.$queryRaw`SELECT bigint, bytes, decimal, date FROM "Table";`
+
+console.log(result)
+```
+
+
+
+
+
+```terminal no-copy wrap
+{ bigint: BigInt("123"), bytes: Buffer.from([1, 2]), decimal: Decimal("12.34"), date: Date("") }
+```
+
+
+
+
+
+In the `result` object, the database values have been mapped to the corresponding JavaScript types.
+
+The following table shows the conversion between types used in the database and the JavaScript type returned by the raw query:
+
+| Database type | JavaScript type |
+| ----------------------- | --------------- |
+| Text | `String` |
+| 32-bit integer | `Number` |
+| Floating point number | `Number` |
+| Double precision number | `Number` |
+| 64-bit integer | `BigInt` |
+| Decimal / numeric | `Decimal` |
+| Bytes | `Buffer` |
+| Json | `Object` |
+| DateTime | `Date` |
+| Date | `Date` |
+| Time | `Date` |
+| Uuid | `String` |
+| Xml | `String` |
+
+Note that the exact name for each database type will vary between databases – for example, the boolean type is known as `boolean` in PostgreSQL and `STRING` in CockroachDB. See the [Scalar types reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for full details of type names for each database.
+
+### PostgreSQL typecasting fixes
+
+Prisma resolves a number of issues with typecasting in PostgreSQL.
+
+
+
+**Feature availability:** In v3.14.x and v3.15.x, these PostgreSQL fixes were available with the preview feature `improvedQueryRaw`. We made these fixes [Generally Available](/orm/more/releases#generally-available-ga) in version 4.0.0, so you do not need to use `improvedQueryRaw` in version 4.0.0 or later.
+
+
+
+For example, the following raw query now works correctly, returning an integer result:
+
+```ts
+await prisma.$queryRaw`SELECT ${1.5}::int as int`
+
+// Before: db error: ERROR: incorrect binary data format in bind parameter 1
+// After: [{ int: 2 }]
+```
+
+A consequence of this fix is that some subtle implicit casts are now handled more strictly, so some queries that previously were allowed will now fail. As an example, take the following query using PostgreSQL's `LENGTH` function, which only accepts the `text` type as an input:
+
+```ts
+await prisma.$queryRaw`SELECT LENGTH(${42});`
+```
+
+Before version 4.0.0, Prisma silently coerces `42` to `text`. From version 4.0.0, the query returns an error:
+
+```terminal wrap
+// ERROR: function length(integer) does not exist
+// HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+```
+
+The fix in this case is to explicitly cast `42` to the `text` type:
+
+```ts
+await prisma.$queryRaw`SELECT LENGTH(${42}::text);`
+```
+
+### Transactions
+
+In 2.10.0 and later, you can use `.$executeRaw()` and `.$queryRaw()` inside a [transaction](/orm/prisma-client/queries/transactions).
+
+### Using variables
+
+`$executeRaw` and `$queryRaw` are implemented as [**tagged templates**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates). Tagged templates are the recommended way to use variables with raw SQL in the Prisma Client.
+
+The following example includes a placeholder named `${userId}`:
+
+```ts
+const userId = 42
+const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${userId};`
+```
+
+✔ Benefits of using the tagged template versions of `$queryRaw` and `$executeRaw` include:
+
+- Prisma Client escapes all variables.
+- Tagged templates are database-agnostic - you do not need to remember if variables should be written as `$1` (PostgreSQL) or `?` (MySQL).
+- [SQL Template Tag](https://github.com/blakeembrey/sql-template-tag) give you access to [useful helpers](#tagged-template-helpers).
+- Embedded, named variables are easier to read.
+
+> **Note**: You cannot pass a table or column name into a tagged template placeholder. For example, you cannot `SELECT ?` and pass in `*` or `id, name` based on some condition.
+
+#### Tagged template helpers
+
+Prisma Client specifically uses [SQL Template Tag](https://github.com/blakeembrey/sql-template-tag), which exposes a number of helpers. For example, the following query uses `join()` to pass in a list of IDs:
+
+```ts
+import { Prisma } from '@prisma/client'
+
+const ids = [1, 3, 5, 10, 20]
+const result =
+ await prisma.$queryRaw`SELECT * FROM User WHERE id IN (${Prisma.join(ids)})`
+```
+
+The following example uses the `empty` and `sql` helpers to change the query depending on whether `userName` is empty:
+
+```ts
+import { Prisma } from '@prisma/client'
+
+const userName = ''
+const result = await prisma.$queryRaw`SELECT * FROM User ${
+ userName ? Prisma.sql`WHERE name = ${userName}` : Prisma.empty // Cannot use "" or NULL here!
+}`
+```
+
+#### `ALTER` limitation (PostgreSQL)
+
+PostgreSQL [does not support using `ALTER` in a prepared statement](https://www.postgresql.org/docs/current/sql-prepare.html), which means that the following queries **will not work**:
+
+```ts
+await prisma.$executeRaw`ALTER USER prisma WITH PASSWORD "${password}"`
+await prisma.$executeRaw(
+ Prisma.sql`ALTER USER prisma WITH PASSWORD "${password}"`
+)
+```
+
+You can use the following query, but be aware that this is potentially **unsafe** as `${password}` is not escaped:
+
+```ts
+await prisma.$executeRawUnsafe('ALTER USER prisma WITH PASSWORD "$1"', password})
+```
+
+### Unsupported types
+
+[`Unsupported` types](/orm/reference/prisma-schema-reference#unsupported) need to be cast to Prisma supported types before using them in `$queryRaw` or `$queryRawUnsafe`. For example, take the following model, which has a `location` field with an `Unsupported` type:
+
+```tsx
+model Country {
+ location Unsupported("point")?
+}
+```
+
+The following query on the unsupported field will **not** work:
+
+```tsx
+await prisma.$queryRaw`SELECT location FROM Country;`
+```
+
+Instead, cast `Unsupported` fields to any supported Prisma type, **if your `Unsupported` column supports the cast**.
+
+The most common type you may want to cast your `Unsupported` column to is `String`. For example, on PostgreSQL, this would map to the `text` type:
+
+```tsx
+await prisma.$queryRaw`SELECT location::text FROM Country;`
+```
+
+The database will thus provide a `String` representation of your data which Prisma supports.
+
+For details of supported Prisma types, see the [Prisma data connector](/orm/overview) for the relevant database.
+
+### SQL injection
+
+Prisma Client mitigates the risk of SQL injection in the following ways:
+
+- Prisma Client escapes all variables when you use tagged templates and sends all queries as prepared statements.
+
+ ```ts
+ $queryRaw`...` // Tagged template
+ $executeRaw`...` // Tagged template
+ ```
+
+- `$executeRaw` can only run **one** query at a time. You cannot append a second query - for example, adding `DROP bobby_tables` to the end of an `ALTER`.
+
+If you cannot use tagged templates, you can instead use [`$queryRawUnsafe`](/orm/prisma-client/queries/raw-database-access/raw-queries#queryrawunsafe) or [`$executeRawUnsafe`](/orm/prisma-client/queries/raw-database-access/raw-queries#executerawunsafe) but **be aware that your code may be vulnerable to SQL injection**.
+
+#### ⚠️ String concatenation
+
+The following example concatenates `query` and `inputString`. Prisma Client ❌ **cannot** escape `inputString` in this example, which makes it vulnerable to SQL injection:
+
+```ts
+const inputString = '"Sarah" UNION SELECT id, title, content FROM Post' // SQL Injection
+const query = 'SELECT id, name, email FROM User WHERE name = ' + inputString
+const result = await prisma.$queryRawUnsafe(query)
+
+console.log(result)
+```
+
+## Raw queries with MongoDB
+
+For MongoDB in versions `3.9.0` and later, Prisma Client exposes three methods that allow you to send raw queries. You can use:
+
+- `$runCommandRaw` to run a command against the database
+- `.findRaw` to find zero or more documents that match the filter.
+- `.aggregateRaw` to perform aggregation operations on a collection.
+
+### `$runCommandRaw`
+
+`$runCommandRaw` runs a raw MongoDB command against the database. As input, it accepts all [MongoDB database commands](https://www.mongodb.com/docs/manual/reference/command/), with the following exceptions:
+
+- `find` (use [`findRaw`](#findraw) instead)
+- `aggregate` (use [`aggregateRaw`](#aggregateraw) instead)
+
+When you use `$runCommandRaw` to run a MongoDB database command, note the following:
+
+- The object that you pass when you invoke `$runCommandRaw` must follow the syntax of the MongoDB database command.
+- You must connect to the database with an appropriate role for the MongoDB database command.
+
+In the following example, a query inserts two records with the same `_id`. This bypasses normal document validation.
+
+```ts no-lines
+prisma.$runCommandRaw({
+ insert: 'Pets',
+ bypassDocumentValidation: true,
+ documents: [
+ {
+ _id: 1,
+ name: 'Felinecitas',
+ type: 'Cat',
+ breed: 'Russian Blue',
+ age: 12,
+ },
+ {
+ _id: 1,
+ name: 'Nao Nao',
+ type: 'Dog',
+ breed: 'Chow Chow',
+ age: 2,
+ },
+ ],
+})
+```
+
+
+
+Do not use `$runCommandRaw` for queries which contain the `"find"` or `"aggregate"` commands, because you might be unable to fetch all data. This is because MongoDB returns a [cursor](https://docs.mongodb.com/manual/tutorial/iterate-a-cursor/) that is attached to your MongoDB session, and you might not hit the same MongoDB session every time. For these queries, you should use the specialised [`findRaw`](#findraw) and [`aggregateRaw`](#aggregateraw) methods instead.
+
+
+
+#### Return type
+
+`$runCommandRaw` returns a `JSON` object whose shape depends on the inputs.
+
+#### Signature
+
+```ts no-lines
+$runCommandRaw(command: InputJsonObject): PrismaPromise;
+```
+
+### `findRaw`
+
+`.findRaw` returns actual database records. It will find zero or more documents that match the filter on the `User` collection:
+
+```ts no-lines
+const result = await prisma.user.findRaw({
+ filter: { age: { $gt: 25 } },
+ options: { projection: { _id: false } },
+})
+```
+
+#### Return type
+
+`.findRaw` returns a `JSON` object whose shape depends on the inputs.
+
+#### Signature
+
+```ts no-lines
+.findRaw(args?: {filter?: InputJsonObject, options?: InputJsonObject}): PrismaPromise;
+```
+
+- `filter`: The query predicate filter. If unspecified, then all documents in the collection will match the [predicate](https://docs.mongodb.com/manual/reference/operator/query).
+
+- `options`: Additional options to pass to the [`find` command](https://docs.mongodb.com/manual/reference/command/find/#command-fields).
+
+### `aggregateRaw`
+
+`.aggregateRaw` returns aggregated database records. It will perform aggregation operations on the `User` collection:
+
+```ts no-lines
+const result = await prisma.user.aggregateRaw({
+ pipeline: [
+ { $match: { status: 'registered' } },
+ { $group: { _id: '$country', total: { $sum: 1 } } },
+ ],
+})
+```
+
+#### Return type
+
+`.aggregateRaw` returns a `JSON` object whose shape depends on the inputs.
+
+#### Signature
+
+```ts no-lines
+.aggregateRaw(args?: {pipeline?: InputJsonObject[], options?: InputJsonObject}): PrismaPromise;
+```
+
+- `pipeline`: An array of aggregation stages to process and transform the document stream via the [aggregation pipeline](https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline).
+
+- `options`: Additional options to pass to the [`aggregate` command](https://docs.mongodb.com/manual/reference/command/aggregate/#command-fields).
diff --git a/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/100-custom-and-type-safe-queries.mdx b/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/100-custom-and-type-safe-queries.mdx
new file mode 100644
index 0000000000..053436ef72
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/100-custom-and-type-safe-queries.mdx
@@ -0,0 +1,369 @@
+---
+title: 'Custom & type-safe queries'
+metaTitle: 'Custom & type-safe queries'
+metaDescription: 'Learn how to use SafeQL and Prisma Client extensions to work around features not natively supported by Prisma, such as PostGIS.'
+---
+
+## Overview
+
+This page explains how to improve the experience of writing raw SQL in Prisma ORM. It uses [Prisma Client extensions](/orm/prisma-client/client-extensions) and [SafeQL](https://safeql.dev) to create custom, type-safe Prisma Client queries which abstract custom SQL that your app might need (using `$queryRaw`).
+
+The example will be using [PostGIS](https://postgis.net/) and PostgreSQL, but is applicable to any raw SQL queries that you might need in your application.
+
+## What is SafeQL?
+
+[SafeQL](https://safeql.dev/) allows for advanced linting and type safety within raw SQL queries. After setup, SafeQL works with Prisma `$queryRaw` and `$executeRaw` to provide type safety when raw queries are required.
+
+SafeQL runs as an [ESLint](https://eslint.org/) plugin and is configured using ESLint rules. This guide doesn't cover setting up ESLint and we will assume that you already having it running in your project.
+
+## Prerequisites
+
+To follow along, you will be expected to have:
+
+- A [PostgreSQL](https://www.postgresql.org/) database with PostGIS installed
+- Prisma set up in your project
+- ESLint set up in your project
+
+## Geographic data support in Prisma
+
+At the time of writing, Prisma does not support working with geographic data, specifically using [PostGIS](https://github.com/prisma/prisma/issues/2789).
+
+A model that has geographic data columns will be stored using the [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) data type. Fields with `Unsupported` types are present in the generated Prisma Client and will be typed as `any`. A model with a required `Unsupported` type does not expose write operations such as `create`, and `update`.
+
+Prisma supports write operations on models with a required `Unsupported` field using `$queryRaw` and `$executeRaw`. You can use Prisma Client extensions and SafeQL to improve the type-safety when working with geographical data in raw queries.
+
+## 1. Set up Prisma for use with PostGIS
+
+If you haven't already, enable the `postgresqlExtensions` Preview feature and add the `postgis` PostgreSQL extension in your Prisma schema:
+
+```prisma highlight=3,9;add
+generator client {
+ provider = "prisma-client-js"
+ previewFeatures = ["postgresqlExtensions"]
+}
+
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+ extensions = [postgis]
+}
+```
+
+
+
+If you are not using a hosted database provider, you will likely need to install the `postgis` extension. Refer to [PostGIS's docs](http://postgis.net/documentation/getting_started/#installing-postgis) to learn more about how to get started with PostGIS. If you're using Docker Compose, you can use the following snippet to set up a PostgreSQL database that has PostGIS installed:
+
+```yaml
+version: '3.6'
+services:
+ pgDB:
+ image: postgis/postgis:13-3.1-alpine
+ restart: always
+ ports:
+ - '5432:5432'
+ volumes:
+ - db_data:/var/lib/postgresql/data
+ environment:
+ POSTGRES_PASSWORD: password
+ POSTGRES_DB: geoexample
+volumes:
+ db_data:
+```
+
+
+
+Next, create a migration and execute a migration to enable the extension:
+
+```terminal
+npx prisma migrate dev --name add-postgis
+```
+
+For reference, the output of the migration file should look like the following:
+
+```sql file=migrations/TIMESTAMP_add_postgis/migration.sql
+-- CreateExtension
+CREATE EXTENSION IF NOT EXISTS "postgis";
+```
+
+You can double-check that the migration has been applied by running `prisma migrate status`.
+
+## 2. Create a new model that uses a geographic data column
+
+Add a new model with a column with a `geography` data type once the migration is applied. For this guide, we'll use a model called `PointOfInterest`.
+
+```prisma
+model PointOfInterest {
+ id Int @id @default(autoincrement())
+ name String
+ location Unsupported("geography(Point, 4326)")
+}
+```
+
+You'll notice that the `location` field uses an [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) type. This means that we lose a lot of the benefits of Prisma when working with `PointOfInterest`. We'll be using [SafeQL](https://safeql.dev/) to fix this.
+
+Like before, create and execute a migration using the `prisma migrate dev` command to create the `PointOfInterest` table in your database:
+
+```terminal
+npx prisma migrate dev --name add-poi
+```
+
+For reference, here is the output of the SQL migration file generated by Prisma Migrate:
+
+```sql file=migrations/TIMESTAMP_add_poi/migration.sql
+-- CreateTable
+CREATE TABLE "PointOfInterest" (
+ "id" SERIAL NOT NULL,
+ "name" TEXT NOT NULL,
+ "location" geography(Point, 4326) NOT NULL,
+
+ CONSTRAINT "PointOfInterest_pkey" PRIMARY KEY ("id")
+);
+```
+
+## 3. Integrate SafeQL
+
+SafeQL is easily integrated with Prisma in order to lint `$queryRaw` and `$executeRaw` Prisma operations. You can reference [SafeQL's integration guide](https://safeql.dev/compatibility/prisma.html) or follow the steps below.
+
+### 3.1. Install the `@ts-safeql/eslint-plugin` npm package
+
+```terminal
+npm install -D @ts-safeql/eslint-plugin
+```
+
+This ESLint plugin is what will allow for queries to be linted.
+
+### 3.2. Add `@ts-safeql/eslint-plugin` to your ESLint plugins
+
+Next, add `@ts-safeql/eslint-plugin` to your list of ESLint plugins. In our example we are using an `.eslintrc.js` file, but this can be applied to any way that you [configure ESLint](https://eslint.org/docs/latest/use/configure/).
+
+```js file=.eslintrc.js highlight=3
+/** @type {import('eslint').Linter.Config} */
+module.exports = {
+ "plugins": [..., "@ts-safeql/eslint-plugin"],
+ ...
+}
+```
+
+### 3.3 Add `@ts-safeql/check-sql` rules
+
+Now, setup the rules that will enable SafeQL to mark invalid SQL queries as ESLint errors.
+
+```js file=.eslintrc.js highlight=4-22;add
+/** @type {import('eslint').Linter.Config} */
+module.exports = {
+ plugins: [..., '@ts-safeql/eslint-plugin'],
+ rules: {
+ '@ts-safeql/check-sql': [
+ 'error',
+ {
+ connections: [
+ {
+ // The migrations path:
+ migrationsDir: './prisma/migrations',
+ targets: [
+ // This makes `prisma.$queryRaw` and `prisma.$executeRaw` commands linted
+ { tag: 'prisma.+($queryRaw|$executeRaw)', transform: '{type}[]' },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+}
+```
+
+> **Note**: If your `PrismaClient` instance is called something different than `prisma`, you need to adjust the value for `tag` accordingly. For example, if it is called `db`, the value for `tag` should be `'db.+($queryRaw|$executeRaw)'`.
+
+### 3.4. Connect to your database
+
+Finally, set up a `connectionUrl` for SafeQL so that it can introspect your database and retrieve the table and column names you use in your schema. SafeQL then uses this information for linting and highlighting problems in your raw SQL statements.
+
+Our example relies on the [`dotenv`](https://github.com/motdotla/dotenv) package to get the same connection string that is used by Prisma. We recommend this in order to keep your database URL out of version control.
+
+If you haven't installed `dotenv` yet, you can install it as follows:
+
+```terminal
+npm install dotenv
+```
+
+Then update your ESLint config as follows:
+
+```js file=.eslintrc.js highlight=1,6-9,16;add
+require('dotenv').config()
+
+/** @type {import('eslint').Linter.Config} */
+module.exports = {
+ plugins: ['@ts-safeql/eslint-plugin'],
+ // exclude `parserOptions` if you are not using TypeScript
+ parserOptions: {
+ project: './tsconfig.json',
+ },
+ rules: {
+ '@ts-safeql/check-sql': [
+ 'error',
+ {
+ connections: [
+ {
+ connectionUrl: process.env.DATABASE_URL,
+ // The migrations path:
+ migrationsDir: './prisma/migrations',
+ targets: [
+ // what you would like SafeQL to lint. This makes `prisma.$queryRaw` and `prisma.$executeRaw`
+ // commands linted
+ { tag: 'prisma.+($queryRaw|$executeRaw)', transform: '{type}[]' },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+}
+```
+
+SafeQL is now fully configured to help you write better raw SQL using Prisma Client.
+
+## 4. Creating extensions to make raw SQL queries type-safe
+
+In this section, we'll create two [`model`](/orm/prisma-client/client-extensions/model) extensions with custom queries to be able to work conveniently with the `PointOfInterest` model:
+
+1. A `create` query that allows us to create new `PointOfInterest` records in the database
+1. A `findClosestPoints` query that returns the `PointOfInterest` records that are closest to a given coordinate
+
+### 4.1. Adding an extension to create `PointOfInterest` records
+
+The `PointOfInterest` model in the Prisma schema uses an `Unsupported` type. As a consequence, the generated `PointOfInterest` type in Prisma Client can't be used to carry values for latitude and longitude.
+
+We will resolve this by defining two custom types that better represent our model in TypeScript:
+
+```ts
+type MyPoint = {
+ latitude: number
+ longitude: number
+}
+
+type MyPointOfInterest = {
+ name: string
+ location: MyPoint
+}
+```
+
+Next, you can add a `create` query to the `pointOfInterest` property of your Prisma Client:
+
+```ts highlight=19;normal
+const prisma = new PrismaClient().$extends({
+ model: {
+ pointOfInterest: {
+ async create(data: {
+ name: string
+ latitude: number
+ longitude: number
+ }) {
+ // Create an object using the custom types from above
+ const poi: MyPointOfInterest = {
+ name: data.name,
+ location: {
+ latitude: data.latitude,
+ longitude: data.longitude,
+ },
+ }
+
+ // Insert the object into the database
+ const point = `POINT(${poi.location.longitude} ${poi.location.latitude})`
+ await prisma.$queryRaw`
+ INSERT INTO "PointOfInterest" (name, location) VALUES (${poi.name}, ST_GeomFromText(${point}, 4326));
+ `
+
+ // Return the object
+ return poi
+ },
+ },
+ },
+})
+```
+
+Notice that the SQL in the line that's highlighted in the code snippet gets checked by SafeQL! For example, if you change the name of the table from `"PointOfInterest"` to `"PointOfInterest2"`, the following error appears:
+
+```
+error Invalid Query: relation "PointOfInterest2" does not exist @ts-safeql/check-sql
+```
+
+This also works with the column names `name` and `location`.
+
+You can now create new `PointOfInterest` records in your code as follows:
+
+```ts
+const poi = await prisma.pointOfInterest.create({
+ name: 'Berlin',
+ latitude: 52.52,
+ longitude: 13.405,
+})
+```
+
+### 4.2. Adding an extension to query for closest to `PointOfInterest` records
+
+Now let's make a Prisma Client extension in order to query this model. We will be making an extension that finds the closest points of interest to a given longitude and latitude.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ model: {
+ pointOfInterest: {
+ async create(data: {
+ name: string
+ latitude: number
+ longitude: number
+ }) {
+ // ... same code as before
+ },
+
+ async findClosestPoints(latitude: number, longitude: number) {
+ // Query for clostest points of interests
+ const result = await prisma.$queryRaw<
+ {
+ id: number | null
+ name: string | null
+ st_x: number | null
+ st_y: number | null
+ }[]
+ >`SELECT id, name, ST_X(location::geometry), ST_Y(location::geometry)
+ FROM "PointOfInterest"
+ ORDER BY ST_DistanceSphere(location::geometry, ST_MakePoint(${latitude}, ${longitude})) DESC`
+
+ // Transform to our custom type
+ const pois: MyPointOfInterest[] = result.map((data) => {
+ return {
+ name: data.name,
+ location: {
+ latitude: data.st_x || 0,
+ longitude: data.st_y || 0,
+ },
+ }
+ })
+
+ // Return data
+ return pois
+ },
+ },
+ },
+})
+```
+
+Now, you can use our Prisma Client as normal to find close points of interest to a given longitude and latitude using the custom method created on the `PointOfInterest` model.
+
+```ts
+const closestPointOfInterest = await prisma.pointOfInterest.findClosestPoints(
+ 53.5488,
+ 9.9872
+)
+```
+
+Similar to before, we again have the benefit of SafeQL to add extra type safety to our raw queries. For example, if we removed the cast to `geometry` for `location` by changing `location::geometry` to just `location`, we would get linting errors in the `ST_X`, `ST_Y` or `ST_DistanceSphere` functions respectively.
+
+```terminal
+error Invalid Query: function st_distancesphere(geography, geometry) does not exist @ts-safeql/check-sql
+```
+
+## Conclusion
+
+While you may sometimes need to drop down to raw SQL when using Prisma, you can use various techniques to make the experience of writing raw SQL queries with Prisma better.
+
+In this article, you have used SafeQL and Prisma Client extensions to create custom, type-safe Prisma Client queries to abstract PostGIS operations which are currently not natively supported in Prisma ORM.
diff --git a/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/index.mdx b/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/index.mdx
new file mode 100644
index 0000000000..ca494a4828
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/090-raw-database-access/index.mdx
@@ -0,0 +1,9 @@
+---
+title: 'Raw database access'
+metaTitle: 'Raw database access'
+metaDescription: 'Raw database access with Prisma Client.'
+---
+
+## In this section
+
+
diff --git a/docs/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx b/docs/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx
new file mode 100644
index 0000000000..5b30fa534a
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/100-query-optimization-performance.mdx
@@ -0,0 +1,343 @@
+---
+title: 'Query optimization'
+metaTitle: 'Query optimization'
+metaDescription: 'How Prisma optimizes queries under the hood'
+tocDepth: 3
+---
+
+
+
+This guide describes ways to optimize query performance, debug performance issues, and how to tackle common performance issues such as the [n+1 problem](#solving-the-n1-problem).
+
+
+
+## Debugging performance issues
+
+To help you debug and diagnose performance issues, you can [log query events at client level](/orm/prisma-client/observability-and-logging/logging#event-based-logging), which allows you to see the generated queries, parameters, and durations.
+
+Alternatively, if you are only interested in the time taken to run a query, you can implement [logging middleware](/orm/prisma-client/client-extensions/middleware/logging-middleware).
+
+## Solving the n+1 problem
+
+The n+1 problem occurs when you loop through the results of a query and perform one additional query **per result**, resulting in `n` number of queries plus the original (n+1). This is a common problem with ORMs, particularly in combination with GraphQL, because it is not always immediately obvious that your code is generating inefficient queries.
+
+### Solving n+1 in GraphQL with `findUnique` and Prisma's dataloader
+
+
+
+
+
+
+
+The Prisma Client dataloader automatically **batches** `findUnique` queries that ✔ occur in the same tick and ✔ have the same `where` and `include` parameters.
+
+Automatic batching of `findUnique` is particularly useful in a **GraphQL context**. GraphQL runs a separate resolver function for every field, which can make it difficult to optimize a nested query.
+
+For example - the following GraphQL runs the `allUsers` resolver to get all users, and the `posts` resolver **once per user** to get each user's posts (n+1):
+
+```js
+query {
+ allUsers {
+ id,
+ posts {
+ id
+ }
+ }
+}
+```
+
+The `allUsers` query uses `user.findMany(..)` to return all users:
+
+```ts highlight=7;normal
+const Query = objectType({
+ name: 'Query',
+ definition(t) {
+ t.nonNull.list.nonNull.field('allUsers', {
+ type: 'User',
+ resolve: (_parent, _args, context) => {
+ return context.prisma.user.findMany()
+ },
+ })
+ },
+})
+```
+
+This results in a single SQL query:
+
+```js
+{
+ timestamp: 2021-02-19T09:43:06.332Z,
+ query: 'SELECT `dev`.`User`.`id`, `dev`.`User`.`email`, `dev`.`User`.`name` FROM `dev`.`User` WHERE 1=1 LIMIT ? OFFSET ?',
+ params: '[-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+```
+
+However, the resolver function for `posts` is then invoked **once per user**. This results in a `findMany` query **✘ per user** rather than a single `findMany` to return all posts by all users (expand CLI output to see queries).
+
+
+
+
+```ts highlight=10-13;normal;
+const User = objectType({
+ name: 'User',
+ definition(t) {
+ t.nonNull.int('id')
+ t.string('name')
+ t.nonNull.string('email')
+ t.nonNull.list.nonNull.field('posts', {
+ type: 'Post',
+ resolve: (parent, _, context) => {
+ return context.prisma.post.findMany({
+ where: { authorId: parent.id || undefined },
+ })
+ },
+ })
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ timestamp: 2021-02-19T09:43:06.343Z,
+ query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?',
+ params: '[1,-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+{
+ timestamp: 2021-02-19T09:43:06.347Z,
+ query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?',
+ params: '[3,-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+{
+ timestamp: 2021-02-19T09:43:06.348Z,
+ query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?',
+ params: '[2,-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+{
+ timestamp: 2021-02-19T09:43:06.348Z,
+ query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?',
+ params: '[4,-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+{
+ timestamp: 2021-02-19T09:43:06.348Z,
+ query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?',
+ params: '[5,-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+// And so on
+```
+
+
+
+
+Instead, use `findUnique` in combination with [the fluent API](/orm/prisma-client/queries/relation-queries#fluent-api) (`.posts()`) as shown to return a user's posts. Even though the resolver is called once per user, the Prisma dataloader **✔ batches the `findUnique` queries**.
+
+
+
+
+```ts highlight=13-18;add|10-12;delete
+const User = objectType({
+ name: 'User',
+ definition(t) {
+ t.nonNull.int('id')
+ t.string('name')
+ t.nonNull.string('email')
+ t.nonNull.list.nonNull.field('posts', {
+ type: 'Post',
+ resolve: (parent, _, context) => {
+ return context.prisma.post.findMany({
+ where: { authorId: parent.id || undefined },
+ })
+ return context.prisma.user
+ .findUnique({
+ where: { id: parent.id || undefined },
+ })
+ .posts()
+ },
+ })
+ },
+})
+```
+
+
+
+
+```js no-copy
+{
+ timestamp: 2021-02-19T09:59:46.340Z,
+ query: 'SELECT `dev`.`User`.`id`, `dev`.`User`.`email`, `dev`.`User`.`name` FROM `dev`.`User` WHERE 1=1 LIMIT ? OFFSET ?',
+ params: '[-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+{
+ timestamp: 2021-02-19T09:59:46.350Z,
+ query: 'SELECT `dev`.`User`.`id` FROM `dev`.`User` WHERE `dev`.`User`.`id` IN (?,?,?) LIMIT ? OFFSET ?',
+ params: '[1,2,3,-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+{
+ timestamp: 2021-02-19T09:59:46.350Z,
+ query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` IN (?,?,?) LIMIT ? OFFSET ?',
+ params: '[1,2,3,-1,0]',
+ duration: 0,
+ target: 'quaint::connector::metrics'
+}
+```
+
+
+
+
+If the `posts` resolver is invoked once per user, Prisma's dataloader groups `findUnique` queries with the same parameters and selection set. Each group is optimized into a single `findMany`.
+
+#### Do I have to use the fluent API to enable batching of queries?
+
+It may seem counterintitive to use a `prisma.user.findUnique(...).posts()` query to return posts instead of `prisma.posts.findMany()` - particularly as the former results in two queries rather than one.
+
+The **only** reason you need to use the fluent API (`user.findUnique(...).posts()`) to return posts is that Prisma's dataloader batches `findUnique` queries and does not currently [batch `findMany` queries](https://github.com/prisma/prisma/issues/1477).
+
+When the dataloader batches `findMany` queries, you no longer need to use `findUnique` with the fluent API in this way.
+
+### n+1 in other contexts
+
+The n+1 problem is most commonly seen in a GraphQL context because you have to find a way to optimize a single query across multiple resolvers. However, you can just as easily introduce the n+1 problem by looping through results with `forEach` in your own code.
+
+The following code results in n+1 queries - one `findMany` to get all users, and one `findMany` **per user** to get each user's posts:
+
+
+
+
+```ts
+// One query to get all users
+const users = await prisma.user.findMany({})
+
+// One query PER USER to get all posts
+users.forEach(async (usr) => {
+ const posts = await prisma.post.findMany({
+ where: {
+ authorId: usr.id,
+ },
+ })
+
+ // Do something with each users' posts
+})
+```
+
+
+
+
+```sql no-copy
+SELECT "public"."User"."id", "public"."User"."email", "public"."User"."name" FROM "public"."User" WHERE 1=1 OFFSET $1
+SELECT "public"."Post"."id", "public"."Post"."title" FROM "public"."Post" WHERE "public"."Post"."authorId" = $1 OFFSET $2
+SELECT "public"."Post"."id", "public"."Post"."title" FROM "public"."Post" WHERE "public"."Post"."authorId" = $1 OFFSET $2
+SELECT "public"."Post"."id", "public"."Post"."title" FROM "public"."Post" WHERE "public"."Post"."authorId" = $1 OFFSET $2
+SELECT "public"."Post"."id", "public"."Post"."title" FROM "public"."Post" WHERE "public"."Post"."authorId" = $1 OFFSET $2
+/* ..and so on .. */
+```
+
+
+
+
+This is not an efficient way to query. Instead, you can:
+
+- Use nested reads ([`include`](/orm/reference/prisma-client-reference#include) ) to return users and related posts
+- Use the [`in`](/orm/reference/prisma-client-reference#in) filter
+
+#### Solving n+1 with `include`
+
+You can use `include` to return each user's posts. This only results in **two** SQL queries - one to get users, and one to get posts. This is known as a [nested read](/orm/prisma-client/queries/relation-queries#nested-reads).
+
+
+
+
+```ts
+const usersWithPosts = await prisma.user.findMany({
+ include: {
+ posts: true,
+ },
+})
+```
+
+
+
+
+```sql no-copy
+SELECT "public"."User"."id", "public"."User"."email", "public"."User"."name" FROM "public"."User" WHERE 1=1 OFFSET $1
+SELECT "public"."Post"."id", "public"."Post"."title", "public"."Post"."authorId" FROM "public"."Post" WHERE "public"."Post"."authorId" IN ($1,$2,$3,$4) OFFSET $5
+```
+
+
+
+
+#### Solving n+1 with `in`
+
+If you have a list of user IDs, you can use the `in` filter to return all posts where the `authorId` is `in` that list of IDs:
+
+
+
+
+```ts
+const users = await prisma.user.findMany({})
+
+const userIds = users.map((x) => x.id)
+
+const posts = await prisma.post.findMany({
+ where: {
+ authorId: {
+ in: userIds,
+ },
+ },
+})
+```
+
+
+
+
+```sql no-copy
+SELECT "public"."User"."id", "public"."User"."email", "public"."User"."name" FROM "public"."User" WHERE 1=1 OFFSET $1
+SELECT "public"."Post"."id", "public"."Post"."createdAt", "public"."Post"."updatedAt", "public"."Post"."title", "public"."Post"."content", "public"."Post"."published", "public"."Post"."authorId" FROM "public"."Post" WHERE "public"."Post"."authorId" IN ($1,$2,$3,$4) OFFSET $5
+```
+
+
+
+
+## Using bulk queries
+
+It is generally more performant to read and write large amounts of data in bulk - for example, inserting 50,000 records in batches of 1000 rather than as 50,000 separate inserts. Prisma Client supports the following bulk queries:
+
+- [`createMany`](/orm/reference/prisma-client-reference#createmany)
+- [`deleteMany`](/orm/reference/prisma-client-reference#deletemany)
+- [`updateMany`](/orm/reference/prisma-client-reference#updatemany)
+- [`findMany`](/orm/reference/prisma-client-reference#findmany)
+
+## Using `select` to limit number of columns returned
+
+Using `select` to limit the number of columns that are returned is **unlikely to have an effect on performance** unless you have identified this as a performance bottleneck through testing. For example, reading all fields may negatively affect performance if you have:
+
+- Tables with a large number of columns
+- Large columns that are stored in a separate location on disk rather than a row, which results in an additional disk read
+
+Furthermore, if you have a mature product with well established query patterns and finely tuned indexes, selecting a specific subset of fields may be beneficial as it avoids reading data from disk. However, in most cases, this level of performance tuning is only necessary at a certain scale.
+
+
diff --git a/docs/200-orm/200-prisma-client/100-queries/index.mdx b/docs/200-orm/200-prisma-client/100-queries/index.mdx
new file mode 100644
index 0000000000..5f98e3590e
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/100-queries/index.mdx
@@ -0,0 +1,9 @@
+---
+title: 'Queries'
+metaTitle: 'Prisma Client Queries'
+metaDescription: 'Learn about the database queries you can send with Prisma Client.'
+---
+
+## In this section
+
+
diff --git a/docs/200-orm/200-prisma-client/200-special-fields-and-types/057-composite-types.mdx b/docs/200-orm/200-prisma-client/200-special-fields-and-types/057-composite-types.mdx
new file mode 100644
index 0000000000..3f1891dc09
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/200-special-fields-and-types/057-composite-types.mdx
@@ -0,0 +1,798 @@
+---
+title: 'Composite types'
+metaTitle: 'Composite types'
+metaDescription: 'Composite types'
+tocDepth: 3
+---
+
+
+
+
+
+Composite types are only available with MongoDB.
+
+
+
+[Composite types](/orm/prisma-schema/data-model/models#defining-composite-types), known as [embedded documents](https://docs.mongodb.com/manual/core/data-model-design/#std-label-data-modeling-embedding) in MongoDB, allow you to embed records within other records.
+
+We made composite types [Generally Available](/orm/more/releases#generally-available-ga) in v3.12.0. They were previously available in [Preview](/orm/reference/preview-features) from v3.10.0.
+
+This page explains how to:
+
+- [find](#finding-records-that-contain-composite-types-with-find-and-findmany) records that contain composite types using `findFirst` and `findMany`
+- [create](#creating-records-with-composite-types-using-create-and-createmany) new records with composite types using `create` and `createMany`
+- [update](#changing-composite-types-within-update-and-updatemany) composite types within existing records using `update` and `updateMany`
+- [delete](#deleting-records-that-contain-composite-types-with-delete-and-deletemany) records with composite types using `delete` and `deleteMany`
+
+
+
+## Example schema
+
+We’ll use this schema for the examples that follow:
+
+```prisma file=schema.prisma
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+model Product {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String @unique
+ price Float
+ colors Color[]
+ sizes Size[]
+ photos Photo[]
+ orders Order[]
+}
+
+model Order {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ product Product @relation(fields: [productId], references: [id])
+ color Color
+ size Size
+ shippingAddress Address
+ billingAddress Address?
+ productId String @db.ObjectId
+}
+
+enum Color {
+ Red
+ Green
+ Blue
+}
+
+enum Size {
+ Small
+ Medium
+ Large
+ XLarge
+}
+
+type Photo {
+ height Int @default(200)
+ width Int @default(100)
+ url String
+}
+
+type Address {
+ street String
+ city String
+ zip String
+}
+```
+
+In this schema, the `Product` model has a `Photo[]` composite type, and the `Order` model has two composite `Address` types. The `shippingAddress` is required, but the `billingAddress` is optional.
+
+## Considerations when using composite types
+
+There are currently some limitations when using composite types in Prisma Client:
+
+- [`findUnique`](/orm/reference/prisma-client-reference#findunique) can't filter on composite types
+- [`aggregate`](/orm/prisma-client/queries/aggregation-grouping-summarizing#aggregate), [`groupBy`](/orm/prisma-client/queries/aggregation-grouping-summarizing#group-by), [`count`](/orm/prisma-client/queries/aggregation-grouping-summarizing#count) don’t support composite operations
+
+## Default values for required fields on composite types
+
+From version 4.0.0, if you carry out a database read on a composite type when all of the following conditions are true, then Prisma Client inserts the default value into the result.
+
+Conditions:
+
+- A field on the composite type is [required](/orm/prisma-schema/data-model/models#optional-and-mandatory-fields), and
+- this field has a [default value](/orm/prisma-schema/data-model/models#defining-a-default-value), and
+- this field is not present in the returned document or documents.
+
+Note:
+
+- This is the same behavior as with [model fields](/orm/reference/prisma-schema-reference#model-field-scalar-types).
+- On read operations, Prisma Client inserts the default value into the result, but does not insert the default value into the database.
+
+In our example schema, suppose that you add a required field to `photo`. This field, `bitDepth`, has a default value:
+
+```prisma file=schema.prisma highlight=4;add
+...
+type Photo {
+ ...
+ bitDepth Int @default(8)
+}
+
+...
+```
+
+Suppose that you then run `npx prisma migrate deploy` to [deploy your database changes](/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate) and regenerate your Prisma Client with `npx prisma generate`. Then, you run the following application code:
+
+```ts
+console.dir(await prisma.product.findMany({}), { depth: Infinity })
+```
+
+The `bitDepth` field has no content because you have only just added this field, so the query returns the default value of `8`.
+
+** Earlier versions **
+
+Before version 4.0.0, Prisma threw a P2032 error as follows:
+
+```
+Error converting field "bitDepth" of expected non-nullable
+type "int", found incompatible value of "null".
+```
+
+## Finding records that contain composite types with `find` and `findMany`
+
+Records can be filtered by a composite type within the `where` operation.
+
+The following section describes the operations available for filtering by a single type or multiple types, and gives examples of each.
+
+### Filtering for one composite type
+
+Use the `is`, `equals`, `isNot` and `isSet` operations to change a single composite type:
+
+- `is`: Filter results by matching composite types. Requires one or more fields to be present _(e.g. Filter orders by the street name on the shipping address)_
+- `equals`: Filter results by matching composite types. Requires all fields to be present. _(e.g. Filter orders by the full shipping address)_
+- `isNot`: Filter results by non-matching composite types
+- `isSet` : Filter optional fields to include only results that have been set (either set to a value, or explicitly set to `null`). Setting this filter to `true` will exclude `undefined` results that are not set at all.
+
+For example, use `is` to filter for orders with a street name of `'555 Candy Cane Lane'`:
+
+```ts
+const orders = await prisma.order.findMany({
+ where: {
+ shippingAddress: {
+ is: {
+ street: '555 Candy Cane Lane',
+ },
+ },
+ },
+})
+```
+
+Use `equals` to filter for orders which match on all fields in the shipping address:
+
+```ts
+const orders = await prisma.order.findMany({
+ where: {
+ shippingAddress: {
+ equals: {
+ street: '555 Candy Cane Lane',
+ city: 'Wonderland',
+ zip: '52337',
+ },
+ },
+ },
+})
+```
+
+You can also use a shorthand notation for this query, where you leave out the `equals`:
+
+```ts
+const orders = await prisma.order.findMany({
+ where: {
+ shippingAddress: {
+ street: '555 Candy Cane Lane',
+ city: 'Wonderland',
+ zip: '52337',
+ },
+ },
+})
+```
+
+Use `isNot` to filter for orders that do not have a `zip` code of `'52337'`:
+
+```ts
+const orders = await prisma.order.findMany({
+ where: {
+ shippingAddress: {
+ isNot: {
+ zip: '52337',
+ },
+ },
+ },
+})
+```
+
+Use `isSet` to filter for orders where the optional `billingAddress` has been set (either to a value or to `null`):
+
+```ts
+const orders = await prisma.order.findMany({
+ where: {
+ billingAddress: {
+ isSet: true,
+ },
+ },
+})
+```
+
+### Filtering for many composite types
+
+Use the `equals`, `isEmpty`, `every`, `some` and `none` operations to filter for multiple composite types:
+
+- `equals`: Checks exact equality of the list
+- `isEmpty`: Checks if the list is empty
+- `every`: Every item in the list must match the condition
+- `some`: One or more of the items in the list must match the condition
+- `none`: None of the items in the list can match the condition
+- `isSet` : Filter optional fields to include only results that have been set (either set to a value, or explicitly set to `null`). Setting this filter to `true` will exclude `undefined` results that are not set at all.
+
+For example, you can use `equals` to find products with a specific list of photos (all `url`, `height` and `width` fields must match):
+
+```ts
+const product = prisma.product.findMany({
+ where: {
+ photos: {
+ equals: [
+ {
+ url: '1.jpg',
+ height: 200,
+ width: 100,
+ },
+ {
+ url: '2.jpg',
+ height: 200,
+ width: 100,
+ },
+ ],
+ },
+ },
+})
+```
+
+You can also use a shorthand notation for this query, where you leave out the `equals` and specify just the fields that you want to filter for:
+
+```ts
+const product = prisma.product.findMany({
+ where: {
+ photos: [
+ {
+ url: '1.jpg',
+ height: 200,
+ width: 100,
+ },
+ {
+ url: '2.jpg',
+ height: 200,
+ width: 100,
+ },
+ ],
+ },
+})
+```
+
+Use `isEmpty` to filter for products with no photos:
+
+```ts
+const product = prisma.product.findMany({
+ where: {
+ photos: {
+ isEmpty: true,
+ },
+ },
+})
+```
+
+Use `some` to filter for products where one or more photos has a `url` of `"2.jpg"`:
+
+```ts
+const product = prisma.product.findFirst({
+ where: {
+ photos: {
+ some: {
+ url: '2.jpg',
+ },
+ },
+ },
+})
+```
+
+Use `none` to filter for products where no photos have a `url` of `"2.jpg"`:
+
+```ts
+const product = prisma.product.findFirst({
+ where: {
+ photos: {
+ none: {
+ url: '2.jpg',
+ },
+ },
+ },
+})
+```
+
+## Creating records with composite types using `create` and `createMany`
+
+
+
+When you create a record with a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types).
+
+
+
+Composite types can be created within a `create` or `createMany` method using the `set` operation. For example, you can use `set` within `create` to create an `Address` composite type inside an `Order`:
+
+```ts
+const order = await prisma.order.create({
+ data: {
+ // Normal relation
+ product: { connect: { id: 'some-object-id' } },
+ color: 'Red',
+ size: 'Large',
+ // Composite type
+ shippingAddress: {
+ set: {
+ street: '1084 Candycane Lane',
+ city: 'Silverlake',
+ zip: '84323',
+ },
+ },
+ },
+})
+```
+
+You can also use a shorthand notation where you leave out the `set` and specify just the fields that you want to create:
+
+```ts
+const order = await prisma.order.create({
+ data: {
+ // Normal relation
+ product: { connect: { id: 'some-object-id' } },
+ color: 'Red',
+ size: 'Large',
+ // Composite type
+ shippingAddress: {
+ street: '1084 Candycane Lane',
+ city: 'Silverlake',
+ zip: '84323',
+ },
+ },
+})
+```
+
+For an optional type, like the `billingAddress`, you can also set the value to `null`:
+
+```ts
+const order = await prisma.order.create({
+ data: {
+ // Normal relation
+ product: { connect: { id: 'some-object-id' } },
+ color: 'Red',
+ size: 'Large',
+ // Composite type
+ shippingAddress: {
+ street: '1084 Candycane Lane',
+ city: 'Silverlake',
+ zip: '84323',
+ },
+ // Embedded optional type, set to null
+ billingAddress: {
+ set: null,
+ },
+ },
+})
+```
+
+To model the case where an `product` contains a list of multiple `photos`, you can `set` multiple composite types at once:
+
+```ts
+const product = await prisma.product.create({
+ data: {
+ name: 'Forest Runners',
+ price: 59.99,
+ colors: ['Red', 'Green'],
+ sizes: ['Small', 'Medium', 'Large'],
+ // New composite type
+ photos: {
+ set: [
+ { height: 100, width: 200, url: '1.jpg' },
+ { height: 100, width: 200, url: '2.jpg' },
+ ],
+ },
+ },
+})
+```
+
+You can also use a shorthand notation where you leave out the `set` and specify just the fields that you want to create:
+
+```ts
+const product = await prisma.product.create({
+ data: {
+ name: 'Forest Runners',
+ price: 59.99,
+ // Scalar lists that we already support
+ colors: ['Red', 'Green'],
+ sizes: ['Small', 'Medium', 'Large'],
+ // New composite type
+ photos: [
+ { height: 100, width: 200, url: '1.jpg' },
+ { height: 100, width: 200, url: '2.jpg' },
+ ],
+ },
+})
+```
+
+These operations also work within the `createMany` method. For example, you can create multiple `product`s which each contain a list of `photos`:
+
+```ts
+const product = await prisma.product.createMany({
+ data: [
+ {
+ name: 'Forest Runners',
+ price: 59.99,
+ colors: ['Red', 'Green'],
+ sizes: ['Small', 'Medium', 'Large'],
+ photos: [
+ { height: 100, width: 200, url: '1.jpg' },
+ { height: 100, width: 200, url: '2.jpg' },
+ ],
+ },
+ {
+ name: 'Alpine Blazers',
+ price: 85.99,
+ colors: ['Blue', 'Red'],
+ sizes: ['Large', 'XLarge'],
+ photos: [
+ { height: 100, width: 200, url: '1.jpg' },
+ { height: 150, width: 200, url: '4.jpg' },
+ { height: 200, width: 200, url: '5.jpg' },
+ ],
+ },
+ ],
+})
+```
+
+## Changing composite types within `update` and `updateMany`
+
+
+
+When you update a record with a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types).
+
+
+
+Composite types can be set, updated or removed within an `update` or `updateMany` method. The following section describes the operations available for updating a single type or multiple types at once, and gives examples of each.
+
+### Changing a single composite type
+
+Use the `set`, `unset` `update` and `upsert` operations to change a single composite type:
+
+- Use `set` to set a composite type, overriding any existing value
+- Use `unset` to unset a composite type. Unlike `set: null`, `unset` removes the field entirely
+- Use `update` to update a composite type
+- Use `upsert` to `update` an existing composite type if it exists, and otherwise `set` the composite type
+
+For example, use `update` to update a required `shippingAddress` with an `Address` composite type inside an `Order`:
+
+```ts
+const order = await prisma.order.update({
+ where: {
+ id: 'some-object-id',
+ },
+ data: {
+ shippingAddress: {
+ // Update just the zip field
+ update: {
+ zip: '41232',
+ },
+ },
+ },
+})
+```
+
+For an optional embedded type, like the `billingAddress`, use `upsert` to create a new record if it does not exist, and update the record if it does:
+
+```ts
+const order = await prisma.order.update({
+ where: {
+ id: 'some-object-id',
+ },
+ data: {
+ billingAddress: {
+ // Create the address if it doesn't exist,
+ // otherwise update it
+ upsert: {
+ set: {
+ street: '1084 Candycane Lane',
+ city: 'Silverlake',
+ zip: '84323',
+ },
+ update: {
+ zip: '84323',
+ },
+ },
+ },
+ },
+})
+```
+
+You can also use the `unset` operation to remove an optional embedded type. The following example uses `unset` to remove the `billingAddress` from an `Order`:
+
+```ts
+const order = await prisma.order.update({
+ where: {
+ id: 'some-object-id',
+ },
+ data: {
+ billingAddress: {
+ // Unset the billing address
+ // Removes "billingAddress" field from order
+ unset: true,
+ },
+ },
+})
+```
+
+You can use [filters](/orm/prisma-client/special-fields-and-types/composite-types#finding-records-that-contain-composite-types-with-find-and-findmany) within `updateMany` to update all records that match a composite type. The following example uses the `is` filter to match the street name from a shipping address on a list of orders:
+
+```ts
+const orders = await prisma.order.updateMany({
+ where: {
+ shippingAddress: {
+ is: {
+ street: '555 Candy Cane Lane',
+ },
+ },
+ },
+ data: {
+ shippingAddress: {
+ update: {
+ street: '111 Candy Cane Drive',
+ },
+ },
+ },
+})
+```
+
+### Changing multiple composite types
+
+Use the `set`, `push`, `updateMany` and `deleteMany` operations to change a list of composite types:
+
+- `set`: Set an embedded list of composite types, overriding any existing list
+- `push`: Push values to the end of an embedded list of composite types
+- `updateMany`: Update many composite types at once
+- `deleteMany`: Delete many composite types at once
+
+For example, use `push` to add a new photo to the `photos` list:
+
+```ts
+const product = prisma.product.update({
+ where: {
+ id: '62de6d328a65d8fffdae2c18',
+ },
+ data: {
+ photos: {
+ // Push a photo to the end of the photos list
+ push: [{ height: 100, width: 200, url: '1.jpg' }],
+ },
+ },
+})
+```
+
+Use `updateMany` to update photos with a `url` of `1.jpg` or `2.png`:
+
+```ts
+const product = prisma.product.update({
+ where: {
+ id: '62de6d328a65d8fffdae2c18',
+ },
+ data: {
+ photos: {
+ updateMany: {
+ where: {
+ url: '1.jpg',
+ },
+ data: {
+ url: '2.png',
+ },
+ },
+ },
+ },
+})
+```
+
+The following example uses `deleteMany` to delete all photos with a `height` of 100:
+
+```ts
+const product = prisma.product.update({
+ where: {
+ id: '62de6d328a65d8fffdae2c18',
+ },
+ data: {
+ photos: {
+ deleteMany: {
+ where: {
+ height: 100,
+ },
+ },
+ },
+ },
+})
+```
+
+## Upserting composite types with `upsert`
+
+
+
+When you create or update the values in a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types).
+
+
+
+To create or update a composite type, use the `upsert` method. You can use the same composite operations as the `create` and `update` methods above.
+
+For example, use `upsert` to either create a new product or add a photo to an existing product:
+
+```ts
+const product = await prisma.product.upsert({
+ where: {
+ name: 'Forest Runners',
+ },
+ create: {
+ name: 'Forest Runners',
+ price: 59.99,
+ colors: ['Red', 'Green'],
+ sizes: ['Small', 'Medium', 'Large'],
+ photos: [
+ { height: 100, width: 200, url: '1.jpg' },
+ { height: 100, width: 200, url: '2.jpg' },
+ ],
+ },
+ update: {
+ photos: {
+ push: { height: 300, width: 400, url: '3.jpg' },
+ },
+ },
+})
+```
+
+## Deleting records that contain composite types with `delete` and `deleteMany`
+
+To remove records which embed a composite type, use the `delete` or `deleteMany` methods. This will also remove the embedded composite type.
+
+For example, use `deleteMany` to delete all products with a `size` of `"Small"`. This will also delete any embedded `photos`.
+
+```ts
+const deleteProduct = await prisma.product.deleteMany({
+ where: {
+ sizes: {
+ equals: 'Small',
+ },
+ },
+})
+```
+
+You can also use [filters](/orm/prisma-client/special-fields-and-types/composite-types#finding-records-that-contain-composite-types-with-find-and-findmany) to delete records that match a composite type. The example below uses the `some` filter to delete products that contain a certain photo:
+
+```ts
+const product = await prisma.product.deleteMany({
+ where: {
+ photos: {
+ some: {
+ url: '2.jpg',
+ },
+ },
+ },
+})
+```
+
+## Ordering composite types
+
+You can use the `orderBy` operation to sort results in ascending or descending order.
+
+For example, the following command finds all orders and orders them by the city name in the shipping address, in ascending order:
+
+```ts
+const orders = await prisma.order.findMany({
+ orderBy: {
+ shippingAddress: {
+ city: 'asc',
+ },
+ },
+})
+```
+
+## Duplicate values in unique fields of composite types
+
+Be careful when you carry out any of the following operations on a record with a composite type that has a unique constraint. In this situation, MongoDB does not enforce unique values inside a record.
+
+- When you create the record
+- When you add data to the record
+- When you update data in the record
+
+If your schema has a composite type with a `@@unique` constraint, MongoDB prevents you from storing the same value for the constrained value in two or more of the records that contain this composite type. However, MongoDB does does not prevent you from storing multiple copies of the same field value in a single record.
+
+Note that you can [use Prisma relations to work around this issue](#use-prisma-relations-to-enforce-unique-values-in-a-record).
+
+For example, in the following schema, `MailBox` has a composite type, `addresses`, which has a `@@unique` constraint on the `email` field.
+
+```prisma
+type Address {
+ email String
+}
+
+model MailBox {
+ name String
+ addresses Address[]
+
+ @@unique([addresses.email])
+}
+```
+
+The following code creates a record with two identical values in `address`. MongoDB does not throw an error in this situation, and it stores `alice@prisma.io` in `addresses` twice.
+
+```ts
+await prisma.MailBox.createMany({
+ data: [
+ {
+ name: 'Alice',
+ addresses: {
+ set: [
+ {
+ address: 'alice@prisma.io', // Not unique
+ },
+ {
+ address: 'alice@prisma.io', // Not unique
+ },
+ ],
+ },
+ },
+ ],
+})
+```
+
+Note: MongoDB throws an error if you try to store the same value in two separate records. In our example above, if you try to store the email address `alice@prisma.io` for the user Alice and for the user Bob, MongoDB does not store the data and throws an error.
+
+### Use Prisma relations to enforce unique values in a record
+
+In the example above, MongoDB did not enforce the unique constraint on a nested address name. However, you can model your data differently to enforce unique values in a record. To do so, use Prisma [relations](/orm/prisma-schema/data-model/relations) to turn the composite type into a collection. Set a relationship to this collection and place a unique constraint on the field that you want to be unique.
+
+In the following example, MongoDB enforces unique values in a record. There is a relation between `Mailbox` and the `Address` model. Also, the `name` field in the `Address` model has a unique constraint.
+
+```prisma
+model Address {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ mailbox Mailbox? @relation(fields: [mailboxId], references: [id])
+ mailboxId String? @db.ObjectId
+
+ @@unique([name])
+}
+
+model Mailbox {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ addresses Address[] @relation
+}
+```
+
+```ts
+await prisma.MailBox.create({
+ data: {
+ name: 'Alice',
+ addresses: {
+ create: [
+ { name: 'alice@prisma.io' }, // Not unique
+ { name: 'alice@prisma.io' }, // Not unique
+ ],
+ },
+ },
+})
+```
+
+If you run the above code, MongoDB enforces the unique constraint. It does not allow your application to add two addresses with the name `alice@prisma.io`.
diff --git a/docs/200-orm/200-prisma-client/200-special-fields-and-types/080-null-and-undefined.mdx b/docs/200-orm/200-prisma-client/200-special-fields-and-types/080-null-and-undefined.mdx
new file mode 100644
index 0000000000..e98f66fd42
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/200-special-fields-and-types/080-null-and-undefined.mdx
@@ -0,0 +1,367 @@
+---
+title: 'Null and undefined'
+metaTitle: 'Null and undefined (Reference)'
+metaDescription: 'How Prisma Client handles null and undefined, including a GraphQL use case.'
+preview: false
+---
+
+
+
+Prisma Client differentiates between `null` and `undefined`:
+
+- `null` is a **value**
+- `undefined` means **do nothing**
+
+
+
+This is particularly important to account for in [a **Prisma with GraphQL context**, where `null` and `undefined` are interchangeable](#null-and-undefined-in-a-graphql-resolver).
+
+
+
+The data below represents a `User` table. This set of data will be used in all of the examples below:
+
+| id | name | email |
+| --- | ------- | ----------------- |
+| 1 | Nikolas | nikolas@gmail.com |
+| 2 | Martin | martin@gmail.com |
+| 3 | _empty_ | sabin@gmail.com |
+| 4 | Tyler | tyler@gmail.com |
+
+
+
+
+
+## `null` and `undefined` in queries that affect _many_ records
+
+This section will cover how `undefined` and `null` values affect the behavior of queries that interact with or create multiple records in a database.
+
+### Null
+
+Consider the following Prisma Client query which searches for all users whose `name` value matches the provided `null` value:
+
+
+
+
+
+```ts
+const users = await prisma.user.findMany({
+ where: {
+ name: null,
+ },
+})
+```
+
+
+
+
+
+```json
+[
+ {
+ "id": 3,
+ "name": null,
+ "email": "sabin@gmail.com"
+ }
+]
+```
+
+
+
+
+
+Because `null` was provided as the filter for the `name` column, Prisma Client will generate a query that searches for all records in the `User` table whose `name` column is _empty_.
+
+### Undefined
+
+Now consider the scenario where you run the same query with `undefined` as the filter value on the `name` column:
+
+
+
+
+
+```ts
+const users = await prisma.user.findMany({
+ where: {
+ name: undefined,
+ },
+})
+```
+
+
+
+
+```json
+[
+ {
+ "id": 1,
+ "name": "Nikolas",
+ "email": "nikolas@gmail.com"
+ },
+ {
+ "id": 2,
+ "name": "Martin",
+ "email": "martin@gmail.com"
+ },
+ {
+ "id": 3,
+ "name": null,
+ "email": "sabin@gmail.com"
+ },
+ {
+ "id": 4,
+ "name": "Tyler",
+ "email": "tyler@gmail.com"
+ }
+]
+```
+
+
+
+
+Using `undefined` as a value in a filter essentially tells Prisma Client you have decided _not to define a filter_ for that column.
+
+An equivalent way to write the above query would be:
+
+```ts
+const users = await prisma.user.findMany()
+```
+
+This query will select every row from the `User` table.
+
+
+
+**Note**: Using `undefined` as the value of any key in a Prisma Client query's parameter object will cause Prisma to act as if that key was not provided at all.
+
+
+
+Although this section's examples focused on the `findMany` function, the same concepts apply to any function that can affect multiple records, such as `updateMany` and `deleteMany`.
+
+## `null` and `undefined` in queries that affect _one_ record
+
+This section will cover how `undefined` and `null` values affect the behavior of queries that interact with or create a single record in a database.
+
+
+
+**Note**: `null` is not a valid filter value in a `findUnique` query.
+
+
+
+The query behavior when using `null` and `undefined` in the filter criteria of a query that affects a single record is very similar to the behaviors described in the previous section.
+
+### Null
+
+Consider the following query where `null` is used to filter the `name` column:
+
+
+
+
+
+```ts
+const user = await prisma.user.findFirst({
+ where: {
+ name: null,
+ },
+})
+```
+
+
+
+
+
+```json
+[
+ {
+ "id": 3,
+ "name": null,
+ "email": "sabin@gmail.com"
+ }
+]
+```
+
+
+
+
+Because `null` was used as the filter on the `name` column, Prisma Client will generate a query that searches for the first record in the `User` table whose `name` value is _empty_.
+
+### Undefined
+
+If `undefined` is used as the filter value on the `name` column instead, _the query will act as if no filter criteria was passed to that column at all_.
+
+Consider the query below:
+
+
+
+
+
+```ts
+const user = await prisma.user.findFirst({
+ where: {
+ name: undefined,
+ },
+})
+```
+
+
+
+
+
+```json
+[
+ {
+ "id": 1,
+ "name": "Nikolas",
+ "email": "nikolas@gmail.com"
+ }
+]
+```
+
+
+
+
+In this scenario, the query will return the very first record in the database.
+
+Another way to represent the above query is:
+
+```ts
+const user = await prisma.user.findFirst()
+```
+
+Although this section's examples focused on the `findFirst` function, the same concepts apply to any function that affects a single record.
+
+## `null` and `undefined` in a GraphQL resolver
+
+For this example, consider a database based on the following Prisma schema:
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+}
+```
+
+In the following GraphQL mutation that updates a user, both `authorEmail` and `name` accept `null`. From a GraphQL perspective, this means that fields are **optional**:
+
+```ts
+type Mutation {
+ // Update author's email or name, or both - or neither!
+ updateUser(id: Int!, authorEmail: String, authorName: String): User!
+}
+```
+
+However, if you pass `null` values for `authorEmail` or `authorName` on to Prisma, the following will happen:
+
+- If `args.authorEmail` is `null`, the query will **fail**. `email` does not accept `null`.
+- If `args.authorName` is `null`, Prisma changes the value of `name` to `null`. This is probably not how you want an update to work.
+
+```ts
+updateUser: (parent, args, ctx: Context) => {
+ return ctx.prisma.user.update({
+ where: { id: Number(args.id) },
+ data: {
+| email: args.authorEmail, // email cannot be null
+| name: args.authorName // name set to null - potentially unwanted behavior
+ },
+ })
+},
+```
+
+Instead, set the value of `email` and `name` to `undefined` if the input value is `null`. Doing this is the same as not updating the field at all:
+
+```ts
+updateUser: (parent, args, ctx: Context) => {
+ return ctx.prisma.user.update({
+ where: { id: Number(args.id) },
+ data: {
+| email: args.authorEmail != null ? args.authorEmail : undefined, // If null, do nothing
+| name: args.authorName != null ? args.authorName : undefined // If null, do nothing
+ },
+ })
+},
+```
+
+## The effect of `null` and `undefined` on conditionals
+
+There are some caveats to filtering with conditionals which might produce unexpected results. When filtering with conditionals you might expect one result but receive another given how Prisma treats nullable values.
+
+The following table provides a high-level overview of how the different operators handle 0, 1 and `n` filters.
+
+| Operator | 0 filters | 1 filter | n filters |
+| -------- | ----------------- | ---------------------- | -------------------- |
+| `OR` | return empty list | validate single filter | validate all filters |
+| `AND` | return all items | validate single filter | validate all filters |
+| `NOT` | return all items | validate single filter | validate all filters |
+
+This example shows how an `undefined` parameter impacts the results returned by a query that uses the [`OR`](/orm/reference/prisma-client-reference#or) operator.
+
+```ts
+interface FormData {
+ name: string
+ email?: string
+}
+
+const formData: FormData = {
+ name: 'Emelie',
+}
+
+const users = await prisma.user.findMany({
+ where: {
+ OR: [
+ {
+ email: {
+ contains: formData.email,
+ },
+ },
+ ],
+ },
+})
+
+// returns: []
+```
+
+The query receives filters from a formData object, which includes an optional email property. In this instance, the value of the email property is `undefined`. When this query is run no data is returned.
+
+This is in contrast to the [`AND`](/orm/reference/prisma-client-reference#and) and [`NOT`](/orm/reference/prisma-client-reference#not-1) operators, which will both return all the users
+if you pass in an `undefined` value.
+
+> This is because passing an `undefined` value to an `AND` or `NOT` operator is the same
+> as passing nothing at all, meaning the `findMany` query in the example will run without any filters and return all the users.
+
+```ts
+interface FormData {
+ name: string
+ email?: string
+}
+
+const formData: FormData = {
+ name: 'Emelie',
+}
+
+const users = await prisma.user.findMany({
+ where: {
+ AND: [
+ {
+ email: {
+ contains: formData.email,
+ },
+ },
+ ],
+ },
+})
+
+// returns: { id: 1, email: 'ems@boop.com', name: 'Emelie' }
+
+const users = await prisma.user.findMany({
+ where: {
+ NOT: [
+ {
+ email: {
+ contains: formData.email,
+ },
+ },
+ ],
+ },
+})
+
+// returns: { id: 1, email: 'ems@boop.com', name: 'Emelie' }
+```
diff --git a/docs/200-orm/200-prisma-client/200-special-fields-and-types/100-working-with-json-fields.mdx b/docs/200-orm/200-prisma-client/200-special-fields-and-types/100-working-with-json-fields.mdx
new file mode 100644
index 0000000000..84d40d3f6f
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/200-special-fields-and-types/100-working-with-json-fields.mdx
@@ -0,0 +1,992 @@
+---
+title: 'Working with Json fields'
+metaTitle: 'Working with Json fields (Concepts)'
+metaDescription: 'How to read, write, and filter by Json fields.'
+tocDepth: 3
+---
+
+
+
+Use the [`Json`](/orm/reference/prisma-schema-reference#json) Prisma field type to read, write, and perform basic filtering on JSON types in the underlying database. In the following example, the `User` model has an optional `Json` field named `extendedPetsData`:
+
+```prisma highlight=6;normal
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+ extendedPetsData Json?
+}
+```
+
+Example field value:
+
+```json
+{
+ "pet1": {
+ "petName": "Claudine",
+ "petType": "House cat"
+ },
+ "pet2": {
+ "petName": "Sunny",
+ "petType": "Gerbil"
+ }
+}
+```
+
+> **Note**: The `Json` field is only supported if the [underlying database](/orm/overview) has a corresponding JSON data type.
+
+The `Json` field supports a few additional types, such as `string` and `boolean`. These additional types exist to match the types supported by [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse):
+
+```ts
+export declare type JsonValue =
+ | string
+ | number
+ | boolean
+ | null
+ | JsonObject
+ | JsonArray
+```
+
+
+
+## Use cases for JSON fields
+
+Reasons to store data as JSON rather than representing data as related models include:
+
+- You need to store data that does not have a consistent structure
+- You are importing data from another system and do not want to map that data to Prisma models
+
+## Reading a `Json` field
+
+You can use the `Prisma.JsonArray` and `Prisma.JsonObject` utility classes to work with the contents of a `Json` field:
+
+```ts
+const { PrismaClient, Prisma } = require('@prisma/client')
+
+const user = await prisma.user.findFirst({
+ where: {
+ id: 9,
+ },
+})
+
+// Example extendedPetsData data:
+// [{ name: 'Bob the dog' }, { name: 'Claudine the cat' }]
+
+if (
+ user?.extendedPetsData &&
+ typeof user?.extendedPetsData === 'object' &&
+ Array.isArray(user?.extendedPetsData)
+) {
+ const petsObject = user?.extendedPetsData as Prisma.JsonArray
+
+ const firstPet = petsObject[0]
+}
+```
+
+See also: [Advanced example: Update a nested JSON key value](#advanced-example-update-a-nested-json-key-value)
+
+## Writing to a `Json` field
+
+The following example writes a JSON object to the `extendedPetsData` field:
+
+```ts
+var json = [
+ { name: 'Bob the dog' },
+ { name: 'Claudine the cat' },
+] as Prisma.JsonArray
+
+const createUser = await prisma.user.create({
+ data: {
+ email: 'birgitte@prisma.io',
+ extendedPetsData: json,
+ },
+})
+```
+
+> **Note**: JavaScript objects (for example, `{ extendedPetsData: "none"}`) are automatically converted to JSON.
+
+See also: [Advanced example: Update a nested JSON key value](#advanced-example-update-a-nested-json-key-value)
+
+## Filter on a `Json` field
+
+From v2.23.0, you can filter rows by the data inside a `Json` type. We call this **advanced `Json` filtering**.
+
+The availability of advanced `Json` filtering depends on your Prisma version:
+
+- V4.0.0 or later: advanced `Json` filtering is [generally available](/orm/more/releases#generally-available-ga).
+- From v2.23.0, but before v4.0.0: advanced `Json` filtering is a [preview feature](/orm/reference/preview-features/client-preview-features). Add `previewFeatures = ["filterJson"]` to your schema. [Learn more](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature).
+- Before v2.23.0: you can [filter on the exact `Json` field value](#filter-on-exact-field-value), but you cannot use the other features described in this section.
+
+
+
+Advanced `Json` filtering is supported by [PostgreSQL](/orm/overview/databases/postgresql) and [MySQL](/orm/overview/databases/mysql) only with different syntaxes for the `path` option. PostgreSQL does not support [filtering on object key values in arrays](#filtering-on-object-key-value-inside-array).
+
+
+
+### Database connector implementation differences
+
+The implementation of `Json` filtering differs between connectors:
+
+- The [MySQL connector](/orm/overview/databases/mysql) uses [MySQL's implementation of JSON path](https://dev.mysql.com/doc/refman/8.0/en/json.html#json-path-syntax)
+- The [PostgreSQL connector](/orm/overview/databases/postgresql) uses the custom JSON functions and operators [supported in version 12 _and earlier_](https://www.postgresql.org/docs/11/functions-json.html)
+
+This means that `path` option syntax differs between database connectors - for example, the following is a valid MySQL `path` value:
+
+```
+$petFeatures.petName
+```
+
+The following is a valid PostgreSQL `path` value:
+
+```
+["petFeatures", "petName"]
+```
+
+### Filter on exact field value
+
+The following query returns all users where the value of `extendedPetsData` matches the `json` variable exactly:
+
+```ts
+var json = { [{ name: 'Bob the dog' }, { name: 'Claudine the cat' }] }
+
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ equals: json,
+ },
+ },
+})
+```
+
+The following query returns all users where the value of `extendedPetsData` does **not** match the `json` variable exactly:
+
+```ts
+var json = {
+ extendedPetsData: [{ name: 'Bob the dog' }, { name: 'Claudine the cat' }],
+}
+
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ not: json,
+ },
+ },
+})
+```
+
+### Filter on object property
+
+In [2.23.0](https://github.com/prisma/prisma/releases/tag/2.23.0) and later, you can filter on a specific property inside a block of JSON. In the following examples, the value of `extendedPetsData` is a one-dimensional, unnested JSON object:
+
+```json highlight=11;normal
+{
+ "petName": "Claudine",
+ "petType": "House cat"
+}
+```
+
+The following query returns all users where the value of `petName` is `"Claudine"`:
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: ['petName'],
+ equals: 'Claudine',
+ },
+ },
+})
+```
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$.petName',
+ equals: 'Claudine',
+ },
+ },
+})
+```
+
+
+
+
+
+The following query returns all users where the value of `petType` _contains_ `"cat"`:
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: ['petType'],
+ string_contains: 'cat',
+ },
+ },
+})
+```
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$.petType',
+ string_contains: 'cat',
+ },
+ },
+})
+```
+
+
+
+
+The following string filters are available:
+
+- [`string_contains`](/orm/reference/prisma-client-reference#string_contains)
+- [`string_starts_with`](/orm/reference/prisma-client-reference#string_starts_with)
+- [`string_ends_with`](/orm/reference/prisma-client-reference#string_ends_with) .
+
+### Filter on nested object property
+
+You can filter on nested JSON properties. In the following examples, the value of `extendedPetsData` is a JSON object with several levels of nesting.
+
+```json
+{
+ "pet1": {
+ "petName": "Claudine",
+ "petType": "House cat"
+ },
+ "pet2": {
+ "petName": "Sunny",
+ "petType": "Gerbil",
+ "features": {
+ "eyeColor": "Brown",
+ "furColor": "White and black"
+ }
+ }
+}
+```
+
+The following query returns all users where `"pet2"` → `"petName"` is `"Sunny"`:
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: ['pet2', 'petName'],
+ equals: 'Sunny',
+ },
+ },
+})
+```
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$.pet2.petName',
+ equals: 'Sunny',
+ },
+ },
+})
+```
+
+
+
+
+The following query returns all users where:
+
+- `"pet2"` → `"petName"` is `"Sunny"`
+- `"pet2"` → `"features"` → `"furColor"` contains `"black"`
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ AND: [
+ {
+ extendedPetsData: {
+ path: ['pet2', 'petName'],
+ equals: 'Sunny',
+ },
+ },
+ {
+ extendedPetsData: {
+ path: ['pet2', 'features', 'furColor'],
+ string_contains: 'black',
+ },
+ },
+ ],
+ },
+})
+```
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ AND: [
+ {
+ extendedPetsData: {
+ path: '$.pet2.petName',
+ equals: 'Sunny',
+ },
+ },
+ {
+ extendedPetsData: {
+ path: '$.pet2.features.furColor',
+ string_contains: 'black',
+ },
+ },
+ ],
+ },
+})
+```
+
+
+
+
+
+### Filtering on an array value
+
+You can filter on the presence of a specific value in a scalar array (strings, integers). In the following example, the value of `extendedPetsData` is an array of strings:
+
+```json
+["Claudine", "Sunny"]
+```
+
+The following query returns all users with a pet named `"Claudine"`:
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ array_contains: ['Claudine'],
+ },
+ },
+})
+```
+
+
+
+**Note**: In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value.
+
+
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ array_contains: 'Claudine',
+ },
+ },
+})
+```
+
+
+
+
+
+The following array filters are available:
+
+- [`array_contains`](/orm/reference/prisma-client-reference#array_contains)
+- [`array_starts_with`](/orm/reference/prisma-client-reference#array_starts_with)
+- [`array_ends_with`](/orm/reference/prisma-client-reference#array_ends_with)
+
+### Filtering on nested array value
+
+You can filter on the presence of a specific value in a scalar array (strings, integers). In the following examples, the value of `extendedPetsData` includes nested scalar arrays of names:
+
+```json
+{
+ "cats": { "owned": ["Bob", "Sunny"], "fostering": ["Fido"] },
+ "dogs": { "owned": ["Ella"], "fostering": ["Prince", "Empress"] }
+}
+```
+
+#### Scalar value arrays
+
+The following query returns all users that foster a cat named `"Fido"`:
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: ['cats', 'fostering'],
+ array_contains: ['Fido'],
+ },
+ },
+})
+```
+
+
+
+**Note**: In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value.
+
+
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$.cats.fostering',
+ array_contains: 'Fido',
+ },
+ },
+})
+```
+
+
+
+
+The following query returns all users that foster cats named `"Fido"` _and_ `"Bob"`:
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: ['cats', 'fostering'],
+ array_contains: ['Fido', 'Bob'],
+ },
+ },
+})
+```
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$.cats.fostering',
+ array_contains: ['Fido', 'Bob'],
+ },
+ },
+})
+```
+
+
+
+
+#### JSON object arrays
+
+
+
+
+```ts
+const json = [{ status: 'expired', insuranceID: 92 }]
+
+const checkJson = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: ['insurances'],
+ array_contains: json,
+ },
+ },
+})
+```
+
+
+
+
+```ts
+const json = { status: 'expired', insuranceID: 92 }
+
+const checkJson = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$.insurances',
+ array_contains: json,
+ },
+ },
+})
+```
+
+
+
+
+- If you are using PostgreSQL, you must pass in an array of objects to match, even if that array only contains one object:
+
+ ```json5
+ [{ status: 'expired', insuranceID: 92 }]
+ // PostgreSQL
+ ```
+
+ If you are using MySQL, you must pass in a single object to match:
+
+ ```json5
+ { status: 'expired', insuranceID: 92 }
+ // MySQL
+ ```
+
+- If your filter array contains multiple objects, PostgreSQL will only return results if _all_ objects are present - not if at least one object is present.
+
+- You must set `array_contains` to a JSON object, not a string. If you use a string, Prisma escapes the quotation marks and the query will not return results. For example:
+
+ ```ts
+ array_contains: '[{"status": "expired", "insuranceID": 92}]'
+ ```
+
+ is sent to the database as:
+
+ ```
+ [{\"status\": \"expired\", \"insuranceID\": 92}]
+ ```
+
+### Targeting an array element by index
+
+You can filter on the value of an element in a specific position.
+
+```json
+{ "owned": ["Bob", "Sunny"], "fostering": ["Fido"] }
+```
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ comments: {
+ path: ['owned', '1'],
+ string_contains: 'Bob',
+ },
+ },
+})
+```
+
+
+
+
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ comments: {
+ path: '$.owned[1]',
+ string_contains: 'Bob',
+ },
+ },
+})
+```
+
+
+
+
+
+### Filtering on object key value inside array
+
+Depending on your provider, you can filter on the key value of an object inside an array.
+
+
+
+Filtering on object key values within an array is **only** supported by the [MySQL database connector](/orm/overview/databases/mysql). However, you can still [filter on the presence of entire JSON objects](#json-object-arrays).
+
+
+
+In the following example, the value of `extendedPetsData` is an array of objects with a nested `insurances` array, which contains two objects:
+
+```json
+[
+ {
+ "petName": "Claudine",
+ "petType": "House cat",
+ "insurances": [
+ { "insuranceID": 92, "status": "expired" },
+ { "insuranceID": 12, "status": "active" }
+ ]
+ },
+ {
+ "petName": "Sunny",
+ "petType": "Gerbil"
+ },
+ {
+ "petName": "Gerald",
+ "petType": "Corn snake"
+ },
+ {
+ "petName": "Nanna",
+ "petType": "Moose"
+ }
+]
+```
+
+The following query returns all users where at least one pet is a moose:
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$[*].petType',
+ array_contains: 'Moose',
+ },
+ },
+})
+```
+
+- `$[*]` is the root array of pet objects
+- `petType` matches the `petType` key in any pet object
+
+The following query returns all users where at least one pet has an expired insurance:
+
+```ts
+const getUsers = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$[*].insurances[*].status',
+ array_contains: 'expired',
+ },
+ },
+})
+```
+
+- `$[*]` is the root array of pet objects
+- `insurances[*]` matches any `insurances` array inside any pet object
+- `status` matches any `status` key in any insurance object
+
+## Advanced example: Update a nested JSON key value
+
+The following example assumes that the value of `extendedPetsData` is some variation of the following:
+
+```json
+{
+ "petName": "Claudine",
+ "petType": "House cat",
+ "insurances": [
+ { "insuranceID": 92, "status": "expired" },
+ { "insuranceID": 12, "status": "active" }
+ ]
+}
+```
+
+The following example:
+
+1. Gets all users
+1. Change the `"status"` of each insurance object to `"expired"`
+1. Get all users that have an expired insurance where the ID is `92`
+
+
+
+
+```ts
+const userQueries: string | any[] = []
+
+getUsers.forEach((user) => {
+ if (
+ user.extendedPetsData &&
+ typeof user.extendedPetsData === 'object' &&
+ !Array.isArray(user.extendedPetsData)
+ ) {
+ const petsObject = user.extendedPetsData as Prisma.JsonObject
+
+ const i = petsObject['insurances']
+
+ if (i && typeof i === 'object' && Array.isArray(i)) {
+ const insurancesArray = i as Prisma.JsonArray
+
+ insurancesArray.forEach((i) => {
+ if (i && typeof i === 'object' && !Array.isArray(i)) {
+ const insuranceObject = i as Prisma.JsonObject
+
+ insuranceObject['status'] = 'expired'
+ }
+ })
+
+ const whereClause = Prisma.validator()({
+ id: user.id,
+ })
+
+ const dataClause = Prisma.validator()({
+ extendedPetsData: petsObject,
+ })
+
+ userQueries.push(
+ prisma.user.update({
+ where: whereClause,
+ data: dataClause,
+ })
+ )
+ }
+ }
+})
+
+if (userQueries.length > 0) {
+ console.log(userQueries.length + ' queries to run!')
+ await prisma.$transaction(userQueries)
+}
+
+const json = [{ status: 'expired', insuranceID: 92 }]
+
+const checkJson = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: ['insurances'],
+ array_contains: json,
+ },
+ },
+})
+
+console.log(checkJson.length)
+```
+
+
+
+
+
+```ts
+const userQueries: string | any[] = []
+
+getUsers.forEach((user) => {
+ if (
+ user.extendedPetsData &&
+ typeof user.extendedPetsData === 'object' &&
+ !Array.isArray(user.extendedPetsData)
+ ) {
+ const petsObject = user.extendedPetsData as Prisma.JsonObject
+
+ const insuranceList = petsObject['insurances'] // is a Prisma.JsonArray
+
+ if (Array.isArray(insuranceList)) {
+ insuranceList.forEach((insuranceItem) => {
+ if (
+ insuranceItem &&
+ typeof insuranceItem === 'object' &&
+ !Array.isArray(insuranceItem)
+ ) {
+ insuranceItem['status'] = 'expired' // is a Prisma.JsonObject
+ }
+ })
+
+ const whereClause = Prisma.validator()({
+ id: user.id,
+ })
+
+ const dataClause = Prisma.validator()({
+ extendedPetsData: petsObject,
+ })
+
+ userQueries.push(
+ prisma.user.update({
+ where: whereClause,
+ data: dataClause,
+ })
+ )
+ }
+ }
+})
+
+if (userQueries.length > 0) {
+ console.log(userQueries.length + ' queries to run!')
+ await prisma.$transaction(userQueries)
+}
+
+const json = { status: 'expired', insuranceID: 92 }
+
+const checkJson = await prisma.user.findMany({
+ where: {
+ extendedPetsData: {
+ path: '$.insurances',
+ array_contains: json,
+ },
+ },
+})
+
+console.log(checkJson.length)
+```
+
+
+
+
+## Using `null` Values
+
+There are two types of `null` values possible for a `JSON` field in an SQL database.
+
+- Database `NULL`: The value in the database is a `NULL`.
+- JSON `null`: The value in the database contains a JSON value that is `null`.
+
+To differentiate between these possibilities, we've introduced three _null enums_ you can use:
+
+- `JsonNull`: Represents the `null` value in JSON.
+- `DbNull`: Represents the `NULL` value in the database.
+- `AnyNull`: Represents both `null` JSON values and `NULL` database values. (Only when filtering)
+
+
+
+From v4.0.0, `JsonNull`, `DbNull`, and `AnyNull` are objects. Before v4.0.0, they were strings.
+
+
+
+
+
+- When filtering using any of the _null enums_ you can not use a shorthand and leave the `equals` operator off.
+- These _null enums_ do not apply to MongoDB because there the difference between a JSON `null` and a database `NULL` does not exist.
+- The _null enums_ do not apply to the `array_contains` operator in all databases because there can only be a JSON `null` within a JSON array. Since there cannot be a database `NULL` within a JSON array, `{ array_contains: null }` is not ambiguous.
+
+
+
+For example:
+
+```prisma
+model Log {
+ id Int @id
+ meta Json
+}
+```
+
+Here is an example of using `AnyNull`:
+
+```ts highlight=7;normal
+import { Prisma } from '@prisma/client'
+
+prisma.log.findMany({
+ where: {
+ data: {
+ meta: {
+ equals: Prisma.AnyNull,
+ },
+ },
+ },
+})
+```
+
+### Inserting `null` Values
+
+This also applies to `create`, `update` and `upsert`. To insert a `null` value
+into a `Json` field, you would write:
+
+```ts highlight=5;normal
+import { Prisma } from '@prisma/client'
+
+prisma.log.create({
+ data: {
+ meta: Prisma.JsonNull,
+ },
+})
+```
+
+And to insert a database `NULL` into a `Json` field, you would write:
+
+```ts highlight=5;normal
+import { Prisma } from '@prisma/client'
+
+prisma.log.create({
+ data: {
+ meta: Prisma.DbNull,
+ },
+})
+```
+
+### Filtering by `null` Values
+
+To filter by `JsonNull` or `DbNull`, you would write:
+
+```ts highlight=6;normal
+import { Prisma } from '@prisma/client'
+
+prisma.log.findMany({
+ where: {
+ meta: {
+ equals: Prisma.AnyNull,
+ },
+ },
+})
+```
+
+
+
+These _null enums_ do not apply to MongoDB because MongoDB does not differentiate between a JSON `null` and a database `NULL`. They also do not apply to the `array_contains` operator in all databases because there can only be a JSON `null` within a JSON array. Since there cannot be a database `NULL` within a JSON array, `{ array_contains: null }` is not ambiguous.
+
+
+
+## Typed `Json`
+
+By default, `Json` fields are not typed in Prisma models. To accomplish strong typing inside of these fields, you will need to use an external package like [prisma-json-types-generator](https://www.npmjs.com/package/prisma-json-types-generator) to accomplish this.
+
+### Using `prisma-json-types-generator`
+
+First, install and configure `prisma-json-types-generator` [according to the package's instructions](https://www.npmjs.com/package/prisma-json-types-generator#using-it).
+
+Then, assuming you have a model like the following:
+
+```prisma no-copy
+model Log {
+ id Int @id
+ meta Json
+}
+```
+
+You can update it and type it by using [abstract syntax tree comments](https://www.prisma.io/docs/orm/prisma-schema/overview#comments)
+
+```prisma highlight=4;normal file=schema.prisma
+model Log {
+ id Int @id
+
+ /// [LogMetaType]
+ meta Json
+}
+```
+
+Then, make sure you define the above type in a type declaration file included in your `tsconfig.json`
+
+```ts file=types.ts
+declare global {
+ namespace PrismaJson {
+ type LogMetaType = { timestamp: number; host: string }
+ }
+}
+```
+
+Now, when working with `Log.meta` it will be strongly typed!
+
+## `Json` FAQs
+
+### Can you select a subset of JSON key/values to return?
+
+No - it is not yet possible to [select which JSON elements to return](https://github.com/prisma/prisma/issues/2431). Prisma Client returns the entire JSON object.
+
+### Can you filter on the presence of a specific key?
+
+No - it is not yet possible to filter on the presence of a specific key.
+
+### Is case insensitive filtering supported?
+
+No - [case insensitive filtering](https://github.com/prisma/prisma/issues/7390) is not yet supported.
diff --git a/docs/200-orm/200-prisma-client/200-special-fields-and-types/200-working-with-scalar-lists-arrays.mdx b/docs/200-orm/200-prisma-client/200-special-fields-and-types/200-working-with-scalar-lists-arrays.mdx
new file mode 100644
index 0000000000..ab258de11f
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/200-special-fields-and-types/200-working-with-scalar-lists-arrays.mdx
@@ -0,0 +1,219 @@
+---
+title: 'Working with scalar lists'
+metaTitle: 'Working with scalar lists/arrays (Concepts)'
+metaDescription: 'How to read, write, and filter by scalar lists / arrays.'
+tocDepth: 3
+---
+
+
+
+[Scalar lists](/orm/reference/prisma-schema-reference#-modifier) are represented by the `[]` modifier and are only available if the underlying database supports scalar lists. The following example has one scalar `String` list named `pets`:
+
+
+
+
+```prisma highlight=4;normal
+model User {
+ id Int @id @default(autoincrement())
+ name String
+ pets String[]
+}
+```
+
+
+
+
+```prisma highlight=4;normal
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ pets String[]
+}
+```
+
+
+
+
+Example field value:
+
+```json5
+['Fido', 'Snoopy', 'Brian']
+```
+
+
+
+## Setting the value of a scalar list
+
+The following example demonstrates how to [`set`](/orm/reference/prisma-client-reference#set-1) the value of a scalar list (`coinflips`) when you create a model:
+
+```ts
+const createdUser = await prisma.user.create({
+ data: {
+ email: 'eloise@prisma.io',
+ coinflips: [true, true, true, false, true],
+ },
+})
+```
+
+## Unsetting the value of a scalar list
+
+
+
+This method is available on MongoDB only in versions
+[3.11.1](https://github.com/prisma/prisma/releases/tag/3.11.1) and later.
+
+
+
+The following example demonstrates how to [`unset`](/orm/reference/prisma-client-reference#unset) the value of a scalar list (`coinflips`):
+
+```ts
+const createdUser = await prisma.user.create({
+ data: {
+ email: 'eloise@prisma.io',
+ coinflips: {
+ unset: true,
+ },
+ },
+})
+```
+
+Unlike `set: null`, `unset` removes the list entirely.
+
+## Adding items to a scalar list
+
+
+
+Available for:
+
+- PostgreSQL in versions [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) and later
+- CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later
+- MongoDB in versions [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0) and later
+
+
+
+Use the [`push`](/orm/reference/prisma-client-reference#push) method to add a single value to a scalar list:
+
+```ts
+const userUpdate = await prisma.user.update({
+ where: {
+ id: 9,
+ },
+ data: {
+ coinflips: {
+ push: true,
+ },
+ },
+})
+```
+
+In earlier versions, you have to overwrite the entire value. The following example retrieves user, uses `push()` to add three new coin flips, and overwrites the `coinflips` field in an `update`:
+
+```ts
+const user = await prisma.user.findUnique({
+ where: {
+ email: 'eloise@prisma.io',
+ },
+})
+
+if (user) {
+ console.log(user.coinflips)
+
+ user.coinflips.push(true, true, false)
+
+ const updatedUser = await prisma.user.update({
+ where: {
+ email: 'eloise@prisma.io',
+ },
+ data: {
+ coinflips: user.coinflips,
+ },
+ })
+
+ console.log(updatedUser.coinflips)
+}
+```
+
+## Filtering scalar lists
+
+
+
+Available for:
+
+- PostgreSQL in versions [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) and later
+- CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later
+- MongoDB in versions [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0) and later
+
+
+
+Use [scalar list filters](/orm/reference/prisma-client-reference#scalar-list-filters) to filter for records with scalar lists that match a specific condition. The following example returns all posts where the tags list includes `databases` _and_ `typescript`:
+
+```ts
+const posts = await prisma.post.findMany({
+ where: {
+ tags: {
+ hasEvery: ['databases', 'typescript'],
+ },
+ },
+})
+```
+
+### `NULL` values in arrays
+
+
+
+This section applies to:
+
+- PostgreSQL in versions [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) and later
+- CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later
+
+
+
+When using scalar list filters with a relational database connector, array fields with a `NULL` value are not considered by the following conditions:
+
+- `NOT` (array does not contain X)
+- `isEmpty` (array is empty)
+
+This means that records you might expect to see are not returned. Consider the following examples:
+
+- The following query returns all posts where the `tags` **do not** include `databases`:
+
+ ```ts
+ const posts = await prisma.post.findMany({
+ where: {
+ NOT: {
+ tags: {
+ has: 'databases',
+ },
+ },
+ },
+ })
+ ```
+
+ - ✔ Arrays that do not contain `"databases"`, such as `{"typescript", "graphql"}`
+ - ✔ Empty arrays, such as `[]`
+
+ The query does not return:
+
+ - ✘ `NULL` arrays, even though they do not contain `"databases"`
+
+The following query returns all posts where `tags` is empty:
+
+```ts
+const posts = await prisma.post.findMany({
+ where: {
+ tags: {
+ isEmpty: true,
+ },
+ },
+})
+```
+
+The query returns:
+
+- ✔ Empty arrays, such as `[]`
+
+The query does not return:
+
+- ✘ `NULL` arrays, even though they could be considered empty
+
+To work around this issue, you can set the default value of array fields to `[]`.
diff --git a/docs/200-orm/200-prisma-client/200-special-fields-and-types/300-working-with-composite-ids-and-constraints.mdx b/docs/200-orm/200-prisma-client/200-special-fields-and-types/300-working-with-composite-ids-and-constraints.mdx
new file mode 100644
index 0000000000..127a4d0cf8
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/200-special-fields-and-types/300-working-with-composite-ids-and-constraints.mdx
@@ -0,0 +1,206 @@
+---
+title: 'Working with compound IDs and unique constraints'
+metaTitle: 'Working with compound IDs and unique constraints (Concepts)'
+metaDescription: 'How to read, write, and filter by compound IDs and unique constraints.'
+tocDepth: 2
+---
+
+
+
+Composite IDs and compound unique constraints can be defined in your Prisma schema using the [`@@id`](/orm/reference/prisma-schema-reference#id-1) and [`@@unique`](/orm/reference/prisma-schema-reference#unique-1) attributes.
+
+
+
+**MongoDB does not support `@@id`**
+MongoDB does not support composite IDs, which means you cannot identify a model with a `@@id` attribute.
+
+
+
+A composite ID or compound unique constraint uses the combined values of two fields as a primary key or identifier in your database table. In the following example, the `postId` field and `userId` field are used as a composite ID for a `Like` table:
+
+```prisma highlight=22;normal
+model User {
+ id Int @id @default(autoincrement())
+ name String
+ post Post[]
+ likes Like[]
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ content String
+ User User? @relation(fields: [userId], references: [id])
+ userId Int?
+ likes Like[]
+}
+
+model Like {
+ postId Int
+ userId Int
+ User User @relation(fields: [userId], references: [id])
+ Post Post @relation(fields: [postId], references: [id])
+
+ @@id([postId, userId])
+}
+```
+
+Querying for records from the `Like` table (e.g. using `prisma.like.findMany()`) would return objects that look as follows:
+
+```json
+{
+ "postId": 1,
+ "userId": 1
+}
+```
+
+Although there are only two fields in the response, those two fields make up a compound ID named `postId_userId`.
+
+You can also create a named compound ID or compound unique constraint by using the `@@id` or `@@unique` attributes' `name` field. For example:
+
+```prisma highlight=7;normal
+model Like {
+ postId Int
+ userId Int
+ User User @relation(fields: [userId], references: [id])
+ Post Post @relation(fields: [postId], references: [id])
+
+ @@id(name: "likeId", [postId, userId])
+}
+```
+
+
+
+## Where you can use compound IDs and unique constraints
+
+Compound IDs and compound unique constraints can be used when working with _unique_ data.
+
+Below is a list of Prisma Client functions that accept a compound ID or compound unique constraint in the `where` filter of the query:
+
+- `findUnique`
+- `findUniqueOrThrow`
+- `delete`
+- `update`
+- `upsert`
+
+A composite ID and a composite unique constraint is also usable when creating relational data with `connect` and `connectOrCreate`.
+
+## Filtering records by a compound ID or unique constraint
+
+Although your query results will not display a compound ID or unique constraint as a field, you can use these compound values to filter your queries for unique records:
+
+```ts highlight=3-6;normal
+const like = await prisma.like.findUnique({
+ where: {
+ likeId: {
+ userId: 1,
+ postId: 1,
+ },
+ },
+})
+```
+
+
+
+Note composite ID and compound unique constraint keys are only available as filter options for _unique_ queries such as `findUnique` and `findUniqueOrThrow`. See the [section](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints#where-you-can-use-compound-ids-and-unique-constraints) above for a list of places these fields may be used.
+
+
+
+## Deleting records by a compound ID or unique constraint
+
+A compound ID or compound unique constraint may be used in the `where` filter of a `delete` query:
+
+```ts highlight=3-6;normal
+const like = await prisma.like.delete({
+ where: {
+ likeId: {
+ userId: 1,
+ postId: 1,
+ },
+ },
+})
+```
+
+## Updating and upserting records by a compound ID or unique constraint
+
+A compound ID or compound unique constraint may be used in the `where` filter of an `update` query:
+
+```ts highlight=3-6;normal
+const like = await prisma.like.update({
+ where: {
+ likeId: {
+ userId: 1,
+ postId: 1,
+ },
+ },
+ data: {
+ postId: 2,
+ },
+})
+```
+
+They may also be used in the `where` filter of an `upsert` query:
+
+```ts highlight=3-6;normal
+await prisma.like.upsert({
+ where: {
+ likeId: {
+ userId: 1,
+ postId: 1,
+ },
+ },
+ update: {
+ userId: 2,
+ },
+ create: {
+ userId: 2,
+ postId: 1,
+ },
+})
+```
+
+## Filtering relation queries by a compound ID or unique constraint
+
+Compound IDs and compound unique constraint can also be used in the `connect` and `connectOrCreate` keys used when connecting records to create a relationship.
+
+For example, consider this query:
+
+```ts highlight=6-9;normal
+await prisma.user.create({
+ data: {
+ name: 'Alice',
+ likes: {
+ connect: {
+ likeId: {
+ postId: 1,
+ userId: 2,
+ },
+ },
+ },
+ },
+})
+```
+
+The `likeId` compound ID is used as the identifier in the `connect` object that is used to locate the `Like` table's record that will be linked to the new user: `"Alice"`.
+
+Similarly, the `likeId` can be used in `connectOrCreate`'s `where` filter to attempt to locate an existing record in the `Like` table:
+
+```ts highlight=10-13;normal
+await prisma.user.create({
+ data: {
+ name: 'Alice',
+ likes: {
+ connectOrCreate: {
+ create: {
+ postId: 1,
+ },
+ where: {
+ likeId: {
+ postId: 1,
+ userId: 1,
+ },
+ },
+ },
+ },
+ },
+})
+```
diff --git a/docs/200-orm/200-prisma-client/200-special-fields-and-types/index.mdx b/docs/200-orm/200-prisma-client/200-special-fields-and-types/index.mdx
new file mode 100644
index 0000000000..4c786346c6
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/200-special-fields-and-types/index.mdx
@@ -0,0 +1,89 @@
+---
+title: 'Fields & types'
+metaTitle: 'Fields & types'
+metaDescription: 'Learn how to use about special fields and types with Prisma Client.'
+tocDepth: 3
+---
+
+
+
+This section covers various special fields and types you can use with Prisma Client.
+
+
+
+## Working with `Decimal`
+
+`Decimal` fields are represented by the [`Decimal.js` library](https://mikemcl.github.io/decimal.js/). The following example demonstrates how to import and use `Prisma.Decimal`:
+
+```ts
+import { PrismaClient, Prisma } from '@prisma/client'
+
+const newTypes = await prisma.sample.create({
+ data: {
+ cost: new Prisma.Decimal(24.454545),
+ },
+})
+```
+
+
+
+The use of the `Decimal` field [is not currently supported in MongoDB](https://github.com/prisma/prisma/issues/12637).
+
+
+
+## Working with `BigInt`
+
+`BigInt` fields are represented by the [`BigInt` type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (Node.js 10.4.0+ required). The following example demonstrates how to use the `BigInt` type:
+
+```ts
+import { PrismaClient, Prisma } from '@prisma/client'
+
+const newTypes = await prisma.sample.create({
+ data: {
+ revenue: BigInt(534543543534),
+ },
+})
+```
+
+### Serializing BigInt
+
+Prisma returns records as plain JavaScript objects. If you attempt to use `JSON.stringify` on an object that includes a `BigInt` field, you will see the following error:
+
+```
+Do not know how to serialize a BigInt
+```
+
+To work around this issue, use a customized implementation of `JSON.stringify`:
+
+```js
+JSON.stringify(
+ this,
+ (key, value) => (typeof value === 'bigint' ? value.toString() : value) // return everything else unchanged
+)
+```
+
+## Working with `Bytes`
+
+`Bytes` fields are represented by the [`Buffer`](https://nodejs.org/api/buffer.html) type. The following example demonstrates how to use the `Buffer` type:
+
+```ts
+import { PrismaClient, Prisma } from '@prisma/client'
+
+const newTypes = await prisma.sample.create({
+ data: {
+ myField: Buffer.from([1, 2, 3, 4]),
+ },
+})
+```
+
+## Working with `Json`
+
+See: [Working with `Json` fields](working-with-json-fields)
+
+## Working with scalar lists / scalar arrays
+
+See: [Working with scalar lists / arrays](working-with-scalar-lists-arrays)
+
+## Working with composite IDs and compound unique constraints
+
+See: [Working with composite IDs and compound unique constraints](working-with-composite-ids-and-constraints)
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/100-model.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/100-model.mdx
new file mode 100644
index 0000000000..a74d1a62c2
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/100-model.mdx
@@ -0,0 +1,164 @@
+---
+title: '`model`: Add custom methods to your models'
+metaTitle: 'Prisma Client extensions: model component'
+metaDescription: 'Extend the functionality of Prisma Client, model component'
+tocDepth: 4
+---
+
+
+
+
+
+Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0.
+
+
+
+You can use the `model` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to add custom methods to your models.
+
+Possible uses for the `model` component include the following:
+
+- New operations to operate alongside existing Prisma Client operations, such as `findMany`
+- Encapsulated business logic
+- Repetitive operations
+- Model-specific utilities
+
+
+
+## Add a custom method
+
+Use the `$extends` [client-level method](/orm/reference/prisma-client-reference#client-methods) to create an _extended client_. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions. Use the `model` extension component to add methods to models in your schema.
+
+### Add a custom method to a specific model
+
+To extend a specific model in your schema, use the following structure. This example adds a method to the `user` model.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ name?: '', // (optional) names the extension for error logs
+ model?: {
+ user: { ... } // in this case, we extend the `user` model
+ },
+});
+```
+
+#### Example
+
+The following example adds a method called `signUp` to the `user` model. This method creates a new user with the specified email address.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ model: {
+ user: {
+ async signUp(email: string) {
+ await prisma.user.create({ data: { email } })
+ },
+ },
+ },
+})
+```
+
+You would call `signUp` in your application as follows:
+
+```ts
+const user = await prisma.user.signUp('john@prisma.io')
+```
+
+When you call a method in an extension, use the constant name from your `$extends` statement, not `prisma`. In the above example, `prisma.user.signUp` works, but `prisma.user.signUp` does not, because the original `prisma` is not modified.
+
+### Add a custom method to all models in your schema
+
+To extend _all_ models in your schema, use the following structure:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ name?: '', // `name` is an optional field that you can use to name the extension for error logs
+ model?: {
+ $allModels: { ... }
+ },
+})
+```
+
+#### Example
+
+The following example adds an `exists` method to all models.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ model: {
+ $allModels: {
+ async exists(
+ this: T,
+ where: Prisma.Args['where']
+ ): Promise {
+ // Get the current model at runtime
+ const context = Prisma.getExtensionContext(this)
+
+ const result = await (context as any).findFirst({ where })
+ return result !== null
+ },
+ },
+ },
+})
+```
+
+You would call `exists` in your application as follows:
+
+```ts
+// `exists` method available on all models
+await prisma.user.exists({ name: 'Alice' })
+await prisma.post.exists({
+ OR: [{ title: { contains: 'Prisma' } }, { content: { contains: 'Prisma' } }],
+})
+```
+
+## Call a custom method from another custom method
+
+You can call a custom method from another custom method, if the two methods are declared on the same model. For example, you can call a custom method on the `user` model from another custom method on the `user` model. It does not matter if the two methods are declared in the same extension or in different extensions.
+
+To do so, use `Prisma.getExtensionContext(this).methodName`. Note that you cannot use `prisma.user.methodName`. This is because `prisma` is not extended yet, and therefore does not contain the new method.
+
+For example:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ model: {
+ user: {
+ firstMethod() {
+ ...
+ },
+ secondMethod() {
+ Prisma.getExtensionContext(this).firstMethod()
+ }
+ }
+ }
+})
+```
+
+## Get the current model name at runtime
+
+
+
+This feature is available from version 4.9.0.
+
+
+
+You can get the name of the current model at runtime with `Prisma.getExtensionContext(this).name`. You might use this to write out the model name to a log, to send the name to another service, or to branch your code based on the model.
+
+For example:
+
+```ts
+// `context` refers to the current model
+const context = Prisma.getExtensionContext(this)
+
+// `context.name` returns the name of the current model
+console.log(context.name)
+
+// Usage
+await(context as any).findFirst({ args })
+```
+
+Refer to [Add a custom method to all models in your schema](#example-1) for a concrete example for retrieving the current model name at runtime.
+
+## Advanced type safety: type utilities for defining generic extensions
+
+You can improve the type-safety of `model` components in your shared extensions with [type utilities](/orm/prisma-client/client-extensions/type-utilities).
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/110-client.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/110-client.mdx
new file mode 100644
index 0000000000..8475af3926
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/110-client.mdx
@@ -0,0 +1,67 @@
+---
+title: '`client`: Add methods to Prisma Client'
+metaTitle: 'Prisma Client extensions: client component'
+metaDescription: 'Extend the functionality of Prisma Client, client component'
+tocDepth: 4
+---
+
+
+
+
+
+Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0.
+
+
+
+You can use the `client` [Prisma Client extensions](/orm/prisma-client/client-extensions) component to add top-level methods to Prisma Client.
+
+
+
+## Extend Prisma Client
+
+Use the `$extends` [client-level method](/orm/reference/prisma-client-reference#client-methods) to create an _extended client_. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions. Use the `client` extension component to add top-level methods to Prisma Client.
+
+To add a top-level method to Prisma Client, use the following structure:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ client?: { ... }
+})
+```
+
+### Example
+
+The following example uses the `client` component to add two methods to Prisma Client:
+
+- `$log` outputs a message.
+- `$totalQueries` returns the number of queries executed by the current client instance. It uses the [metrics](/orm/prisma-client/observability-and-logging/metrics) feature to collect this information.
+
+
+
+To use metrics in your project, you must enable the `metrics` feature flag in the `generator` block of your `schema.prisma` file. [Learn more](/orm/prisma-client/observability-and-logging/metrics#step-2-enable-the-feature-flag-in-the-prisma-schema-file).
+
+
+
+```ts
+const prisma = new PrismaClient().$extends({
+ client: {
+ $log: (s: string) => console.log(s),
+ async $totalQueries() {
+ const index_prisma_client_queries_total = 0
+ // Prisma.getExtensionContext(this) in the following block
+ // returns the current client instance
+ const metricsCounters = await (
+ await Prisma.getExtensionContext(this).$metrics.json()
+ ).counters
+
+ return metricsCounters[index_prisma_client_queries_total].value
+ },
+ },
+})
+
+async function main() {
+ prisma.$log('Hello world')
+ const totalQueries = await prisma.$totalQueries()
+ console.log(totalQueries)
+}
+```
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/120-query.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/120-query.mdx
new file mode 100644
index 0000000000..68a12b52ce
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/120-query.mdx
@@ -0,0 +1,299 @@
+---
+title: '`query`: Create custom Prisma Client queries'
+metaTitle: 'Prisma Client extensions: query component'
+metaDescription: 'Extend the functionality of Prisma Client, query component'
+tocDepth: 4
+---
+
+
+
+
+
+Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0.
+
+
+
+You can use the `query` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to hook into the query life-cycle and modify an incoming query or its result.
+
+You can use Prisma Client extensions `query` component to create independent clients. This provides an alternative to [middlewares](/orm/prisma-client/client-extensions/middleware). You can bind one client to a specific filter or user, and another client to another filter or user. For example, you might do this to get [user isolation](/orm/prisma-client/client-extensions#extended-clients) in a row-level security (RLS) extension. In addition, unlike middlewares the `query` extension component gives you end-to-end type safety. [Learn more about `query` extensions versus middlewares](#query-extensions-versus-middlewares).
+
+
+
+## Extend Prisma Client query operations
+
+Use the `$extends` [client-level method](/orm/reference/prisma-client-reference#client-methods) to create an [extended client](/orm/prisma-client/client-extensions#about-prisma-client-extensions). An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions.
+
+Use the `query` extension component to modify queries. You can modify a custom query in the following:
+
+- [A specific operation in a specific model](#modify-a-specific-operation-in-a-specific-model)
+- [A specific operation in all models of your schema](#modify-a-specific-operation-in-all-models-of-your-schema)
+- [All Prisma Client operations](#modify-all-prisma-client-operations)
+- [All operations in a specific model](#modify-all-operations-in-a-specific-model)
+- [All operations in all models of your schema](#modify-all-operations-in-all-models-of-your-schema)
+- [A specific top-level raw query operation](#modify-a-top-level-raw-query-operation)
+
+To create a custom query, use the following structure:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ name?: 'name',
+ query?: {
+ user: { ... } // in this case, we add a query to the `user` model
+ },
+});
+```
+
+The properties are as follows:
+
+- `name`: (optional) specifies a name for the extension that appears in error logs.
+- `query`: defines a custom query.
+
+### Modify a specific operation in a specific model
+
+The `query` object can contain functions that map to the names of the [Prisma Client operations](/orm/reference/prisma-client-reference#model-queries), such as `findUnique`, `findFirst`, `findMany`, `count`, and `create`. The following example modifies `user.findMany` to a use a customized query that finds only users who are older than 18 years:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ query: {
+ user: {
+ async findMany({ model, operation, args, query }) {
+ // take incoming `where` and set `age`
+ args.where = { ...args.where, age: { gt: 18 } }
+
+ return query(args)
+ },
+ },
+ },
+})
+
+await prisma.user.findMany() // returns users whose age is greater than 18
+```
+
+In the above example, a call to `prisma.user.findMany` triggers `query.user.findMany`. Each callback receives a type-safe `{ model, operation, args, query }` object that describes the query. This object has the following properties:
+
+- `model`: the name of the containing model for the query that we want to extend.
+
+ In the above example, the `model` is a string of type `"User"`.
+
+- `operation`: the name of the operation being extended and executed.
+
+ In the above example, the `operation` is a string of type `"findMany"`.
+
+- `args`: the specific query input information to be extended.
+
+ This is a type-safe object that you can mutate before the query happens. You can mutate any of the properties in `args`. Exception: you cannot mutate `include` or `select` because that would change the expected output type and break type safety.
+
+- `query`: a promise for the result of the query.
+
+ - You can use `await` and then mutate the result of this promise, because its value is type-safe. TypeScript catches any unsafe mutations on the object.
+
+### Modify a specific operation in all models of your schema
+
+To extend the queries in all the models of your schema, use `$allModels` instead of a specific model name. For example:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ query: {
+ $allModels: {
+ async findMany({ model, operation, args, query }) {
+ // set `take` and fill with the rest of `args`
+ args = { take: 100, ...args }
+
+ return query(args)
+ },
+ },
+ },
+})
+```
+
+### Modify all operations in a specific model
+
+Use `$allOperations` to extend all operations in a specific model.
+
+For example, the following code applies a custom query to all operations on the `user` model:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ query: {
+ user: {
+ $allOperations({ model, operation, args, query }) {
+ /* your custom logic here */
+ return query(args)
+ },
+ },
+ },
+})
+```
+
+### Modify all Prisma Client operations
+
+Use the `$allOperations` method to modify all query methods present in Prisma Client. The `$allOperations` can be used on both model operations and raw queries.
+
+You can modify all methods as follows:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ query: {
+ $allOperations({ model, operation, args, query }) {
+ /* your custom logic for modifying all Prisma Client operations here */
+ return query(args)
+ },
+ },
+})
+```
+
+In the event a [raw query](/orm/prisma-client/queries/raw-database-access/raw-queries) is invoked, the `model` argument passed to the callback will be `undefined`.
+
+For example, you can use the `$allOperations` method to log queries as follows:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ query: {
+ async $allOperations({ operation, model, args, query }) {
+ const start = performance.now()
+ const result = await query(args)
+ const end = performance.now()
+ const time = end - start
+ console.log(
+ util.inspect(
+ { model, operation, args, time },
+ { showHidden: false, depth: null, colors: true }
+ )
+ )
+ return result
+ },
+ },
+})
+```
+
+### Modify all operations in all models of your schema
+
+Use `$allModels` and `$allOperations` to extend all operations in all models of your schema.
+
+To apply a custom query to all operations on all models of your schema:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ query: {
+ $allModels: {
+ $allOperations({ model, operation, args, query }) {
+ /* your custom logic for modifying all operations on all models here */
+ return query(args)
+ },
+ },
+ },
+})
+```
+
+### Modify a top-level raw query operation
+
+To apply custom behavior to a specific top-level raw query operation, use the name of a top-level raw query function instead of a model name:
+
+
+
+
+```ts copy
+const prisma = new PrismaClient().$extends({
+ query: {
+ $queryRaw({ args, query, operation }) {
+ // handle $queryRaw operation
+ return query(args)
+ },
+ $executeRaw({ args, query, operation }) {
+ // handle $executeRaw operation
+ return query(args)
+ },
+ $queryRawUnsafe({ args, query, operation }) {
+ // handle $queryRawUnsafe operation
+ return query(args)
+ },
+ $executeRawUnsafe({ args, query, operation }) {
+ // handle $executeRawUnsafe operation
+ return query(args)
+ },
+ },
+})
+```
+
+
+
+
+```ts copy
+const prisma = new PrismaClient().$extends({
+ query: {
+ $runCommandRaw({ args, query, operation }) {
+ // handle $runCommandRaw operation
+ return query(args)
+ },
+ },
+})
+```
+
+
+
+
+### Mutate the result of a query
+
+You can use `await` and then mutate the result of the `query` promise.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ query: {
+ user: {
+ async findFirst({ model, operation, args, query }) {
+ const user = await query(args)
+
+ if (user.password !== undefined) {
+ user.password = '******'
+ }
+
+ return user
+ },
+ },
+ },
+})
+```
+
+
+
+We include the above example to show that this is possible. However, for performance reasons we recommend that you use the [`result` component type](/orm/prisma-client/client-extensions/result) to override existing fields. The `result` component type usually gives better performance in this situation because it computes only on access. The `query` component type computes after query execution.
+
+
+
+## Wrap a query into a batch transaction
+
+You can wrap your extended queries into a [batch transaction](/orm/prisma-client/queries/transactions). For example, you can use this to enact row-level security (RLS).
+
+The following example extends `findFirst` so that it runs in a batch transaction.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ query: {
+ user: {
+ // Get the input `args` and a callback to `query`
+ async findFirst({ args, query, operation }) {
+ const [result] = await prisma.$transaction([query(args)]) // wrap the query in a batch transaction, and destructure the result to return an array
+ return result // return the first result found in the array
+ },
+ },
+ },
+})
+```
+
+## Query extensions versus middlewares
+
+You can use query extensions or [middlewares](/orm/prisma-client/client-extensions/middleware) to hook into the query life-cycle and modify an incoming query or its result. Client extensions and middlewares differ in the following ways:
+
+- Middlewares always apply globally to the same client. Client extensions are isolated, unless you deliberately combine them. [Learn more about client extensions](/orm/prisma-client/client-extensions#about-prisma-client-extensions).
+ - For example, in a row-level security (RLS) scenario, you can keep each user in an entirely separate client. With middlewares, all users are active in the same client.
+- During application execution, with extensions you can choose from one or more extended clients, or the standard Prisma Client. With middlewares, you cannot choose which client to use, because there is only one global client.
+- Extensions benefit from end-to-end type safety and inference, but middlewares don't.
+
+You can use Prisma Client extensions in all scenarios where middlewares can be used.
+
+### If you use the `query` extension component and middlewares
+
+If you use the `query` extension component and middlewares in your project, then the following rules and priorities apply:
+
+- In your application code, you must declare all your middlewares on the main Prisma Client instance. You cannot declare them on an extended client.
+- In situations where middlewares and extensions with a `query` component execute, Prisma Client executes the middlewares before it executes the extensions with the `query` component. Prisma Client executes the individual middlewares and extensions in the order in which you instantiated them with `$use` or `$extends`.
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/130-result.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/130-result.mdx
new file mode 100644
index 0000000000..14c7d6e9bc
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/130-result.mdx
@@ -0,0 +1,146 @@
+---
+title: '`result`: Add custom fields and methods to query results'
+metaTitle: 'Prisma Client extensions: result component'
+metaDescription: 'Extend the functionality of Prisma Client, result component'
+tocDepth: 4
+---
+
+
+
+
+
+Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0.
+
+
+
+You can use the `result` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to add custom fields and methods to query results.
+
+
+
+## Add custom fields or methods to query results
+
+Use the `$extends` [client-level method](/orm/reference/prisma-client-reference#client-methods) to create an _extended client_. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions.
+
+Use the `result` extension component to add custom fields and methods to query results.
+
+To add a custom [field](#add-a-custom-field-to-query-results) or [method](#add-a-custom-method-to-the-result-object) to query results, use the following structure. In this example, we add the custom field `myComputedField` to the result of a `user` model query.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ name?: 'name',
+ result?: {
+ user: { // in this case, we extend the `user` model
+ myComputedField: { // the name of the new computed field
+ needs: { ... },
+ compute() { ... }
+ },
+ },
+ },
+});
+```
+
+The parameters are as follows:
+
+- `name`: (optional) specifies a name for the extension that appears in error logs.
+- `result`: defines new fields and methods to the query results.
+- `needs`: an object which describes the dependencies of the result field.
+- `compute`: a method that defines how the virtual field is computed when it is accessed.
+
+### Add a custom field to query results
+
+You can use the `result` extension component to add fields to query results. These fields are computed at runtime and are type-safe.
+
+In the following example, we add a new virtual field called `fullName` to the `user` model.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ result: {
+ user: {
+ fullName: {
+ // the dependencies
+ needs: { firstName: true, lastName: true },
+ compute(user) {
+ // the computation logic
+ return `${user.firstName} ${user.lastName}`
+ },
+ },
+ },
+ },
+})
+
+const user = await prisma.user.findFirst()
+
+// return the user's full name, such as "John Doe"
+console.log(user.fullName)
+```
+
+In above example, the input `user` of `compute` is automatically typed according to the object defined in `needs`. `firstName` and `lastName` are of type `string`, because they are specified in `needs`. If they are not specified in `needs`, then they cannot be accessed.
+
+### Re-use a computed field in another computed field
+
+The following example computes a user's title and full name in a type-safe way. `titleFullName` is a computed field that reuses the `fullName` computed field.
+
+```ts
+const prisma = new PrismaClient()
+ .$extends({
+ result: {
+ user: {
+ fullName: {
+ needs: { firstName: true, lastName: true },
+ compute(user) {
+ return `${user.firstName} ${user.lastName}`
+ },
+ },
+ },
+ },
+ })
+ .$extends({
+ result: {
+ user: {
+ titleFullName: {
+ needs: { title: true, fullName: true },
+ compute(user) {
+ return `${user.title} (${user.fullName})`
+ },
+ },
+ },
+ },
+ })
+```
+
+#### Considerations for fields
+
+- For performance reasons, Prisma Client computes results on access, not on retrieval.
+- You can only create computed fields that are based on scalar fields.
+- You can only use computed fields with `select` and you cannot aggregate them. For example:
+
+ ```ts
+ const user = await prisma.user.findFirst({
+ select: { email: true },
+ })
+ console.log(user.fullName) // undefined
+ ```
+
+### Add a custom method to the result object
+
+You can use the `result` component to add methods to query results. The following example adds a new method, `save` to the result object.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ result: {
+ user: {
+ save: {
+ needs: { id: true },
+ compute(user) {
+ return () =>
+ prisma.user.update({ where: { id: user.id }, data: user })
+ },
+ },
+ },
+ },
+})
+
+const user = await prisma.user.findUniqueOrThrow({ where: { id: someId } })
+user.email = 'mynewmail@mailservice.com'
+await user.save()
+```
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/140-shared-extensions.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/140-shared-extensions.mdx
new file mode 100644
index 0000000000..cd27e58d20
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/140-shared-extensions.mdx
@@ -0,0 +1,143 @@
+---
+title: 'Shared Prisma Client extensions'
+metaTitle: 'Shared Prisma Client extensions'
+metaDescription: 'Share extensions or import shared extensions into your Prisma project'
+tocDepth: 4
+---
+
+
+
+You can share your [Prisma Client extensions](/orm/prisma-client/client-extensions) with other users, either as packages or as modules, and import extensions that other users create into your project.
+
+If you would like to build a shareable extension, we also recommend using the [`prisma-client-extension-starter`](https://github.com/prisma/prisma-client-extension-starter) template.
+
+
+
+## Install a shared, packaged extension
+
+In your project, you can install any Prisma Client extension that another user has published to `npm`. To do so, run the following command:
+
+```terminal
+npm install prisma-extension-
+```
+
+For example, if the package name for an available extension is `prisma-extension-find-or-create`, you could install it as follows:
+
+```terminal
+npm install prisma-extension-find-or-create
+```
+
+To import the `find-or-create` extension from the example above, and wrap your client instance with it, you could use the following code. This example assumes that the extension name is `findOrCreate`.
+
+```ts
+import findOrCreate from 'prisma-extension-find-or-create'
+
+const prisma = new PrismaClient().$extends(findOrCreate)
+const user = await prisma.user.findOrCreate()
+```
+
+When you call a method in an extension, use the constant name from your `$extends` statement, not `prisma`. In the above example,`xprisma.user.findOrCreate` works, but `prisma.user.findOrCreate` does not, because the original `prisma` is not modified.
+
+## Create a shareable extension
+
+When you want to create extensions other users can use, and that are not tailored just for your schema, Prisma provides utilities to allow you to create shareable extensions.
+
+To create a shareable extension:
+
+1. Define the extension as a module using `Prisma.defineExtension`
+2. Use one of the methods that begin with the `$all` prefix such as [`$allModels`](/orm/prisma-client/client-extensions/model#add-a-custom-method-to-all-models-in-your-schema) or [`$allOperations`](/orm/prisma-client/client-extensions/query#modify-all-prisma-client-operations)
+
+### Define an extension
+
+Use the `Prisma.defineExtension` method to make your extension shareable. You can use it to package the extension to either separate your extensions into a separate file or share it with other users as an npm package.
+
+The benefit of `Prisma.defineExtension` is that it provides strict type checks and auto completion for authors of extension in development and users of shared extensions.
+
+### Use a generic method
+
+Extensions that contain methods under `$allModels` apply to every model instead of a specific one. Similarly, methods under `$allOperations` apply to a client instance as a whole and not to a named component, e.g. `result` or `query`.
+
+You do not need to use the `$all` prefix with the [`client`](/orm/prisma-client/client-extensions/client) component, because the `client` component always applies to the client instance.
+
+For example, a generic extension might take the following form:
+
+```ts
+export default Prisma.defineExtension({
+ name: 'prisma-extension-find-or-create', //Extension name
+ model: {
+ $allModels: {
+ // new method
+ findOrCreate(/* args */) {
+ /* code for the new method */
+ return query(args)
+ },
+ },
+ },
+})
+```
+
+Refer to the following pages to learn the different ways you can modify Prisma Client operations:
+
+- [Modify all Prisma Client operations](/orm/prisma-client/client-extensions/query#modify-all-prisma-client-operations)
+- [Modify a specific operation in all models of your schema](/orm/prisma-client/client-extensions/query#modify-a-specific-operation-in-all-models-of-your-schema)
+- [Modify all operations in all models of your schema](/orm/prisma-client/client-extensions/query#modify-all-operations-in-all-models-of-your-schema)
+
+
+ For versions earlier than 4.16.0
+
+The `Prisma` import is available from a different path shown in the snippet below:
+
+```ts
+import { Prisma } from '@prisma/client/scripts/default-index'
+
+export default Prisma.defineExtension({
+ name: 'prisma-extension-',
+})
+```
+
+
+
+### Publishing the shareable extension to npm
+
+You can then share the extension on `npm`. When you choose a package name, we recommend that you use the `prisma-extension-` convention, to make it easier to find and install.
+
+### Call a client-level method from your packaged extension
+
+In the following situations, you need to refer to a Prisma Client instance that your extension wraps:
+
+- When you want to use a [client-level method](/orm/reference/prisma-client-reference#client-methods), such as `$queryRaw`, in your packaged extension.
+- When you want to chain multiple `$extends` calls in your packaged extension.
+
+However, when someone includes your packaged extension in their project, your code cannot know the details of the Prisma Client instance.
+
+You can refer to this client instance as follows:
+
+```ts
+Prisma.defineExtension((client) => {
+ // The Prisma Client instance that the extension user applies the extension to
+ return client.$extends({
+ name: 'prisma-extension-',
+ })
+})
+```
+
+For example:
+
+```ts
+export default Prisma.defineExtension((client) => {
+ return client.$extends({
+ name: 'prisma-extension-find-or-create',
+ query: {
+ $allModels: {
+ async findOrCreate({ args, query, operation }) {
+ return (await client.$transaction([query(args)]))[0]
+ },
+ },
+ },
+ })
+})
+```
+
+### Advanced type safety: type utilities for defining generic extensions
+
+You can improve the type-safety of your shared extensions using [type utilities](/orm/prisma-client/client-extensions/type-utilities).
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/150-type-utilities.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/150-type-utilities.mdx
new file mode 100644
index 0000000000..dbc0c53cef
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/150-type-utilities.mdx
@@ -0,0 +1,101 @@
+---
+title: 'Type utilities'
+metaTitle: 'Prisma Client Extensions: Type utilities'
+metaDescription: 'Advanced type safety: improve type safety in your custom model methods'
+---
+
+
+
+Several type utilities exist within Prisma Client that can assist in the creation of highly type-safe extensions.
+
+
+
+## Type Utilities
+
+[Prisma Client type utilities](/orm/prisma-client/type-safety) are utilities available within your application and Prisma Client extensions and provide useful ways of constructing safe and extendable types for your extension.
+
+The type utilities available are:
+
+- `Exact`: Enforces strict type safety on `Input`. `Exact` makes sure that a generic type `Input` strictly complies with the type that you specify in `Shape`. It [narrows](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) `Input` down to the most precise types.
+- `Args`: Retrieves the input arguments for any given model and operation. This is particularly useful for extension authors who want to do the following:
+ - Re-use existing types to extend or modify them.
+ - Benefit from the same auto-completion experience as on existing operations.
+- `Result`: Takes the input arguments and provides the result for a given model and operation. You would usually use this in conjunction with `Args`. As with `Args`, `Result` helps you to re-use existing types to extend or modify them.
+- `Payload`: Retrieves the entire structure of the result, as scalars and relations objects for a given model and operation. For example, you can use this to determine which keys are scalars or objects at a type level.
+
+The following example creates a new operation, `exists`, based on `findFirst`. It has all of the arguments that `findFirst`.
+
+```ts
+const prisma = new PrismaClient().$extends({
+ model: {
+ $allModels: {
+ // Define a new `exists` operation on all models
+ // T is a generic type that corresponds to the current model
+ async exists(
+ // `this` refers to the current type, e.g. `prisma.user` at runtime
+ this: T,
+
+ // The `exists` function will use the `where` arguments from the current model, `T`, and the `findFirst` operation
+ where: Prisma.Args['where']
+ ): Promise {
+ // Retrieve the current model at runtime
+ const context = Prisma.getExtensionContext(this)
+
+ // Prisma Client query that retrieves data based
+ const result = await (context as any).findFirst({ where })
+ return result !== null
+ },
+ },
+ },
+})
+
+async function main() {
+ const user = await prisma.user.exists({ name: 'Alice' })
+ const post = await prisma.post.exists({
+ OR: [
+ { title: { contains: 'Prisma' } },
+ { content: { contains: 'Prisma' } },
+ ],
+ })
+}
+```
+
+## Add a custom property to a method
+
+The following example illustrates how you can add custom arguments, to a method in an extension:
+
+```ts highlight=16
+type CacheStrategy = {
+ swr: number
+ ttl: number
+}
+
+const prisma = new PrismaClient().$extends({
+ model: {
+ $allModels: {
+ findMany(
+ this: T,
+ args: Prisma.Exact<
+ A,
+ // For the `findMany` method, use the arguments from model `T` and the `findMany` method
+ // and intersect it with `CacheStrategy` as part of `findMany` arguments
+ Prisma.Args & CacheStrategy
+ >
+ ): Prisma.Result {
+ // method implementation with the cache strategy
+ },
+ },
+ },
+})
+
+async function main() {
+ await prisma.post.findMany({
+ cacheStrategy: {
+ ttl: 360,
+ swr: 60,
+ },
+ })
+}
+```
+
+The example here is only conceptual. For the actual caching to work, you will have to implement the logic. If you're interested in a caching extension/ service, we recommend taking a look at [Prisma Accelerate](https://www.prisma.io/data-platform/accelerate).
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/200-extension-examples.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/200-extension-examples.mdx
new file mode 100644
index 0000000000..2312713f0b
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/200-extension-examples.mdx
@@ -0,0 +1,64 @@
+---
+title: 'Shared packages & examples'
+metaTitle: 'Prisma Client extensions | Shared packages & examples'
+metaDescription: 'Explore the Prisma Client extensions that have been built by Prisma and its community'
+---
+
+## Extensions made by Prisma
+
+The following is a list of extensions we've built at Prisma:
+
+| Extension | Description |
+| :------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [`@prisma/extension-accelerate`](https://www.npmjs.com/package/@prisma/extension-accelerate) | Enables [Accelerate](https://www.prisma.io/accelerate), a global database cache available in 300+ locations with built-in connection pooling |
+| [`@prisma/extension-pulse`](https://npmjs.com/package/@prisma/extension-pulse) | Enables [Pulse](https://www.prisma.io/pulse), a service that captures change events from your database and delivers them instantly to your applications. |
+| [`@prisma/extension-read-replicas`](https://github.com/prisma/extension-read-replicas) | Adds read replica support to Prisma Client |
+
+## Extensions made by Prisma's community
+
+The following is a list of extensions created by the community. If you want to create your own package, refer to the [Shared Prisma Client extensions](/orm/prisma-client/client-extensions/shared-extensions) documentation.
+
+| Extension | Description |
+| :--------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------- |
+| [`prisma-extension-supabase-rls`](https://github.com/dthyresson/prisma-extension-supabase-rls) | Adds support for Supabase Row Level Security with Prisma |
+| [`prisma-extension-bark`](https://github.com/adamjkb/bark) | Implements the Materialized Path pattern that allows you to easily create and interact with tree structures in Prisma |
+| [`prisma-cursorstream`](https://github.com/etabits/prisma-cursorstream) | Adds cursor-based streaming |
+| [`prisma-gpt`](https://github.com/aliyeysides/prisma-gpt) | Lets you query your database using natural language |
+| [`prisma-extension-caching`](https://github.com/isaev-the-poetry/prisma-extension-caching) | Transforms SQL data from queries in streams to improve performance in larger datasets |
+| [`prisma-extension-cache-manager`](https://github.com/random42/prisma-extension-cache-manager) | Caches model queries with any [cache-manager](https://www.npmjs.com/package/cache-manager) compatible cache |
+| [`prisma-extension-random`](https://github.com/nkeil/prisma-extension-random) | Lets you query for random rows in your database |
+| [`prisma-paginate`](https://github.com/sandrewTx08/prisma-paginate) | Adds support for paginating read queries |
+
+If you have built an extension and would like to see it featured, feel free to add it to the list by opening a pull request.
+
+## Examples
+
+
+
+The following example extensions are provided as examples only, and without warranty. They are supposed to show how Prisma Client extensions can be created using approaches documented here. We recommend using these examples as a source of inspiration for building your own extensions.
+
+
+
+| Example | Description |
+| :------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------ |
+| [`audit-log-context`](https://github.com/prisma/prisma-client-extensions/tree/main/audit-log-context) | Provides the current user's ID as context to Postgres audit log triggers |
+| [`callback-free-itx`](https://github.com/prisma/prisma-client-extensions/tree/main/callback-free-itx) | Adds a method to start interactive transactions without callbacks |
+| [`computed-fields`](https://github.com/prisma/prisma-client-extensions/tree/main/computed-fields) | Adds virtual / computed fields to result objects |
+| [`input-transformation`](https://github.com/prisma/prisma-client-extensions/tree/main/input-transformation) | Transforms the input arguments passed to Prisma Client queries to filter the result set |
+| [`input-validation`](https://github.com/prisma/prisma-client-extensions/tree/main/input-validation) | Runs custom validation logic on input arguments passed to mutation methods |
+| [`instance-methods`](https://github.com/prisma/prisma-client-extensions/tree/main/instance-methods) | Adds Active Record-like methods like `save()` and `delete()` to result objects |
+| [`json-field-types`](https://github.com/prisma/prisma-client-extensions/tree/main/json-field-types) | Uses strongly-typed runtime parsing for data stored in JSON columns |
+| [`model-filters`](https://github.com/prisma/prisma-client-extensions/tree/main/model-filters) | Adds reusable filters that can composed into complex `where` conditions for a model |
+| [`obfuscated-fields`](https://github.com/prisma/prisma-client-extensions/tree/main/obfuscated-fields) | Prevents sensitive data (e.g. `password` fields) from being included in results |
+| [`query-logging`](https://github.com/prisma/prisma-client-extensions/tree/main/query-logging) | Wraps Prisma Client queries with simple query timing and logging |
+| [`readonly-client`](https://github.com/prisma/prisma-client-extensions/tree/main/readonly-client) | Creates a client that only allows read operations |
+| [`retry-transactions`](https://github.com/prisma/prisma-client-extensions/tree/main/retry-transactions) | Adds a retry mechanism to transactions with exponential backoff and jitter |
+| [`row-level-security`](https://github.com/prisma/prisma-client-extensions/tree/main/row-level-security) | Uses Postgres row-level security policies to isolate data a multi-tenant application |
+| [`static-methods`](https://github.com/prisma/prisma-client-extensions/tree/main/static-methods) | Adds custom query methods to Prisma Client models |
+| [`transformed-fields`](https://github.com/prisma/prisma-client-extensions/tree/main/transformed-fields) | Demonstrates how to use result extensions to transform query results and add i18n to an app |
+| [`exists-method`](https://github.com/prisma/prisma-client-extensions/tree/main/exists-fn) | Demonstrates how to add an `exists` method to all your models |
+| [`update-delete-ignore-not-found `](https://github.com/prisma/prisma-client-extensions/tree/main/update-delete-ignore-not-found) | Demonstrates how to add the `updateIgnoreOnNotFound` and `deleteIgnoreOnNotFound` methods to all your models. |
+
+## Going further
+
+- Learn more about [Prisma Client extensions](/orm/prisma-client/client-extensions).
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/100-soft-delete-middleware.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/100-soft-delete-middleware.mdx
new file mode 100644
index 0000000000..583441ea93
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/100-soft-delete-middleware.mdx
@@ -0,0 +1,669 @@
+---
+title: 'Middleware sample: soft delete'
+metaTitle: 'Middleware sample: soft delete (Reference)'
+metaDescription: 'How to use middleware to intercept deletes and set a field value instead of deleting the record.'
+tocDepth: 4
+---
+
+
+
+The following sample uses [middleware](/orm/prisma-client/client-extensions/middleware) to perform a **soft delete**. Soft delete means that a record is **marked as deleted** by changing a field like `deleted` to `true` rather than actually being removed from the database. Reasons to use a soft delete include:
+
+- Regulatory requirements that mean you have to keep data for a certain amount of time
+- 'Trash' / 'bin' functionality that allows users to restore content that was deleted
+
+
+
+**Note:** This page demonstrates a sample use of middleware. We do not intend the sample to be a fully functional soft delete feature.
+
+
+
+This sample uses the following schema - note the `deleted` field on the `Post` model:
+
+```prisma highlight=28;normal
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ name String?
+ email String @unique
+ posts Post[]
+ followers User[] @relation("UserToUser")
+ user User? @relation("UserToUser", fields: [userId], references: [id])
+ userId Int?
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ content String?
+ user User? @relation(fields: [userId], references: [id])
+ userId Int?
+ tags Tag[]
+ views Int @default(0)
+ deleted Boolean @default(false)
+}
+
+model Category {
+ id Int @id @default(autoincrement())
+ parentCategory Category? @relation("CategoryToCategory", fields: [categoryId], references: [id])
+ category Category[] @relation("CategoryToCategory")
+ categoryId Int?
+}
+
+model Tag {
+ tagName String @id // Must be unique
+ posts Post[]
+}
+```
+
+
+
+## Step 1: Store status of record
+
+Add a field named `deleted` to the `Post` model. You can choose between two field types depending on your requirements:
+
+- `Boolean` with a default value of `false`:
+
+ ```prisma highlight=4;normal
+ model Post {
+ id Int @id @default(autoincrement())
+ ...
+ deleted Boolean @default(false)
+ }
+ ```
+
+- Create a nullable `DateTime` field so that you know exactly _when_ a record was marked as deleted - `NULL` indicates that a record has not been deleted. In some cases, storing when a record was removed may be a regulatory requirement:
+
+ ```prisma highlight=4;normal
+ model Post {
+ id Int @id @default(autoincrement())
+ ...
+ deleted DateTime?
+ }
+ ```
+
+> **Note**: Using two separate fields (`isDeleted` and `deletedDate`) may result in these two fields becoming out of sync - for example, a record may be marked as deleted but have no associated date.)
+
+This sample uses a `Boolean` field type for simplicity.
+
+## Step 2: Soft delete middleware
+
+Add a middleware that performs the following tasks:
+
+- Intercepts `delete` and `deleteMany` queries for the `Post` model
+- Changes the `params.action` to `update` and `updateMany` respectively
+- Introduces a `data` argument and sets `{ deleted: true }`, preserving other filter arguments if they exist
+
+Run the following sample to test the soft delete middleware:
+
+```ts
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient({})
+
+async function main() {
+ /***********************************/
+ /* SOFT DELETE MIDDLEWARE */
+ /***********************************/
+
+ prisma.$use(async (params, next) => {
+ // Check incoming query type
+ if (params.model == 'Post') {
+ if (params.action == 'delete') {
+ // Delete queries
+ // Change action to an update
+ params.action = 'update'
+ params.args['data'] = { deleted: true }
+ }
+ if (params.action == 'deleteMany') {
+ // Delete many queries
+ params.action = 'updateMany'
+ if (params.args.data != undefined) {
+ params.args.data['deleted'] = true
+ } else {
+ params.args['data'] = { deleted: true }
+ }
+ }
+ }
+ return next(params)
+ })
+
+ /***********************************/
+ /* TEST */
+ /***********************************/
+
+ const titles = [
+ { title: 'How to create soft delete middleware' },
+ { title: 'How to install Prisma' },
+ { title: 'How to update a record' },
+ ]
+
+ console.log('\u001b[1;34mSTARTING SOFT DELETE TEST \u001b[0m')
+ console.log('\u001b[1;34m#################################### \u001b[0m')
+
+ let i = 0
+ let posts = new Array()
+
+ // Create 3 new posts with a randomly assigned title each time
+ for (i == 0; i < 3; i++) {
+ const createPostOperation = prisma.post.create({
+ data: titles[Math.floor(Math.random() * titles.length)],
+ })
+ posts.push(createPostOperation)
+ }
+
+ var postsCreated = await prisma.$transaction(posts)
+
+ console.log(
+ 'Posts created with IDs: ' +
+ '\u001b[1;32m' +
+ postsCreated.map((x) => x.id) +
+ '\u001b[0m'
+ )
+
+ // Delete the first post from the array
+ const deletePost = await prisma.post.delete({
+ where: {
+ id: postsCreated[0].id, // Random ID
+ },
+ })
+
+ // Delete the 2nd two posts
+ const deleteManyPosts = await prisma.post.deleteMany({
+ where: {
+ id: {
+ in: [postsCreated[1].id, postsCreated[2].id],
+ },
+ },
+ })
+
+ const getPosts = await prisma.post.findMany({
+ where: {
+ id: {
+ in: postsCreated.map((x) => x.id),
+ },
+ },
+ })
+
+ console.log()
+
+ console.log(
+ 'Deleted post with ID: ' + '\u001b[1;32m' + deletePost.id + '\u001b[0m'
+ )
+ console.log(
+ 'Deleted posts with IDs: ' +
+ '\u001b[1;32m' +
+ [postsCreated[1].id + ',' + postsCreated[2].id] +
+ '\u001b[0m'
+ )
+ console.log()
+ console.log(
+ 'Are the posts still available?: ' +
+ (getPosts.length == 3
+ ? '\u001b[1;32m' + 'Yes!' + '\u001b[0m'
+ : '\u001b[1;31m' + 'No!' + '\u001b[0m')
+ )
+ console.log()
+ console.log('\u001b[1;34m#################################### \u001b[0m')
+ // 4. Count ALL posts
+ const f = await prisma.post.findMany({})
+ console.log('Number of posts: ' + '\u001b[1;32m' + f.length + '\u001b[0m')
+
+ // 5. Count DELETED posts
+ const r = await prisma.post.findMany({
+ where: {
+ deleted: true,
+ },
+ })
+ console.log(
+ 'Number of SOFT deleted posts: ' + '\u001b[1;32m' + r.length + '\u001b[0m'
+ )
+}
+
+main()
+```
+
+The sample outputs the following:
+
+```no-lines
+STARTING SOFT DELETE TEST
+####################################
+Posts created with IDs: 587,588,589
+
+Deleted post with ID: 587
+Deleted posts with IDs: 588,589
+
+Are the posts still available?: Yes!
+
+####################################
+```
+
+:::tip
+
+Comment out the middleware to see the message change.
+
+:::
+
+✔ Pros of this approach to soft delete include:
+
+- Soft delete happens at data access level, which means that you cannot delete records unless you use raw SQL
+
+✘ Cons of this approach to soft delete include:
+
+- Content can still be read and updated unless you explicitly filter by `where: { deleted: false }` - in a large project with a lot of queries, there is a risk that soft deleted content will still be displayed
+- You can still use raw SQL to delete records
+
+:::tip
+
+You can create rules or triggers ([MySQL](https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html) and [PostgreSQL](https://www.postgresql.org/docs/8.1/rules-update.html)) at a database level to prevent records from being deleted.
+
+:::
+
+## Step 3: Optionally prevent read/update of soft deleted records
+
+In step 2, we implemented middleware that prevents `Post` records from being deleted. However, you can still read and update deleted records. This step explores two ways to prevent the reading and updating of deleted records.
+
+> **Note**: These options are just ideas with pros and cons, you may choose to do something entirely different.
+
+### Option 1: Implement filters in your own application code
+
+In this option:
+
+- Prisma middleware is responsible for preventing records from being deleted
+- Your own application code (which could be a GraphQL API, a REST API, a module) is responsible for filtering out deleted posts where necessary (`{ where: { deleted: false } }`) when reading and updating data - for example, the `getPost` GraphQL resolver never returns a deleted post
+
+✔ Pros of this approach to soft delete include:
+
+- No change to Prisma's create/update queries - you can easily request deleted records if you need them
+- Modifying queries in middleware can have some unintended consequences, such as changing query return types (see option 2)
+
+✘ Cons of this approach to soft delete include:
+
+- Logic relating to soft delete maintained in two different places
+- If your API surface is very large and maintained by multiple contributors, it may be difficult to enforce certain business rules (for example, never allow deleted records to be updated)
+
+### Option 2: Use middleware to determine the behavior of read/update queries for deleted records
+
+Option two uses Prisma middleware to prevent soft deleted records from being returned. The following table describes how the middleware affects each query:
+
+| **Query** | **Middleware logic** | **Changes to return type** |
+| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------- | --- |
+| `findUnique` | 🔧 Change query to `findFirst` (because you cannot apply `deleted: false` filters to `findUnique`) 🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts 🔧 From version 5.0.0, you can use `findUnique` to apply `delete: false` filters since [non unique fields are exposed](/orm/reference/prisma-client-reference#filter-on-non-unique-fields-with-userwhereuniqueinput). | No change | |
+| `findMany` | 🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts by default 🔧 Allow developers to **explicitly request** soft deleted posts by specifying `deleted: true` | No change |
+| `update` | 🔧 Change query to `updateMany` (because you cannot apply `deleted: false` filters to `update`) 🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts | `{ count: n }` instead of `Post` |
+| `updateMany` | 🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts | No change |
+
+- **Is it not possible to utilize soft delete with `findFirstOrThrow` or `findUniqueOrThrow`?**
+ From version [5.1.0](https://github.com/prisma/prisma/releases/5.1.0), you can apply soft delete `findFirstOrThrow` or `findUniqueOrThrow` by using middleware.
+- **Why are you making it possible to use `findMany` with a `{ where: { deleted: true } }` filter, but not `updateMany`?**
+ This particular sample was written to support the scenario where a user can _restore_ their deleted blog post (which requires a list of soft deleted posts) - but the user should not be able to edit a deleted post.
+- **Can I still `connect` or `connectOrCreate` a deleted post?**
+ In this sample - yes. The middleware does not prevent you from connecting an existing, soft deleted post to a user.
+
+Run the following sample to see how middleware affects each query:
+
+```ts
+import { PrismaClient, Prisma } from '@prisma/client'
+
+const prisma = new PrismaClient({})
+
+async function main() {
+ /***********************************/
+ /* SOFT DELETE MIDDLEWARE */
+ /***********************************/
+
+ prisma.$use(async (params, next) => {
+ if (params.model == 'Post') {
+ if (params.action === 'findUnique' || params.action === 'findFirst') {
+ // Change to findFirst - you cannot filter
+ // by anything except ID / unique with findUnique
+ params.action = 'findFirst'
+ // Add 'deleted' filter
+ // ID filter maintained
+ params.args.where['deleted'] = false
+ }
+ if (
+ params.action === 'findFirstOrThrow' ||
+ params.action === 'findUniqueOrThrow'
+ ) {
+ if (params.args.where) {
+ if (params.args.where.deleted == undefined) {
+ // Exclude deleted records if they have not been explicitly requested
+ params.args.where['deleted'] = false
+ }
+ } else {
+ params.args['where'] = { deleted: false }
+ }
+ }
+ if (params.action === 'findMany') {
+ // Find many queries
+ if (params.args.where) {
+ if (params.args.where.deleted == undefined) {
+ params.args.where['deleted'] = false
+ }
+ } else {
+ params.args['where'] = { deleted: false }
+ }
+ }
+ }
+ return next(params)
+ })
+
+ prisma.$use(async (params, next) => {
+ if (params.model == 'Post') {
+ if (params.action == 'update') {
+ // Change to updateMany - you cannot filter
+ // by anything except ID / unique with findUnique
+ params.action = 'updateMany'
+ // Add 'deleted' filter
+ // ID filter maintained
+ params.args.where['deleted'] = false
+ }
+ if (params.action == 'updateMany') {
+ if (params.args.where != undefined) {
+ params.args.where['deleted'] = false
+ } else {
+ params.args['where'] = { deleted: false }
+ }
+ }
+ }
+ return next(params)
+ })
+
+ prisma.$use(async (params, next) => {
+ // Check incoming query type
+ if (params.model == 'Post') {
+ if (params.action == 'delete') {
+ // Delete queries
+ // Change action to an update
+ params.action = 'update'
+ params.args['data'] = { deleted: true }
+ }
+ if (params.action == 'deleteMany') {
+ // Delete many queries
+ params.action = 'updateMany'
+ if (params.args.data != undefined) {
+ params.args.data['deleted'] = true
+ } else {
+ params.args['data'] = { deleted: true }
+ }
+ }
+ }
+ return next(params)
+ })
+
+ /***********************************/
+ /* TEST */
+ /***********************************/
+
+ const titles = [
+ { title: 'How to create soft delete middleware' },
+ { title: 'How to install Prisma' },
+ { title: 'How to update a record' },
+ ]
+
+ console.log('\u001b[1;34mSTARTING SOFT DELETE TEST \u001b[0m')
+ console.log('\u001b[1;34m#################################### \u001b[0m')
+
+ let i = 0
+ let posts = new Array()
+
+ // Create 3 new posts with a randomly assigned title each time
+ for (i == 0; i < 3; i++) {
+ const createPostOperation = prisma.post.create({
+ data: titles[Math.floor(Math.random() * titles.length)],
+ })
+ posts.push(createPostOperation)
+ }
+
+ var postsCreated = await prisma.$transaction(posts)
+
+ console.log(
+ 'Posts created with IDs: ' +
+ '\u001b[1;32m' +
+ postsCreated.map((x) => x.id) +
+ '\u001b[0m'
+ )
+
+ // Delete the first post from the array
+ const deletePost = await prisma.post.delete({
+ where: {
+ id: postsCreated[0].id, // Random ID
+ },
+ })
+
+ // Delete the 2nd two posts
+ const deleteManyPosts = await prisma.post.deleteMany({
+ where: {
+ id: {
+ in: [postsCreated[1].id, postsCreated[2].id],
+ },
+ },
+ })
+
+ const getOnePost = await prisma.post.findUnique({
+ where: {
+ id: postsCreated[0].id,
+ },
+ })
+
+ const getOneUniquePostOrThrow = async () =>
+ await prisma.post.findUniqueOrThrow({
+ where: {
+ id: postsCreated[0].id,
+ },
+ })
+
+ const getOneFirstPostOrThrow = async () =>
+ await prisma.post.findFirstOrThrow({
+ where: {
+ id: postsCreated[0].id,
+ },
+ })
+
+ const getPosts = await prisma.post.findMany({
+ where: {
+ id: {
+ in: postsCreated.map((x) => x.id),
+ },
+ },
+ })
+
+ const getPostsAnDeletedPosts = await prisma.post.findMany({
+ where: {
+ id: {
+ in: postsCreated.map((x) => x.id),
+ },
+ deleted: true,
+ },
+ })
+
+ const updatePost = await prisma.post.update({
+ where: {
+ id: postsCreated[1].id,
+ },
+ data: {
+ title: 'This is an updated title (update)',
+ },
+ })
+
+ const updateManyDeletedPosts = await prisma.post.updateMany({
+ where: {
+ deleted: true,
+ id: {
+ in: postsCreated.map((x) => x.id),
+ },
+ },
+ data: {
+ title: 'This is an updated title (updateMany)',
+ },
+ })
+
+ console.log()
+
+ console.log(
+ 'Deleted post (delete) with ID: ' +
+ '\u001b[1;32m' +
+ deletePost.id +
+ '\u001b[0m'
+ )
+ console.log(
+ 'Deleted posts (deleteMany) with IDs: ' +
+ '\u001b[1;32m' +
+ [postsCreated[1].id + ',' + postsCreated[2].id] +
+ '\u001b[0m'
+ )
+ console.log()
+ console.log(
+ 'findUnique: ' +
+ (getOnePost?.id != undefined
+ ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m'
+ : '\u001b[1;31m' +
+ 'Post not returned!' +
+ '(Value is: ' +
+ JSON.stringify(getOnePost) +
+ ')' +
+ '\u001b[0m')
+ )
+ try {
+ console.log('findUniqueOrThrow: ')
+ await getOneUniquePostOrThrow()
+ } catch (error) {
+ if (
+ error instanceof Prisma.PrismaClientKnownRequestError &&
+ error.code == 'P2025'
+ )
+ console.log(
+ '\u001b[1;31m' +
+ 'PrismaClientKnownRequestError is catched' +
+ '(Error name: ' +
+ error.name +
+ ')' +
+ '\u001b[0m'
+ )
+ }
+ try {
+ console.log('findFirstOrThrow: ')
+ await getOneFirstPostOrThrow()
+ } catch (error) {
+ if (
+ error instanceof Prisma.PrismaClientKnownRequestError &&
+ error.code == 'P2025'
+ )
+ console.log(
+ '\u001b[1;31m' +
+ 'PrismaClientKnownRequestError is catched' +
+ '(Error name: ' +
+ error.name +
+ ')' +
+ '\u001b[0m'
+ )
+ }
+ console.log()
+ console.log(
+ 'findMany: ' +
+ (getPosts.length == 3
+ ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m'
+ : '\u001b[1;31m' + 'Posts not returned!' + '\u001b[0m')
+ )
+ console.log(
+ 'findMany ( delete: true ): ' +
+ (getPostsAnDeletedPosts.length == 3
+ ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m'
+ : '\u001b[1;31m' + 'Posts not returned!' + '\u001b[0m')
+ )
+ console.log()
+ console.log(
+ 'update: ' +
+ (updatePost.id != undefined
+ ? '\u001b[1;32m' + 'Post updated!' + '\u001b[0m'
+ : '\u001b[1;31m' +
+ 'Post not updated!' +
+ '(Value is: ' +
+ JSON.stringify(updatePost) +
+ ')' +
+ '\u001b[0m')
+ )
+ console.log(
+ 'updateMany ( delete: true ): ' +
+ (updateManyDeletedPosts.count == 3
+ ? '\u001b[1;32m' + 'Posts updated!' + '\u001b[0m'
+ : '\u001b[1;31m' + 'Posts not updated!' + '\u001b[0m')
+ )
+ console.log()
+ console.log('\u001b[1;34m#################################### \u001b[0m')
+ // 4. Count ALL posts
+ const f = await prisma.post.findMany({})
+ console.log(
+ 'Number of active posts: ' + '\u001b[1;32m' + f.length + '\u001b[0m'
+ )
+
+ // 5. Count DELETED posts
+ const r = await prisma.post.findMany({
+ where: {
+ deleted: true,
+ },
+ })
+ console.log(
+ 'Number of SOFT deleted posts: ' + '\u001b[1;32m' + r.length + '\u001b[0m'
+ )
+}
+
+main()
+```
+
+The sample outputs the following:
+
+```
+STARTING SOFT DELETE TEST
+####################################
+Posts created with IDs: 680,681,682
+
+Deleted post (delete) with ID: 680
+Deleted posts (deleteMany) with IDs: 681,682
+
+findUnique: Post not returned!(Value is: [])
+findMany: Posts not returned!
+findMany ( delete: true ): Posts returned!
+
+update: Post not updated!(Value is: {"count":0})
+updateMany ( delete: true ): Posts not updated!
+
+####################################
+Number of active posts: 0
+Number of SOFT deleted posts: 95
+```
+
+✔ Pros of this approach:
+
+- A developer can make a conscious choice to include deleted records in `findMany`
+- You cannot accidentally read or update a deleted record
+
+✖ Cons of this approach:
+
+- Not obvious from API that you aren't getting all records and that `{ where: { deleted: false } }` is part of the default query
+- Return type `update` affected because middleware changes the query to `updateMany`
+- Doesn't handle complex queries with `AND`, `OR`, `every`, etc...
+- Doesn't handle filtering when using `include` from another model.
+
+## FAQ
+
+### Can I add a global `includeDeleted` to the `Post` model?
+
+You may be tempted to 'hack' your API by adding a `includeDeleted` property to the `Post` model and make the following query possible:
+
+```ts
+prisma.post.findMany({ where: { includeDeleted: true } })
+```
+
+> **Note**: You would still need to write middleware.
+
+We **✘ do not** recommend this approach as it pollutes the schema with fields that do not represent real data.
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/200-logging-middleware.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/200-logging-middleware.mdx
new file mode 100644
index 0000000000..fbf2da4f85
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/200-logging-middleware.mdx
@@ -0,0 +1,90 @@
+---
+title: 'Middleware sample: logging'
+metaTitle: 'Middleware sample: logging (Reference)'
+metaDescription: 'How to use middleware to log the time taken to perform any query.'
+---
+
+
+
+The following example logs the time taken for a Prisma Query to run:
+
+```ts
+const prisma = new PrismaClient()
+
+prisma.$use(async (params, next) => {
+ const before = Date.now()
+
+ const result = await next(params)
+
+ const after = Date.now()
+
+ console.log(`Query ${params.model}.${params.action} took ${after - before}ms`)
+
+ return result
+})
+
+const create = await prisma.post.create({
+ data: {
+ title: 'Welcome to Prisma Day 2020',
+ },
+})
+
+const createAgain = await prisma.post.create({
+ data: {
+ title: 'All about database collation',
+ },
+})
+```
+
+Example output:
+
+```no-lines
+Query Post.create took 92ms
+Query Post.create took 15ms
+```
+
+The example is based on the following sample schema:
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "mysql"
+ url = env("DATABASE_URL")
+}
+
+model Post {
+ authorId Int?
+ content String?
+ id Int @id @default(autoincrement())
+ published Boolean @default(false)
+ title String
+ user User? @relation(fields: [authorId], references: [id])
+ language String?
+
+ @@index([authorId], name: "authorId")
+}
+
+model User {
+ email String @unique
+ id Int @id @default(autoincrement())
+ name String?
+ posts Post[]
+ extendedProfile Json?
+ role Role @default(USER)
+}
+
+enum Role {
+ ADMIN
+ USER
+ MODERATOR
+}
+```
+
+
+
+## Going further
+
+You can also use [Prisma Client extensions](/orm/prisma-client/client-extensions) to log the time it takes to perform a query. A functional example can be found in [this GitHub repository](https://github.com/prisma/prisma-client-extensions/tree/main/query-logging).
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/300-session-data-middleware.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/300-session-data-middleware.mdx
new file mode 100644
index 0000000000..bd70ecdb2e
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/300-session-data-middleware.mdx
@@ -0,0 +1,71 @@
+---
+title: 'Middleware sample: session data'
+metaTitle: 'Middleware sample: session data (Reference)'
+metaDescription: 'How to use middleware to set the value taken from session state.'
+---
+
+
+
+The following example sets the `language` field of each `Post` to the context language (taken, for example, from session state):
+
+```ts
+const prisma = new PrismaClient()
+
+const contextLanguage = 'en-us' // Session state
+
+prisma.$use(async (params, next) => {
+ if (params.model == 'Post' && params.action == 'create') {
+ params.args.data.language = contextLanguage
+ }
+
+ return next(params)
+})
+
+const create = await prisma.post.create({
+ data: {
+ title: 'My post in English',
+ },
+})
+```
+
+The example is based on the following sample schema:
+
+```prisma
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "mysql"
+ url = env("DATABASE_URL")
+}
+
+model Post {
+ authorId Int?
+ content String?
+ id Int @id @default(autoincrement())
+ published Boolean @default(false)
+ title String
+ user User? @relation(fields: [authorId], references: [id])
+ language String?
+
+ @@index([authorId], name: "authorId")
+}
+
+model User {
+ email String @unique
+ id Int @id @default(autoincrement())
+ name String?
+ posts Post[]
+ extendedProfile Json?
+ role Role @default(USER)
+}
+
+enum Role {
+ ADMIN
+ USER
+ MODERATOR
+}
+```
+
+
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/index.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/index.mdx
new file mode 100644
index 0000000000..002d7b531e
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/500-middleware/index.mdx
@@ -0,0 +1,187 @@
+---
+title: 'Middleware'
+metaTitle: 'Middleware (Reference)'
+metaDescription: 'Prisma Client middleware allows you to perform actions before or after any query on any model with the prisma.$use method.'
+---
+
+
+
+
+
+**Deprecated**: Middleware is deprecated in version 4.16.0.
+
+We recommend using the [Prisma Client extensions `query` component type](/orm/prisma-client/client-extensions/query) as an alternative to middleware. Prisma Client extensions were first introduced into Preview in version 4.7.0 and made Generally Available in 4.16.0.
+
+Prisma Client extensions allow you to create independent Prisma Client instances and bind each client to a specific filter or user. For example, you could bind clients to specific users to provide user isolation. Prisma Client extensions also provide end-to-end type safety.
+
+
+
+Middlewares act as query-level lifecycle hooks, which allow you to perform an action before or after a query runs. Use the [`prisma.$use`](/orm/reference/prisma-client-reference#use) method to add middleware, as follows:
+
+```ts highlight=4-9,12-17;normal
+const prisma = new PrismaClient()
+
+// Middleware 1
+prisma.$use(async (params, next) => {
+ // Manipulate params here
+ const result = await next(params)
+ // See results here
+ return result
+})
+
+// Middleware 2
+prisma.$use(async (params, next) => {
+ // Manipulate params here
+ const result = await next(params)
+ // See results here
+ return result
+})
+
+// Queries here
+```
+
+
+
+Do not invoke `next` multiple times within a middleware when using [batch transactions](/orm/prisma-client/queries/transactions#sequential-prisma-client-operations). This will cause you to break out of the transaction and lead to unexpected results.
+
+
+
+[`params`](/orm/reference/prisma-client-reference#params) represent parameters available in the middleware, such as the name of the query, and [`next`](/orm/reference/prisma-client-reference#next) represents [the next middleware in the stack _or_ the original Prisma Client query](#running-order-and-the-middleware-stack).
+
+Possible use cases for middleware include:
+
+- Setting or overwriting a field value - for example, [setting the context language of a blog post comment](session-data-middleware)
+- Validating input data - for example, check user input for inappropriate language via an external service
+- Intercept a `delete` query and change it to an `update` in order to perform a [soft delete](soft-delete-middleware)
+- [Log the time taken to perform a query](logging-middleware)
+
+There are many more use cases for middleware - this list serves as inspiration for the types of problems that middleware is designed to address.
+
+
+
+## Samples
+
+The following sample scenarios show how to use middleware in practice:
+
+
+
+## Where to add middleware
+
+Add Prisma middleware **outside the context of the request handler**, otherwise each request adds a new _instance_ of the middleware to the stack. The following example demonstrates where to add Prisma middleware in the context of an Express app:
+
+```ts highlight=6-11;normal
+import express from 'express'
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+prisma.$use(async (params, next) => {
+ // Manipulate params here
+ const result = await next(params)
+ // See results here
+ return result
+})
+
+const app = express()
+app.get('/feed', async (req, res) => {
+ // NO MIDDLEWARE HERE
+ const posts = await prisma.post.findMany({
+ where: { published: true },
+ include: { author: true },
+ })
+ res.json(posts)
+})
+```
+
+## Running order and the middleware stack
+
+If you have multiple middlewares, the running order for **each separate query** is:
+
+1. All logic **before** `await next(params)` in each middleware, in descending order
+2. All logic **after** `await next(params)` in each middleware, in ascending order
+
+Depending on where you are in the stack, `await next(params)` either:
+
+- Runs the next middleware (in middlewares #1 and #2 in the example) _or_
+- Runs the original Prisma Client query (in middleware #3)
+
+```ts
+const prisma = new PrismaClient()
+
+// Middleware 1
+prisma.$use(async (params, next) => {
+ console.log(params.args.data.title)
+ console.log('1')
+ const result = await next(params)
+ console.log('6')
+ return result
+})
+
+// Middleware 2
+prisma.$use(async (params, next) => {
+ console.log('2')
+ const result = await next(params)
+ console.log('5')
+ return result
+})
+
+// Middleware 3
+prisma.$use(async (params, next) => {
+ console.log('3')
+ const result = await next(params)
+ console.log('4')
+ return result
+})
+
+const create = await prisma.post.create({
+ data: {
+ title: 'Welcome to Prisma Day 2020',
+ },
+})
+
+const create2 = await prisma.post.create({
+ data: {
+ title: 'How to Prisma!',
+ },
+})
+```
+
+Output:
+
+```no-lines
+Welcome to Prisma Day 2020
+1
+2
+3
+4
+5
+6
+How to Prisma!
+1
+2
+3
+4
+5
+6
+```
+
+## Performance and appropriate use cases
+
+Middleware executes for **every** query, which means that overuse has the potential to negatively impact performance. To avoid adding performance overheads:
+
+- Check the `params.model` and `params.action` properties early in your middleware to avoid running logic unnecessarily:
+
+ ```ts
+ prisma.$use(async (params, next) => {
+ if (params.model == 'Post' && params.action == 'delete') {
+ // Logic only runs for delete action and Post model
+ }
+ return next(params)
+ })
+ ```
+
+- Consider whether middleware is the appropriate solution for your scenario. For example:
+
+ - If you need to populate a field, can you use the [`@default`](/orm/reference/prisma-schema-reference#default) attribute?
+ - If you need to set the value of a `DateTime` field, can you use the `now()` function or the `@updatedAt` attribute?
+ - If you need to perform more complex validation, can you use a `CHECK` constraint in the database itself?
diff --git a/docs/200-orm/200-prisma-client/300-client-extensions/index.mdx b/docs/200-orm/200-prisma-client/300-client-extensions/index.mdx
new file mode 100644
index 0000000000..2b10696724
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/300-client-extensions/index.mdx
@@ -0,0 +1,231 @@
+---
+title: 'Extensions'
+metaTitle: 'Prisma Client extensions'
+metaDescription: 'Extend the functionality of Prisma Client'
+tocDepth: 4
+---
+
+
+
+
+
+Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0.
+
+
+
+You can use Prisma Client extensions to add functionality to your models, result objects, and queries, or to add client-level methods.
+
+You can create an extension with one or more of the following component types:
+
+- `model`: [add custom methods or fields to your models](/orm/prisma-client/client-extensions/model)
+- `client`: [add client-level methods to Prisma Client](/orm/prisma-client/client-extensions/client)
+- `query`: [create custom Prisma Client queries](/orm/prisma-client/client-extensions/query)
+- `result`: [add custom fields to your query results](/orm/prisma-client/client-extensions/result)
+
+For example, you might create an extension that uses the `model` and `client` component types.
+
+
+
+## About Prisma Client extensions
+
+When you use a Prisma Client extension, you create an _extended client_. An extended client is a lightweight variant of the standard Prisma Client that is wrapped by one or more extensions. The standard client is not mutated. You can add as many extended clients as you want to your project. [Learn more about extended clients](#extended-clients).
+
+You can associate a single extension, or multiple extensions, with an extended client. [Learn more about multiple extensions](#multiple-extensions).
+
+You can [share your Prisma Client extensions](/orm/prisma-client/client-extensions/shared-extensions) with other Prisma users, and [import Prisma Client extensions developed by other users](/orm/prisma-client/client-extensions/shared-extensions#install-a-shared-packaged-extension) into your Prisma project.
+
+### Extended clients
+
+Extended clients interact with each other, and with the standard client, as follows:
+
+- Each extended client operates independently in an isolated instance.
+- Extended clients cannot conflict with each other, or with the standard client.
+- All extended clients and the standard client communicate with the same [Prisma query engine](/orm/more/under-the-hood/engines).
+- All extended clients and the standard client share the same connection pool.
+
+> **Note**: The author of an extension can modify this behavior since they're able to run arbitrary code as part of an extension. For example, an extension might actually create an entirely new `PrismaClient` instance (including its own query engine and connection pool). Be sure to check the documentation of the extension you're using to learn about any specific behavior it might implement.
+
+### Example use cases for extended clients
+
+Because extended clients operate in isolated instances, they can be a good way to do the following, for example:
+
+- Implement row-level security (RLS), where each HTTP request has its own client with its own RLS extension, customized with session data. This can keep each user entirely separate, each in a separate client.
+- Add a `user.current()` method for the `User` model to get the currently logged-in user.
+- Enable more verbose logging for requests if a debug cookie is set.
+- Attach a unique request id to all logs so that you can correlate them later, for example to help you analyze the operations that Prisma Client carries out.
+- Remove a `delete` method from models unless the application calls the admin endpoint and the user has the necessary privileges.
+
+## Add an extension to Prisma Client
+
+You can create an extension using two primary ways:
+
+- Use the client-level [`$extends`](/orm/reference/prisma-client-reference#client-methods) method
+
+ ```ts
+ const xprisma = prisma.$extends({
+ name: 'signUp', // Optional: name appears in error logs
+ model: { // This is a `model` component
+ user: { ... } // The extension logic for the `user` model goes inside the curly braces
+ },
+ })
+ ```
+
+- Use the `Prisma.defineExtension` method to define an extension and assign it to a variable, and then pass the extension to the client-level `$extends` method
+
+ ```ts
+ import { Prisma } from '@prisma/client'
+
+ // Define the extension
+ const myExtension = Prisma.defineExtension({
+ name: 'signUp', // Optional: name appears in error logs
+ model: { // This is a `model` component
+ user: { ... } // The extension logic for the `user` model goes inside the curly braces
+ },
+ })
+
+ // Pass the extension to a Prisma Client instance
+ const xprisma = prisma.$extends(myExtension)
+ ```
+
+ :::tip
+
+ This pattern is useful for when you would like to separate extensions into multiple files or directories within a project.
+
+ :::
+
+The above examples use the [`model` extension component](/orm/prisma-client/client-extensions/model) to extend the `User` model.
+
+In your `$extends` method, use the appropriate extension component or components ([`model`](/orm/prisma-client/client-extensions/model), [`client`](/orm/prisma-client/client-extensions/client), [`result`](/orm/prisma-client/client-extensions/result) or [`query`](/orm/prisma-client/client-extensions/query)).
+
+## Name an extension for error logs
+
+You can name your extensions to help identify them in error logs. To do so, use the optional field `name`. For example:
+
+```ts
+const prisma = new PrismaClient().$extends({
+ name: `signUp`, // (Optional) Extension name
+ model: {
+ user: { ... }
+ },
+})
+```
+
+## Multiple extensions
+
+You can associate an extension with an [extended client](#about-prisma-client-extensions) in one of two ways:
+
+- You can associate it with an extended client on its own, or
+- You can combine the extension with other extensions and associate all of these extensions with an extended client. The functionality from these combined extensions applies to the same extended client.
+ Note: [Combined extensions can conflict](#conflicts-in-combined-extensions).
+
+You can combine the two approaches above. For example, you might associate one extension with its own extended client and associate two other extensions with another extended client. [Learn more about how client instances interact](#extended-clients).
+
+### Apply multiple extensions to an extended client
+
+In the following example, suppose that you have two extensions, `extensionA` and `extensionB`. There are two ways to combine these.
+
+#### Option 1: Declare the new client in one line
+
+With this option, you apply both extensions to a new client in one line of code.
+
+```ts
+// First of all, store your original Prisma Client in a variable as usual
+const prisma = new PrismaClient()
+
+// Declare an extended client that has an extensionA and extensionB
+const prismaAB = prisma.$extends(extensionA).$extends(extensionB)
+```
+
+You can then refer to `prismaAB` in your code, for example `prismaAB.myExtensionMethod()`.
+
+#### Option 2: Declare multiple extended clients
+
+The advantage of this option is that you can call any of the extended clients separately.
+
+```ts
+// First of all, store your original Prisma Client in a variable as usual
+const prisma = new PrismaClient()
+
+// Declare an extended client that has extensionA applied
+const prismaA = prisma.$extends(extensionA)
+
+// Declare an extended client that has extensionB applied
+const prismaB = prisma.$extends(extensionB)
+
+// Declare an extended client that is a combination of clientA and clientB
+const prismaAB = prismaA.$extends(extensionB)
+```
+
+In your code, you can call any of these clients separately, for example `prismaA.myExtensionMethod()`, `prismaB.myExtensionMethod()`, or `prismaAB.myExtensionMethod()`.
+
+### Conflicts in combined extensions
+
+When you combine two or more extensions into a single extended client, then the _last_ extension that you declare takes precedence in any conflict. In the example in option 1 above, suppose there is a method called `myExtensionMethod()` defined in `extensionA` and a method called `myExtensionMethod()` in `extensionB`. When you call `prismaAB.myExtensionMethod()`, then Prisma Client uses `myExtensionMethod()` as defined in `extensionB`.
+
+## Type of an extended client
+
+You can infer the type of an extended Prisma Client instance using the [`typeof`](https://www.typescriptlang.org/docs/handbook/2/typeof-types.html) utility as follows:
+
+```ts
+const extendedPrismaClient = new PrismaClient().$extends({
+ /** extension */
+})
+
+type ExtendedPrismaClient = typeof extendedPrismaClient
+```
+
+If you're using Prisma Client as a singleton, you can get the type of the extended Prisma Client instance using the `typeof` and [`ReturnType`](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype) utilities as follows:
+
+```ts
+function getExtendedClient() {
+ return new PrismaClient().$extends({
+ /* extension */
+ })
+}
+
+type ExtendedPrismaClient = ReturnType
+```
+
+## Limitations
+
+### Usage of `$on` and `$use` with extended clients
+
+`$on` and `$use` are not available in extended clients. If you would like to continue using these [client-level methods](/orm/reference/prisma-client-reference#client-methods) with an extended client, you will need to hook them up before extending the client.
+
+```ts
+const prisma = new PrismaClient()
+
+prisma.$use(async (params, next) => {
+ console.log('This is middleware!')
+ return next(params)
+})
+
+const xPrisma = prisma.$extends({
+ name: 'myExtension',
+ model: {
+ user: {
+ async signUp(email: string) {
+ await prisma.user.create({ data: { email } })
+ },
+ },
+ },
+})
+```
+
+To learn more, see our documentation on [`$on`](/orm/reference/prisma-client-reference#on) and [`$use`](/orm/reference/prisma-client-reference#use)
+
+### Usage of client-level methods in extended clients
+
+[Client-level methods](/orm/reference/prisma-client-reference#client-methods) do not necessarily exist on extended clients. For these clients you will need to first check for existence before using.
+
+```ts
+const xPrisma = prisma.$extends(...);
+
+if (xPrisma.$connect) {
+ xPrisma.$connect()
+}
+```
+
+### Usage with nested operations
+
+The `query` extension type does not support nested read and write operations.
diff --git a/docs/200-orm/200-prisma-client/400-type-safety/050-prisma-validator.mdx b/docs/200-orm/200-prisma-client/400-type-safety/050-prisma-validator.mdx
new file mode 100644
index 0000000000..8a65adfd0d
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/400-type-safety/050-prisma-validator.mdx
@@ -0,0 +1,153 @@
+---
+title: 'Prisma validator'
+metaTitle: 'Prisma validator'
+metaDescription: 'The Prisma validator is a utility function that takes a generated type and returns a type-safe object which adheres to the generated types model fields.'
+---
+
+
+
+The [`Prisma.validator`](/orm/reference/prisma-client-reference#prismavalidator) is a utility function that takes a generated type and returns a type-safe object which adheres to the generated types model fields.
+
+This page introduces the `Prisma.validator` and offers some motivations behind why you might choose to use it.
+
+
+
+> **Note**: If you have a use case for `Prisma.validator`, be sure to check out this [blog post](https://www.prisma.io/blog/satisfies-operator-ur8ys8ccq7zb) about improving your Prisma workflows with the new TypeScript `satisfies` keyword. It's likely that you can solve your use case natively using `satisfies` instead of using `Prisma.validator`.
+
+## Creating a typed query statement
+
+Let's imagine that you created a new `userEmail` object that you wanted to re-use in different queries throughout your application. It's typed and can be safely used in queries.
+
+The below example asks `Prisma` to return the `email` of the user whose `id` is 3, if no user exists it will return `null`.
+
+```ts
+import { Prisma } from '@prisma/client'
+
+const userEmail: Prisma.UserSelect = {
+ email: true,
+}
+
+// Run inside async function
+const user = await prisma.user.findUnique({
+ where: {
+ id: 3,
+ },
+ select: userEmail,
+})
+```
+
+This works well but there is a caveat to extracting query statements this way.
+
+You'll notice that if you hover your mouse over `userEmail` TypeScript won't infer the object's key or value (that is, `email: true`).
+
+The same applies if you use dot notation on `userEmail` within the `prisma.user.findUnique(...)` query, you will be able to access all of the properties available to a `select` object.
+
+If you are using this in one file that may be fine, but if you are going to export this object and use it in other queries, or if you are compiling an external library where you want to control how the user uses this object within their queries then this won't be type-safe.
+
+The object `userEmail` has been created to select only the user's `email`, and yet it still gives access to all the other properties available. **It is typed, but not type-safe**.
+
+`Prisma` has a way to validate generated types to make sure they are type-safe, a utility function available on the namespace called `validator`.
+
+## Using the `Prisma.validator`
+
+The following example passes the `UserSelect` generated type into the `Prisma.validator` utility function and defines the expected return type in much the same way as the previous example.
+
+```ts highlight=3,4,5;delete|7-9;add
+import { Prisma } from '@prisma/client'
+
+const userEmail: Prisma.UserSelect = {
+ email: true,
+}
+
+const userEmail = Prisma.validator()({
+ email: true,
+})
+
+// Run inside async function
+const user = await prisma.user.findUnique({
+ where: {
+ id: 3,
+ },
+ select: userEmail,
+})
+```
+
+Alternatively, you can use the following syntax that uses a "selector" pattern using an existing instance of Prisma Client:
+
+```ts
+import { Prisma } from '@prisma/client'
+import prisma from './lib/prisma'
+
+const userEmail = Prisma.validator(
+ prisma,
+ 'user',
+ 'findUnique',
+ 'select'
+)({
+ email: true,
+})
+```
+
+The big difference is that the `userEmail` object is now type-safe. If you hover your mouse over it TypeScript will tell you the object's key/value pair. If you use dot notation to access the object's properties you will only be able to access the `email` property of the object.
+
+This functionality is handy when combined with user defined input, like form data.
+
+## Combining `Prisma.validator` with form input
+
+The following example creates a type-safe function from the `Prisma.validator` which can be used when interacting with user created data, such as form inputs.
+
+> **Note**: Form input is determined at runtime so can't be verified by only using TypeScript. Be sure to validate your form input through other means too (such as an external validation library) before passing that data through to your database.
+
+```ts
+import { Prisma, PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+// Create a new function and pass the parameters onto the validator
+const createUserAndPost = (
+ name: string,
+ email: string,
+ postTitle: string,
+ profileBio: string
+) => {
+ return Prisma.validator()({
+ name,
+ email,
+ posts: {
+ create: {
+ title: postTitle,
+ },
+ },
+ profile: {
+ create: {
+ bio: profileBio,
+ },
+ },
+ })
+}
+
+const findSpecificUser = (email: string) => {
+ return Prisma.validator()({
+ email,
+ })
+}
+
+// Create the user in the database based on form input
+// Run inside async function
+await prisma.user.create({
+ data: createUserAndPost(
+ 'Rich',
+ 'rich@boop.com',
+ 'Life of Pie',
+ 'Learning each day'
+ ),
+})
+
+// Find the specific user based on form input
+// Run inside async function
+const oneUser = await prisma.user.findUnique({
+ where: findSpecificUser('rich@boop.com'),
+})
+```
+
+The `createUserAndPost` custom function is created using the `Prisma.validator` and passed a generated type, `UserCreateInput`. The `Prisma.validator` validates the functions input because the types assigned to the parameters must match those the generated type expects.
diff --git a/docs/200-orm/200-prisma-client/400-type-safety/100-operating-against-partial-structures-of-model-types.mdx b/docs/200-orm/200-prisma-client/400-type-safety/100-operating-against-partial-structures-of-model-types.mdx
new file mode 100644
index 0000000000..751a0ce83b
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/400-type-safety/100-operating-against-partial-structures-of-model-types.mdx
@@ -0,0 +1,137 @@
+---
+title: 'Operating against partial structures of your model types'
+metaTitle: 'Operating against partial structures of your model types'
+metaDescription: 'This page documents various scenarios for using the generated types from the Prisma namespace'
+---
+
+
+
+When using Prisma Client, every model from your [Prisma schema](/orm/prisma-schema) is translated into a dedicated TypeScript type. For example, assume you have the following `User` and `Post` models:
+
+```prisma
+model User {
+ id Int @id
+ email String @unique
+ name String?
+ posts Post[]
+}
+
+model Post {
+ id Int @id
+ author User @relation(fields: [userId], references: [id])
+ title String
+ published Boolean @default(false)
+ userId Int
+}
+```
+
+The Prisma Client code that's generated from this schema contains this representation of the `User` type:
+
+```ts
+export declare type User = {
+ id: string
+ email: string
+ name: string | null
+}
+```
+
+
+
+## Problem: Using variations of the generated model type
+
+### Description
+
+In some scenarios, you may need a _variation_ of the generated `User` type. For example, when you have a function that expects an instance of the `User` model that carries the `posts` relation. Or when you need a type to pass only the `User` model's `email` and `name` fields around in your application code.
+
+### Solution
+
+As a solution, you can customize the generated model type using Prisma Client's helper types.
+
+The `User` type only contains the model's [scalar](/orm/prisma-schema/data-model/models#scalar-fields) fields, but doesn't account for any relations. That's because [relations are not included by default](/orm/prisma-client/queries/select-fields#return-the-default-selection-set) in Prisma Client queries.
+
+However, sometimes it's useful to have a type available that **includes a relation** (i.e. a type that you'd get from an API call that uses [`include`](/orm/prisma-client/queries/select-fields#include-relations-and-select-relation-fields)). Similarly, another useful scenario could be to have a type available that **includes only a subset of the model's scalar fields** (i.e. a type that you'd get from an API call that uses [`select`](/orm/prisma-client/queries/select-fields#select-specific-fields)).
+
+One way of achieving this would be to define these types manually in your application code:
+
+```ts
+// 1: Define a type that includes the relation to `Post`
+type UserWithPosts = {
+ id: string
+ email: string
+ name: string | null
+ posts: Post[]
+}
+
+// 2: Define a type that only contains a subset of the scalar fields
+type UserPersonalData = {
+ email: string
+ name: string | null
+}
+```
+
+While this is certainly feasible, this approach increases the maintenance burden upon changes to the Prisma schema as you need to manually maintain the types. A cleaner solution to this is to use the `UserGetPayload` type that is generated and exposed by Prisma Client under the `Prisma` namespace in combination with the [`validator`](prisma-validator).
+
+The following example uses the `Prisma.validator` to create two type-safe objects and then uses the `Prisma.UserGetPayload` utility function to create a type that can be used to return all users and their posts.
+
+```ts
+import { Prisma } from '@prisma/client'
+
+// 1: Define a type that includes the relation to `Post`
+const userWithPosts = Prisma.validator()({
+ include: { posts: true },
+})
+
+// 2: Define a type that only contains a subset of the scalar fields
+const userPersonalData = Prisma.validator()({
+ select: { email: true, name: true },
+})
+
+// 3: This type will include a user and all their posts
+type UserWithPosts = Prisma.UserGetPayload
+```
+
+The main benefits of the latter approach are:
+
+- Cleaner approach as it leverages Prisma Client's generated types
+- Reduced maintenance burden and improved type safety when the schema changes
+
+## Problem: Getting access to the return type of a function
+
+### Description
+
+When doing [`select`](/orm/reference/prisma-client-reference#select) or [`include`](/orm/reference/prisma-client-reference#include) operations on your models and returning these variants from a function, it can be difficult to gain access to the return type, e.g:
+
+```ts
+// Function definition that returns a partial structure
+async function getUsersWithPosts() {
+ const users = await prisma.user.findMany({ include: { posts: true } })
+ return users
+}
+```
+
+Extracting the type that represents "users with posts" from the above code snippet requires some advanced TypeScript usage:
+
+```ts
+// Function definition that returns a partial structure
+async function getUsersWithPosts() {
+ const users = await prisma.user.findMany({ include: { posts: true } })
+ return users
+}
+
+// Extract `UsersWithPosts` type with
+type ThenArg = T extends PromiseLike ? U : T
+type UsersWithPosts = ThenArg>
+
+// run inside `async` function
+const usersWithPosts: UsersWithPosts = await getUsersWithPosts()
+```
+
+### Solution
+
+With the `PromiseReturnType` that is exposed by the Prisma namespace, you can solve this more elegantly:
+
+```ts
+import { Prisma } from '@prisma/client'
+
+type UsersWithPosts = Prisma.PromiseReturnType
+```
diff --git a/docs/200-orm/200-prisma-client/400-type-safety/830-prisma-type-system.mdx b/docs/200-orm/200-prisma-client/400-type-safety/830-prisma-type-system.mdx
new file mode 100644
index 0000000000..e00397c0f8
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/400-type-safety/830-prisma-type-system.mdx
@@ -0,0 +1,164 @@
+---
+title: How to use Prisma's type system
+metaDescription: How to use Prisma's type system
+tocDepth: 3
+---
+
+
+
+This guide introduces Prisma's type system and explains how to introspect existing native types in your database, and how to use types when you apply schema changes to your database with Prisma Migrate or `db push`.
+
+
+
+## How does Prisma's type system work?
+
+Prisma uses _types_ to define the kind of data that a field can hold. To make it easy to get started, Prisma provides a small number of core [scalar types](/orm/reference/prisma-schema-reference#model-field-scalar-types) that should cover most default use cases. For example, take the following blog post model:
+
+```prisma file=schema.prisma
+datasource db {
+ provider = "postgresql"
+ url = env("DATABASE_URL")
+}
+
+model Post {
+ id Int @id
+ title String
+ createdAt DateTime
+}
+```
+
+The `title` field of the `Post` model uses the `String` scalar type, while the `createdAt` field uses the `DateTime` scalar type.
+
+Databases also have their own type system, which defines the type of value that a column can hold. Most databases provide a large number of data types to allow fine-grained control over exactly what a column can store. For example, a database might provide inbuilt support for multiple sizes of integers, or for XML data. The names of these types vary between databases. For example, in PostgreSQL the column type for booleans is `boolean`, whereas in MySQL the `tinyint(1)` type is typically used.
+
+In the blog post example above, we are using the PostgreSQL connector. This is specified in the `datasource` block of the Prisma schema.
+
+### Default type mappings
+
+To allow you to get started with our core scalar types, Prisma provides _default type mappings_ that map each scalar type to a default type in the underlying database. For example:
+
+- by default Prisma's `String` type gets mapped to PostgreSQL's `text` type and MySQL's `varchar` type
+- by default Prisma's `DateTime` type gets mapped to PostgreSQL's `timestamp(3)` type and SQL Server's `datetime2` type
+
+See Prisma's [database connector pages](/orm/overview) for the default type mappings for a given database. For example, [this table](/orm/overview/databases/postgresql#type-mapping-between-postgresql-and-prisma-schema) gives the default type mappings for PostgreSQL.
+To see the default type mappings for all databases for a specific given Prisma type, see the [model field scalar types section](/orm/reference/prisma-schema-reference#model-field-scalar-types) of the Prisma schema reference. For example, [this table](/orm/reference/prisma-schema-reference#float) gives the default type mappings for the `Float` scalar type.
+
+### Native type mappings
+
+Sometimes you may need to use a more specific database type that is not one of the default type mappings for your Prisma type. For this purpose, Prisma provides [native type attributes](/orm/prisma-schema/data-model/models#native-types-mapping) to refine the core scalar types. For example, in the `createdAt` field of your `Post` model above you may want to use a date-only column in your underlying PostgreSQL database, by using the `date` type instead of the default type mapping of `timestamp(3)`. To do this, add a `@db.Date` native type attribute to the `createdAt` field:
+
+```prisma file=schema.prisma
+model Post {
+ id Int @id
+ title String
+ createdAt DateTime @db.Date
+}
+```
+
+Native type mappings allow you to express all the types in your database. However, you do not need to use them if the Prisma defaults satisfy your needs. This leads to a shorter, more readable Prisma schema for common use cases.
+
+## How to introspect database types
+
+When you [introspect](/orm/prisma-schema/introspection) an existing database, Prisma will take the database type of each table column and represent it in your Prisma schema using the correct Prisma type for the corresponding model field. If the database type is not the default database type for that Prisma scalar type, Prisma will also add a native type attribute.
+
+As an example, take a `User` table in a PostgreSQL database, with:
+
+- an `id` column with a data type of `serial`
+- a `name` column with a data type of `text`
+- an `isActive` column with a data type of `boolean`
+
+You can create this with the following SQL command:
+
+```sql
+CREATE TABLE "public"."User" (
+ id serial PRIMARY KEY NOT NULL,
+ name text NOT NULL,
+ "isActive" boolean NOT NULL
+);
+```
+
+Introspect your database with the following command run from the root directory of your project:
+
+```terminal
+npx prisma db pull
+```
+
+You will get the following Prisma schema:
+
+```prisma file=schema.prisma
+model User {
+ id Int @id @default(autoincrement())
+ name String
+ isActive Boolean
+}
+```
+
+The `id`, `name` and `isActive` columns in the database are mapped respectively to the `Int`, `String` and `Boolean` Prisma types. The database types are the _default_ database types for these Prisma types, so Prisma does not add any native type attributes.
+
+Now add a `createdAt` column to your database with a data type of `date` by running the following SQL command:
+
+```sql
+ALTER TABLE "public"."User"
+ADD COLUMN "createdAt" date NOT NULL;
+```
+
+Introspect your database again:
+
+```terminal
+npx prisma db pull
+```
+
+Your Prisma schema now includes the new `createdAt` field with a Prisma type of `DateTime`. The `createdAt` field also has a `@db.Date` native type attribute, because PostgreSQL's `date` is not the default type for the `DateTime` type:
+
+```prisma file=schema.prisma highlight=5;add
+model User {
+ id Int @id @default(autoincrement())
+ name String
+ isActive Boolean
+ createdAt DateTime @db.Date
+}
+```
+
+## How to use types when you apply schema changes to your database
+
+When you apply schema changes to your database using Prisma Migrate or `db push`, Prisma will use both the Prisma scalar type of each field and any native attribute it has to determine the correct database type for the corresponding column in the database.
+
+As an example, create a Prisma schema with the following `Post` model:
+
+```prisma file=schema.prisma
+model Post {
+ id Int @id
+ title String
+ createdAt DateTime
+ updatedAt DateTime @db.Date
+}
+```
+
+This `Post` model has:
+
+- an `id` field with a Prisma type of `Int`
+- a `title` field with a Prisma type of `String`
+- a `createdAt` field with a Prisma type of `DateTime`
+- an `updatedAt` field with a Prisma type of `DateTime` and a `@db.Date` native type attribute
+
+Now apply these changes to an empty PostgreSQL database with the following command, run from the root directory of your project:
+
+```terminal
+npx prisma db push
+```
+
+You will see that the database has a newly created `Post` table, with:
+
+- an `id` column with a database type of `integer`
+- a `title` column with a database type of `text`
+- a `createdAt` column with a database type of `timestamp(3)`
+- an `updatedAt` column with a database type of `date`
+
+Notice that the `@db.Date` native type attribute modifies the database type of the `updatedAt` column to `date`, rather than the default of `timestamp(3)`.
+
+## More on using Prisma's type system
+
+For further reference information on using Prisma's type system, see the following resources:
+
+- The [database connector](/orm/overview) page for each database provider has a type mapping section with a table of default type mappings between Prisma types and database types, and a table of database types with their corresponding native type attribute in Prisma. For example, the type mapping section for PostgreSQL is [here](/orm/overview/databases/postgresql#type-mapping-between-postgresql-and-prisma-schema).
+- The [model field scalar types](/orm/reference/prisma-schema-reference#model-field-scalar-types) section of the Prisma schema reference has a subsection for each Prisma scalar type. This includes a table of default mappings for that Prisma type in each database, and a table for each database listing the corresponding database types and their native type attributes in Prisma. For example, the entry for the `String` Prisma type is [here](/orm/reference/prisma-schema-reference#string).
diff --git a/docs/200-orm/200-prisma-client/400-type-safety/index.mdx b/docs/200-orm/200-prisma-client/400-type-safety/index.mdx
new file mode 100644
index 0000000000..7b968206f5
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/400-type-safety/index.mdx
@@ -0,0 +1,267 @@
+---
+title: 'Type safety'
+metaTitle: 'Type safety'
+metaDescription: 'Prisma Client provides full type safety for queries, even for partial queries or included relations. This page explains how to leverage the generated types and utilities.'
+tocDepth: 3
+---
+
+
+
+The generated code for Prisma Client contains several helpful types and utilities that you can use to make your application more type-safe. This page describes patterns for leveraging them.
+
+> **Note**: If you're interested in advanced type safety topics with Prisma, be sure to check out this [blog post](https://www.prisma.io/blog/satisfies-operator-ur8ys8ccq7zb) about improving your Prisma workflows with the new TypeScript `satisfies` keyword.
+
+
+
+## Importing generated types
+
+You can import the `Prisma` namespace and use dot notation to access types and utilities. The following example shows how to import the `Prisma` namespace and use it to access and use the `Prisma.UserSelect` [generated type](#what-are-generated-types):
+
+```ts
+import { Prisma } from '@prisma/client'
+
+// Build 'select' object
+const userEmail: Prisma.UserSelect = {
+ email: true,
+}
+
+// Use select object
+const createUser = await prisma.user.create({
+ data: {
+ email: 'bob@prisma.io',
+ },
+ select: userEmail,
+})
+```
+
+See also: [Using the `Prisma.UserCreateInput` generated type](/orm/prisma-client/queries/crud#create-a-single-record-using-generated-types)
+
+## What are generated types?
+
+Generated types are TypeScript types that are derived from your models. You can use them to create typed objects that you pass into top-level methods like `prisma.user.create(...)` or `prisma.user.update(...)`, or options such as `select` or `include`.
+
+For example, `select` accepts an object of type `UserSelect`. Its object properties match those that are supported by `select` statements according to the model.
+
+The first tab below shows the `UserSelect` generated type and how each property on the object has a type annotation. The second tab shows the resulting schema model.
+
+
+
+
+
+```ts
+type Prisma.UserSelect = {
+ id?: boolean | undefined;
+ email?: boolean | undefined;
+ name?: boolean | undefined;
+ posts?: boolean | Prisma.PostFindManyArgs | undefined;
+ profile?: boolean | Prisma.ProfileArgs | undefined;
+}
+```
+
+
+
+
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+ profile Profile?
+}
+```
+
+
+
+
+
+In TypeScript the concept of [type annotations](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-annotations-on-variables) is when you declare a variable and add a type annotation to describe the type of the variable. See the below example.
+
+```ts
+const myAge: number = 37
+const myName: string = 'Rich'
+```
+
+Both of these variable declarations have been given a type annotation to specify what primitive type they are, `number` and `string` respectively. Most of the time this kind of annotation is not needed as TypeScript will infer the type of the variable based on how its initialized. In the above example `myAge` was initialized with a number so TypeScript guesses that it should be typed as a number.
+
+Going back to the `UserSelect` type, if you were to use dot notation on the created object `userEmail`, you would have access to all of the fields on the `User` model that can be interacted with using a `select` statement.
+
+```prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+ profile Profile?
+}
+```
+
+```ts
+import { Prisma } from '@prisma/client'
+
+const userEmail: Prisma.UserSelect = {
+ email: true,
+}
+
+// properties available on the typed object
+userEmail.id
+userEmail.email
+userEmail.name
+userEmail.posts
+userEmail.profile
+```
+
+In the same mould, you can type an object with an `include` generated type then your object would have access to those properties on which you can use an `include` statement.
+
+```ts
+import { Prisma } from '@prisma/client'
+
+const userPosts: Prisma.UserInclude = {
+ posts: true,
+}
+
+// properties available on the typed object
+userPosts.posts
+userPosts.profile
+```
+
+> See the [model query options](/orm/reference/prisma-client-reference#model-query-options) reference for more information about the different types available.
+
+### Generated `UncheckedInput` types
+
+The `UncheckedInput` types are a special set of generated types that allow you to perform some operations that Prisma Client considers "unsafe", like directly writing [relation scalar fields](/orm/prisma-schema/data-model/relations). You can choose either the "safe" `Input` types or the "unsafe" `UncheckedInput` type when doing operations like `create`, `update`, or `upsert`.
+
+For example, this Prisma schema has a one-to-many relation between `User` and `Post`:
+
+```prisma
+model Post {
+ id Int @id @default(autoincrement())
+ title String @db.VarChar(255)
+ content String?
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ posts Post[]
+}
+```
+
+The first tab shows the `PostUncheckedCreateInput` generated type. It contains the `authorId` property, which is a relation scalar field. The second tab shows an example query that uses the `PostUncheckedCreateInput` type. This query will result in an error if a user with an `id` of `1` does not exist.
+
+
+
+
+
+```ts
+type PostUncheckedCreateInput = {
+ id?: number
+ title: string
+ content?: string | null
+ authorId: number
+}
+```
+
+
+
+
+```ts
+prisma.post.create({
+ data: {
+ title: 'First post',
+ content: 'Welcome to the first post in my blog...',
+ authorId: 1,
+ },
+})
+```
+
+
+
+
+
+The same query can be rewritten using the "safer" `PostCreateInput` type. This type does not contain the `authorId` field but instead contains the `author` relation field.
+
+
+
+
+
+```ts
+type PostCreateInput = {
+ title: string
+ content?: string | null
+ author: UserCreateNestedOneWithoutPostsInput
+}
+
+type UserCreateNestedOneWithoutPostsInput = {
+ create?: XOR<
+ UserCreateWithoutPostsInput,
+ UserUncheckedCreateWithoutPostsInput
+ >
+ connectOrCreate?: UserCreateOrConnectWithoutPostsInput
+ connect?: UserWhereUniqueInput
+}
+```
+
+
+
+
+```ts
+prisma.post.create({
+ data: {
+ title: 'First post',
+ content: 'Welcome to the first post in my blog...',
+ author: {
+ connect: {
+ id: 1,
+ },
+ },
+ },
+})
+```
+
+
+
+
+
+This query will also result in an error if an author with an `id` of `1` does not exist. In this case, Prisma Client will give a more descriptive error message. You can also use the [`connectOrCreate`](/orm/reference/prisma-client-reference#connectorcreate) API to safely create a new user if one does not already exist with the given `id`.
+
+We recommend using the "safe" `Input` types whenever possible.
+
+## Type utilities
+
+
+
+This feature is available from Prisma version 4.9.0 upwards.
+
+
+
+To help you create highly type-safe applications, Prisma Client provides a set of type utilities that tap into input and output types. These types are fully dynamic, which means that they adapt to any given model and schema. You can use them to improve the auto-completion and developer experience of your projects.
+
+This is especially useful in [validating inputs](/orm/prisma-client/type-safety/prisma-validator) and [shared Prisma Client extensions](/orm/prisma-client/client-extensions/shared-extensions).
+
+The following type utilities are available in Prisma Client:
+
+- `Exact`: Enforces strict type safety on `Input`. `Exact` makes sure that a generic type `Input` strictly complies with the type that you specify in `Shape`. It [narrows](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) `Input` down to the most precise types.
+- `Args`: Retrieves the input arguments for any given model and operation. This is particularly useful for extension authors who want to do the following:
+ - Re-use existing types to extend or modify them.
+ - Benefit from the same auto-completion experience as on existing operations.
+- `Result`: Takes the input arguments and provides the result for a given model and operation. You would usually use this in conjunction with `Args`. As with `Args`, `Result` helps you to re-use existing types to extend or modify them.
+- `Payload`: Retrieves the entire structure of the result, as scalars and relations objects for a given model and operation. For example, you can use this to determine which keys are scalars or objects at a type level.
+
+As an example, here's a quick way you can enforce that the arguments to a function matches what you will pass to a `post.create`:
+
+```ts
+type PostCreateBody = Prisma.Args['data']
+
+const addPost = async (postBody: PostCreateBody) => {
+ const post = await prisma.post.create({ data: postBody })
+ return post
+}
+
+await addPost(myData)
+// ^ guaranteed to match the input of `post.create`
+```
diff --git a/docs/200-orm/200-prisma-client/450-testing/100-unit-testing.mdx b/docs/200-orm/200-prisma-client/450-testing/100-unit-testing.mdx
new file mode 100644
index 0000000000..d5cbb0d23c
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/450-testing/100-unit-testing.mdx
@@ -0,0 +1,351 @@
+---
+title: 'Unit testing'
+metaTitle: 'Unit testing with Prisma'
+metaDescription: 'Learn how to setup and run unit tests with Prisma Client'
+tocDepth: 3
+---
+
+
+
+Unit testing aims to isolate a small portion (unit) of code and test it for logically predictable behaviors. It generally involves mocking objects or server responses to simulate real world behaviors. Some benefits to unit testing include:
+
+- Quickly find and isolate bugs in code.
+- Provides documentation for each module of code by way of indicating what certain code blocks should be doing.
+- A helpful gauge that a refactor has gone well. The tests should still pass after code has been refactored.
+
+In the context of Prisma, this generally means testing a function which makes database calls using Prisma Client.
+
+A single test should focus on how your function logic handles different inputs (such as a null value or an empty list).
+
+This means that you should aim to remove as many dependencies as possible, such as external services and databases, to keep the tests and their environments as lightweight as possible.
+
+
+
+> **Note**: This [blog post](https://www.prisma.io/blog/testing-series-2-xPhjjmIEsM) provides a comprehensive guide to implementing unit testing in your Express project with Prisma. If you're looking to delve into this topic, be sure to give it a read!
+
+## Prerequisites
+
+This guide assumes you have the JavaScript testing library [`Jest`](https://jestjs.io/) and [`ts-jest`](https://github.com/kulshekhar/ts-jest) already setup in your project.
+
+## Mocking Prisma Client
+
+To ensure your unit tests are isolated from external factors you can mock Prisma Client, this means you get the benefits of being able to use your schema (**_type-safety_**), without having to make actual calls to your database when your tests are run.
+
+This guide will cover two approaches to mocking Prisma Client, a singleton instance and dependency injection. Both have their merits depending on your use cases. To help with mocking Prisma Client the [`jest-mock-extended`](https://github.com/marchaos/jest-mock-extended) package will be used.
+
+```terminal
+npm install jest-mock-extended@2.0.4 --save-dev
+```
+
+
+
+At the time of writing, this guide uses `jest-mock-extended` version `^2.0.4`.
+
+
+
+### Singleton
+
+The following steps guide you through mocking Prisma Client using a singleton pattern.
+
+1. Create a file at your projects root called `client.ts` and add the following code. This will instantiate a Prisma Client instance.
+
+ ```ts file=client.ts
+ import { PrismaClient } from '@prisma/client'
+
+ const prisma = new PrismaClient()
+ export default prisma
+ ```
+
+2. Next create a file named `singleton.ts` at your projects root and add the following:
+
+ ```ts file=singleton.ts
+ import { PrismaClient } from '@prisma/client'
+ import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'
+
+ import prisma from './client'
+
+ jest.mock('./client', () => ({
+ __esModule: true,
+ default: mockDeep(),
+ }))
+
+ beforeEach(() => {
+ mockReset(prismaMock)
+ })
+
+ export const prismaMock = prisma as unknown as DeepMockProxy
+ ```
+
+The singleton file tells Jest to mock a default export (the Prisma Client instance in `./client.ts`), and uses the `mockDeep` method from `jest-mock-extended` to enable access to the objects and methods available on Prisma Client. It then resets the mocked instance before each test is run.
+
+Next, add the `setupFilesAfterEnv` property to your `jest.config.js` file with the path to your `singleton.ts` file.
+
+```js file=jest.config.js highlight=5;add
+module.exports = {
+ clearMocks: true,
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ setupFilesAfterEnv: ['/singleton.ts'],
+}
+```
+
+### Dependency injection
+
+Another popular pattern that can be used is dependency injection.
+
+1. Create a `context.ts` file and add the following:
+
+ ```ts file=context.ts
+ import { PrismaClient } from '@prisma/client'
+ import { mockDeep, DeepMockProxy } from 'jest-mock-extended'
+
+ export type Context = {
+ prisma: PrismaClient
+ }
+
+ export type MockContext = {
+ prisma: DeepMockProxy
+ }
+
+ export const createMockContext = (): MockContext => {
+ return {
+ prisma: mockDeep(),
+ }
+ }
+ ```
+
+:::tip
+
+If you find that you're seeing a circular dependency error highlighted through mocking Prisma Client, try adding `"strictNullChecks": true`
+to your `tsconfig.json`.
+
+:::
+
+2. To use the context, you would do the following in your test file:
+
+ ```ts
+ import { MockContext, Context, createMockContext } from '../context'
+
+ let mockCtx: MockContext
+ let ctx: Context
+
+ beforeEach(() => {
+ mockCtx = createMockContext()
+ ctx = mockCtx as unknown as Context
+ })
+ ```
+
+This will create a new context before each test is run via the `createMockContext` function. This (`mockCtx`) context will be used to make a mock call to Prisma and run a query to test. The `ctx` context will be used to run a scenario query that is tested against.
+
+## Example unit tests
+
+A real world use case for unit testing Prisma might be a signup form. Your user fills in a form which calls a function, which in turn uses Prisma to make a call to your database.
+
+All of the examples that follow use the following schema model:
+
+```prisma file=schema.prisma
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ name String?
+ acceptTermsAndConditions Boolean
+}
+```
+
+The following unit tests will mock the process of
+
+- Creating a new user
+- Updating a users name
+- Failing to create a user if terms are not accepted
+
+The functions that use the dependency injection pattern will have the context injected (passed in as a parameter) into them, whereas the functions that use the singleton pattern will use the singleton instance of Prisma Client.
+
+```ts file=functions-with-context.ts
+import { Context } from './context'
+
+interface CreateUser {
+ name: string
+ email: string
+ acceptTermsAndConditions: boolean
+}
+
+export async function createUser(user: CreateUser, ctx: Context) {
+ if (user.acceptTermsAndConditions) {
+ return await ctx.prisma.user.create({
+ data: user,
+ })
+ } else {
+ return new Error('User must accept terms!')
+ }
+}
+
+interface UpdateUser {
+ id: number
+ name: string
+ email: string
+}
+
+export async function updateUsername(user: UpdateUser, ctx: Context) {
+ return await ctx.prisma.user.update({
+ where: { id: user.id },
+ data: user,
+ })
+}
+```
+
+```ts file=functions-without-context.ts
+import prisma from './client'
+
+interface CreateUser {
+ name: string
+ email: string
+ acceptTermsAndConditions: boolean
+}
+
+export async function createUser(user: CreateUser) {
+ if (user.acceptTermsAndConditions) {
+ return await prisma.user.create({
+ data: user,
+ })
+ } else {
+ return new Error('User must accept terms!')
+ }
+}
+
+interface UpdateUser {
+ id: number
+ name: string
+ email: string
+}
+
+export async function updateUsername(user: UpdateUser) {
+ return await prisma.user.update({
+ where: { id: user.id },
+ data: user,
+ })
+}
+```
+
+The tests for each methodology are fairly similar, the difference is how the mocked Prisma Client is used.
+
+The **_dependency injection_** example passes the context through to the function that is being tested as well as using it to call the mock implementation.
+
+The **_singleton_** example uses the singleton client instance to call the mock implementation.
+
+```ts file=__tests__/with-singleton.ts
+import { createUser, updateUsername } from '../functions-without-context'
+import { prismaMock } from '../singleton'
+
+test('should create new user ', async () => {
+ const user = {
+ id: 1,
+ name: 'Rich',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: true,
+ }
+
+ prismaMock.user.create.mockResolvedValue(user)
+
+ await expect(createUser(user)).resolves.toEqual({
+ id: 1,
+ name: 'Rich',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: true,
+ })
+})
+
+test('should update a users name ', async () => {
+ const user = {
+ id: 1,
+ name: 'Rich Haines',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: true,
+ }
+
+ prismaMock.user.update.mockResolvedValue(user)
+
+ await expect(updateUsername(user)).resolves.toEqual({
+ id: 1,
+ name: 'Rich Haines',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: true,
+ })
+})
+
+test('should fail if user does not accept terms', async () => {
+ const user = {
+ id: 1,
+ name: 'Rich Haines',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: false,
+ }
+
+ prismaMock.user.create.mockImplementation()
+
+ await expect(createUser(user)).resolves.toEqual(
+ new Error('User must accept terms!')
+ )
+})
+```
+
+```ts file=__tests__/with-dependency-injection.ts
+import { MockContext, Context, createMockContext } from '../context'
+import { createUser, updateUsername } from '../functions-with-context'
+
+let mockCtx: MockContext
+let ctx: Context
+
+beforeEach(() => {
+ mockCtx = createMockContext()
+ ctx = mockCtx as unknown as Context
+})
+
+test('should create new user ', async () => {
+ const user = {
+ id: 1,
+ name: 'Rich',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: true,
+ }
+ mockCtx.prisma.user.create.mockResolvedValue(user)
+
+ await expect(createUser(user, ctx)).resolves.toEqual({
+ id: 1,
+ name: 'Rich',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: true,
+ })
+})
+
+test('should update a users name ', async () => {
+ const user = {
+ id: 1,
+ name: 'Rich Haines',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: true,
+ }
+ mockCtx.prisma.user.update.mockResolvedValue(user)
+
+ await expect(updateUsername(user, ctx)).resolves.toEqual({
+ id: 1,
+ name: 'Rich Haines',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: true,
+ })
+})
+
+test('should fail if user does not accept terms', async () => {
+ const user = {
+ id: 1,
+ name: 'Rich Haines',
+ email: 'hello@prisma.io',
+ acceptTermsAndConditions: false,
+ }
+
+ mockCtx.prisma.user.create.mockImplementation()
+
+ await expect(createUser(user, ctx)).resolves.toEqual(
+ new Error('User must accept terms!')
+ )
+})
+```
diff --git a/docs/200-orm/200-prisma-client/450-testing/150-integration-testing.mdx b/docs/200-orm/200-prisma-client/450-testing/150-integration-testing.mdx
new file mode 100644
index 0000000000..278f472708
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/450-testing/150-integration-testing.mdx
@@ -0,0 +1,475 @@
+---
+title: 'Integration testing'
+metaTitle: 'Integration testing with Prisma'
+metaDescription: 'Learn how to setup and run integration tests with Prisma and Docker'
+tocDepth: 3
+---
+
+
+
+Integration tests focus on testing how separate parts of the program work together. In the context of applications using a database, integration tests usually require a database to be available and contain data that is convenient to the scenarios intended to be tested.
+
+One way to simulate a real world environment is to use [Docker](https://www.docker.com/get-started) to encapsulate a database and some test data. This can be spun up and torn down with the tests and so operate as an isolated environment away from your production databases.
+
+
+
+> **Note:** This [blog post](https://www.prisma.io/blog/testing-series-2-xPhjjmIEsM) offers a comprehensive guide on setting up an integration testing environment and writing integration tests against a real database, providing valuable insights for those looking to explore this topic.
+
+## Prerequisites
+
+This guide assumes you have [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) installed on your machine as well as `Jest` setup in your project.
+
+The following ecommerce schema will be used throughout the guide. This varies from the traditional `User` and `Post` models used in other parts of the docs, mainly because it is unlikely you will be running integration tests against your blog.
+
+
+
+Ecommerce schema
+
+```prisma file=schema.prisma
+// Can have 1 customer
+// Can have many order details
+model CustomerOrder {
+ id Int @id @default(autoincrement())
+ createdAt DateTime @default(now())
+ customer Customer @relation(fields: [customerId], references: [id])
+ customerId Int
+ orderDetails OrderDetails[]
+}
+
+// Can have 1 order
+// Can have many products
+model OrderDetails {
+ id Int @id @default(autoincrement())
+ products Product @relation(fields: [productId], references: [id])
+ productId Int
+ order CustomerOrder @relation(fields: [orderId], references: [id])
+ orderId Int
+ total Decimal
+ quantity Int
+}
+
+// Can have many order details
+// Can have 1 category
+model Product {
+ id Int @id @default(autoincrement())
+ name String
+ description String
+ price Decimal
+ sku Int
+ orderDetails OrderDetails[]
+ category Category @relation(fields: [categoryId], references: [id])
+ categoryId Int
+}
+
+// Can have many products
+model Category {
+ id Int @id @default(autoincrement())
+ name String
+ products Product[]
+}
+
+// Can have many orders
+model Customer {
+ id Int @id @default(autoincrement())
+ email String @unique
+ address String?
+ name String?
+ orders CustomerOrder[]
+}
+```
+
+
+
+The guide uses a singleton pattern for Prisma Client setup. Refer to the [singleton](/orm/prisma-client/testing/unit-testing#singleton) docs for a walk through of how to set that up.
+
+## Add Docker to your project
+
+
+
+With Docker and Docker compose both installed on your machine you can use them in your project.
+
+1. Begin by creating a `docker-compose.yml` file at your projects root. Here you will add a Postgres image and specify the environments credentials.
+
+```yml file=docker-compose.yml
+# Set the version of docker compose to use
+version: '3.9'
+
+# The containers that compose the project
+services:
+ db:
+ image: postgres:13
+ restart: always
+ container_name: integration-tests-prisma
+ ports:
+ - '5433:5432'
+ environment:
+ POSTGRES_USER: prisma
+ POSTGRES_PASSWORD: prisma
+ POSTGRES_DB: tests
+```
+
+> **Note**: The compose version used here (`3.9`) is the latest at the time of writing, if you are following along be sure to use the same version for consistency.
+
+The `docker-compose.yml` file defines the following:
+
+- The Postgres image (`postgres`) and version tag (`:13`). This will be downloaded if you do not have it locally available.
+- The port `5433` is mapped to the internal (Postgres default) port `5432`. This will be the port number the database is exposed on externally.
+- The database user credentials are set and the database given a name.
+
+2. To connect to the database in the container, create a new connection string with the credentials defined in the `docker-compose.yml` file. For example:
+
+```env file=.env.test
+DATABASE_URL="postgresql://prisma:prisma@localhost:5433/tests"
+```
+
+
+
+The above `.env.test` file is used as part of a multiple `.env` file setup. Checkout the [using multiple .env files.](/orm/more/development-environment/environment-variables/using-multiple-env-files) section to learn more about setting up your project with multiple `.env` files
+
+
+
+3. To create the container in a detached state so that you can continue to use the terminal tab, run the following command:
+
+```terminal
+docker-compose up -d
+```
+
+4. Next you can check that the database has been created by executing a `psql` command inside the container. Make a note of the container id.
+
+
+
+
+
+ ```
+ docker ps
+ ```
+
+
+
+
+
+ ```code no-copy
+ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+ 1322e42d833f postgres:13 "docker-entrypoint.s…" 2 seconds ago Up 1 second 0.0.0.0:5433->5432/tcp integration-tests-prisma
+ ```
+
+
+
+
+
+> **Note**: The container id is unique to each container, you will see a different id displayed.
+
+5. Using the container id from the previous step, run `psql` in the container, login with the created user and check the database is created:
+
+
+
+
+
+ ```
+ docker exec -it 1322e42d833f psql -U prisma tests
+ ```
+
+
+
+
+
+ ```code no-copy
+ tests=# \l
+ List of databases
+ Name | Owner | Encoding | Collate | Ctype | Access privileges
+
+ postgres | prisma | UTF8 | en_US.utf8 | en_US.utf8 |
+ template0 | prisma | UTF8 | en_US.utf8 | en_US.utf8 | =c/prisma +
+ | | | | | prisma=CTc/prisma
+ template1 | prisma | UTF8 | en_US.utf8 | en_US.utf8 | =c/prisma +
+ | | | | | prisma=CTc/prisma
+ tests | prisma | UTF8 | en_US.utf8 | en_US.utf8 |
+ (4 rows)
+ ```
+
+
+
+
+
+## Integration testing
+
+Integration tests will be run against a database in a **dedicated test environment** instead of the production or development environments.
+
+### The flow of operations
+
+The flow for running said tests goes as follows:
+
+1. Start the container and create the database
+1. Migrate the schema
+1. Run the tests
+1. Destroy the container
+
+Each test suite will seed the database before all the test are run. After all the tests in the suite have finished, the data from all the tables will be dropped and the connection terminated.
+
+### The function to test
+
+The ecommerce application you are testing has a function which creates an order. This function does the following:
+
+- Accepts input about the customer making the order
+- Accepts input about the product being ordered
+- Checks if the customer has an existing account
+- Checks if the product is in stock
+- Returns an "Out of stock" message if the product doesn't exist
+- Creates an account if the customer doesn't exist in the database
+- Create the order
+
+An example of how such a function might look can be seen below:
+
+```ts file=create-order.ts
+import prisma from '../client'
+
+export interface Customer {
+ id?: number
+ name?: string
+ email: string
+ address?: string
+}
+
+export interface OrderInput {
+ customer: Customer
+ productId: number
+ quantity: number
+}
+
+/**
+ * Creates an order with customer.
+ * @param input The order parameters
+ */
+export async function createOrder(input: OrderInput) {
+ const { productId, quantity, customer } = input
+ const { name, email, address } = customer
+
+ // Get the product
+ const product = await prisma.product.findUnique({
+ where: {
+ id: productId,
+ },
+ })
+
+ // If the product is null its out of stock, return error.
+ if (!product) return new Error('Out of stock')
+
+ // If the customer is new then create the record, otherwise connect via their unique email
+ await prisma.customerOrder.create({
+ data: {
+ customer: {
+ connectOrCreate: {
+ create: {
+ name,
+ email,
+ address,
+ },
+ where: {
+ email,
+ },
+ },
+ },
+ orderDetails: {
+ create: {
+ total: product.price,
+ quantity,
+ products: {
+ connect: {
+ id: product.id,
+ },
+ },
+ },
+ },
+ },
+ })
+}
+```
+
+### The test suite
+
+The following tests will check if the `createOrder` function works as it should do. They will test:
+
+- Creating a new order with a new customer
+- Creating an order with an existing customer
+- Show an "Out of stock" error message if a product doesn't exist
+
+Before the test suite is run the database is seeded with data. After the test suite has finished a [`deleteMany`](/orm/reference/prisma-client-reference#deletemany) is used to clear the database of its data.
+
+:::tip
+
+Using `deleteMany` may suffice in situations where you know ahead of time how your schema is structured. This is because the operations need to be executed in the correct order according to how the model relations are setup.
+
+However, this doesn't scale as well as having a more generic solution that maps over your models and performs a truncate on them. For those scenarios and examples of using raw SQL queries see [Deleting all data with raw SQL / `TRUNCATE`](/orm/prisma-client/queries/crud#deleting-all-data-with-raw-sql--truncate)
+
+:::
+
+```ts file=__tests__/create-order.ts
+import prisma from '../src/client'
+import { createOrder, Customer, OrderInput } from '../src/functions/index'
+
+beforeAll(async () => {
+ // create product categories
+ await prisma.category.createMany({
+ data: [{ name: 'Wand' }, { name: 'Broomstick' }],
+ })
+
+ console.log('✨ 2 categories successfully created!')
+
+ // create products
+ await prisma.product.createMany({
+ data: [
+ {
+ name: 'Holly, 11", phoenix feather',
+ description: 'Harry Potters wand',
+ price: 100,
+ sku: 1,
+ categoryId: 1,
+ },
+ {
+ name: 'Nimbus 2000',
+ description: 'Harry Potters broom',
+ price: 500,
+ sku: 2,
+ categoryId: 2,
+ },
+ ],
+ })
+
+ console.log('✨ 2 products successfully created!')
+
+ // create the customer
+ await prisma.customer.create({
+ data: {
+ name: 'Harry Potter',
+ email: 'harry@hogwarts.io',
+ address: '4 Privet Drive',
+ },
+ })
+
+ console.log('✨ 1 customer successfully created!')
+})
+
+afterAll(async () => {
+ const deleteOrderDetails = prisma.orderDetails.deleteMany()
+ const deleteProduct = prisma.product.deleteMany()
+ const deleteCategory = prisma.category.deleteMany()
+ const deleteCustomerOrder = prisma.customerOrder.deleteMany()
+ const deleteCustomer = prisma.customer.deleteMany()
+
+ await prisma.$transaction([
+ deleteOrderDetails,
+ deleteProduct,
+ deleteCategory,
+ deleteCustomerOrder,
+ deleteCustomer,
+ ])
+
+ await prisma.$disconnect()
+})
+
+it('should create 1 new customer with 1 order', async () => {
+ // The new customers details
+ const customer: Customer = {
+ id: 2,
+ name: 'Hermione Granger',
+ email: 'hermione@hogwarts.io',
+ address: '2 Hampstead Heath',
+ }
+ // The new orders details
+ const order: OrderInput = {
+ customer,
+ productId: 1,
+ quantity: 1,
+ }
+
+ // Create the order and customer
+ await createOrder(order)
+
+ // Check if the new customer was created by filtering on unique email field
+ const newCustomer = await prisma.customer.findUnique({
+ where: {
+ email: customer.email,
+ },
+ })
+
+ // Check if the new order was created by filtering on unique email field of the customer
+ const newOrder = await prisma.customerOrder.findFirst({
+ where: {
+ customer: {
+ email: customer.email,
+ },
+ },
+ })
+
+ // Expect the new customer to have been created and match the input
+ expect(newCustomer).toEqual(customer)
+ // Expect the new order to have been created and contain the new customer
+ expect(newOrder).toHaveProperty('customerId', 2)
+})
+
+it('should create 1 order with an existing customer', async () => {
+ // The existing customers email
+ const customer: Customer = {
+ email: 'harry@hogwarts.io',
+ }
+ // The new orders details
+ const order: OrderInput = {
+ customer,
+ productId: 1,
+ quantity: 1,
+ }
+
+ // Create the order and connect the existing customer
+ await createOrder(order)
+
+ // Check if the new order was created by filtering on unique email field of the customer
+ const newOrder = await prisma.customerOrder.findFirst({
+ where: {
+ customer: {
+ email: customer.email,
+ },
+ },
+ })
+
+ // Expect the new order to have been created and contain the existing customer with an id of 1 (Harry Potter from the seed script)
+ expect(newOrder).toHaveProperty('customerId', 1)
+})
+
+it("should show 'Out of stock' message if productId doesn't exit", async () => {
+ // The existing customers email
+ const customer: Customer = {
+ email: 'harry@hogwarts.io',
+ }
+ // The new orders details
+ const order: OrderInput = {
+ customer,
+ productId: 3,
+ quantity: 1,
+ }
+
+ // The productId supplied doesn't exit so the function should return an "Out of stock" message
+ await expect(createOrder(order)).resolves.toEqual(new Error('Out of stock'))
+})
+```
+
+## Running the tests
+
+This setup isolates a real world scenario so that you can test your applications functionality against real data in a controlled environment.
+
+You can add some scripts to your projects `package.json` file which will setup the database and run the tests, then afterwards manually destroy the container.
+
+```json file=package.json
+ "scripts": {
+ "docker:up": "docker-compose up -d",
+ "docker:down": "docker-compose down",
+ "test": "yarn docker:up && yarn prisma migrate deploy && jest -i"
+ },
+```
+
+The `test` script does the following:
+
+1. Runs `docker-compose up -d` to create the container with the Postgres image and database.
+1. Applies the migrations found in `./prisma/migrations/` directory to the database, this creates the tables in the container's database.
+1. Executes the tests.
+
+Once you are satisfied you can run `yarn docker:down` to destroy the container, its database and any test data.
diff --git a/docs/200-orm/200-prisma-client/450-testing/Docker_Diagram_V1.png b/docs/200-orm/200-prisma-client/450-testing/Docker_Diagram_V1.png
new file mode 100644
index 0000000000..e2bc67509d
Binary files /dev/null and b/docs/200-orm/200-prisma-client/450-testing/Docker_Diagram_V1.png differ
diff --git a/docs/200-orm/200-prisma-client/450-testing/index.mdx b/docs/200-orm/200-prisma-client/450-testing/index.mdx
new file mode 100644
index 0000000000..9523cc79c8
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/450-testing/index.mdx
@@ -0,0 +1,14 @@
+---
+title: 'Testing'
+navTitle: Testing
+metaTitle: 'Testing with Prisma'
+metaDescription: 'How to implement unit and integration testing with Prisma'
+---
+
+
+
+This section describes how to approach testing an application that uses Prisma Client.
+
+
+
+
diff --git a/docs/200-orm/200-prisma-client/500-deployment/001-deploy-prisma.mdx b/docs/200-orm/200-prisma-client/500-deployment/001-deploy-prisma.mdx
new file mode 100644
index 0000000000..b733f5c803
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/001-deploy-prisma.mdx
@@ -0,0 +1,40 @@
+---
+title: 'Deploy Prisma'
+metaTitle: 'Deploying Prisma-based projects'
+metaDescription: 'Learn more about the different deployment paradigms for Node.js applications and how they affect deploying an application using Prisma Client.'
+tocDepth: 2
+---
+
+
+
+Projects using Prisma Client can be deployed to many different cloud platforms. Given the variety of cloud platforms and different names, it's noteworthy to mention the different deployment paradigms, as they affect the way you deploy an application using Prisma Client.
+
+
+
+## Deployment paradigms
+
+Each paradigm has different tradeoffs that affect the performance, scalability, and operational costs of your application.
+
+Moreover, the user traffic pattern of your application is also an important factor to consider. For example, any application with consistent user traffic may be better suited for a [continuously running paradigm](#traditional-servers), whereas an application with sudden spikes may be better suited to [serverless](#serverless-functions).
+
+### Traditional servers
+
+Your application is [traditionally deployed](/orm/prisma-client/deployment/traditional) if a Node.js process is continuously running and handles multiple requests at the same time. Your application could be deployed to a Platform-as-a-Service (PaaS) like [Heroku](/orm/prisma-client/deployment/traditional/deploy-to-heroku), [Koyeb](/orm/prisma-client/deployment/traditional/deploy-to-koyeb), as a Docker container to Kubernetes, or as a Node.js process on a virtual machine, or good old bare metal server.
+
+See also: [Connection management in long-running processes](/orm/prisma-client/setup-and-configuration/databases-connections#long-running-processes)
+
+### Serverless Functions
+
+Your application is [serverless](/orm/prisma-client/deployment/serverless) if the Node.js processes of your application (or subsets of it broken into functions) are started as requests come in, and each function only handles one request at a time. Your application would most likely be deployed to a Function-as-a-Service (FaaS) offering, such as [AWS Lambda](/orm/prisma-client/deployment/serverless/deploy-to-aws-lambda) or [Azure Functions](/orm/prisma-client/deployment/serverless/deploy-to-azure-functions)
+
+Serverless environments have the concept of warm starts, which means that for subsequent invocations of the same function, it may use an already existing container that has the allocated processes, memory, file system (`/tmp` is writable on AWS Lambda), and even DB connection still available.
+
+Typically, any piece of code [outside the handler](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-features.html#gettingstarted-features-programmingmodel) remains initialized.
+
+See also: [Connection management in serverless environments](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas)
+
+### Edge Functions
+
+Your application is [edge deployed](/orm/prisma-client/deployment/edge) if your application is [serverless](#serverless-functions) and the functions are distributed across one or more regions close to the user.
+
+Typically, edge environments also have a different runtime than a traditional or serverless environment, leading to common APIs being unavailable.
diff --git a/docs/200-orm/200-prisma-client/500-deployment/101-traditional/200-deploy-to-heroku.mdx b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/200-deploy-to-heroku.mdx
new file mode 100644
index 0000000000..4242c91b81
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/200-deploy-to-heroku.mdx
@@ -0,0 +1,280 @@
+---
+title: 'Deploy to Heroku'
+metaTitle: 'Deploy a Prisma app to Heroku'
+metaDescription: 'Learn how to deploy a Node.js server that uses Prisma to Heroku.'
+---
+
+
+
+In this guide, you will set up and deploy a Node.js server that uses Prisma with PostgreSQL to [Heroku](https://www.heroku.com). The application exposes a REST API and uses Prisma Client to handle fetching, creating, and deleting records from a database.
+
+Heroku is a cloud platform as a service (PaaS). In contrast to the popular serverless deployment model, with Heroku, your application is constantly running even if no requests are made to it. This has several benefits due to the connection limits of a PostgreSQL database. For more information, check out the [general deployment documentation](/orm/prisma-client/deployment/deploy-prisma)
+
+Typically Heroku integrates with a Git repository for automatic deployments upon commits. You can deploy to Heroku from a GitHub repository or by pushing your source to a [Git repository that Heroku creates per app](https://devcenter.heroku.com/articles/git). This guide uses the latter approach whereby you push your code to the app's repository on Heroku, which triggers a build and deploys the application.
+
+The application has the following components:
+
+- **Backend**: Node.js REST API built with Express.js with resource endpoints that use Prisma Client to handle database operations against a PostgreSQL database (e.g., hosted on Heroku).
+- **Frontend**: Static HTML page to interact with the API.
+
+
+
+The focus of this guide is showing how to deploy projects using Prisma to Heroku. The starting point will be the [Prisma Heroku example](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/heroku), which contains an Express.js server with a couple of preconfigured REST endpoints and a simple frontend.
+
+> **Note:** The various **checkpoints** throughout the guide allowing you to validate whether you performed the steps correctly.
+
+
+
+## A note on deploying GraphQL servers to Heroku
+
+While the example uses REST, the same principles apply to a GraphQL server, with the main difference being that you typically have a single GraphQL API endpoint rather than a route for every resource as with REST.
+
+## Prerequisites
+
+- [Heroku](https://www.heroku.com) account.
+- [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) installed.
+- Node.js installed.
+- PostgreSQL CLI `psql` installed.
+
+> **Note:** Heroku doesn't provide a free plan, so billing information is required.
+
+## Prisma workflow
+
+At the core of Prisma is the [Prisma schema](/orm/prisma-schema) – a declarative configuration where you define your data model and other Prisma-related configuration. The Prisma schema is also a single source of truth for both Prisma Client and Prisma Migrate.
+
+In this guide, you will use [Prisma Migrate](/orm/prisma-migrate) to create the database schema. Prisma Migrate is based on the Prisma schema and works by generating `.sql` migration files that are executed against the database.
+
+Migrate comes with two primary workflows:
+
+- Creating migrations and applying during local development with `prisma migrate dev`
+- Applying generated migration to production with `prisma migrate deploy`
+
+For brevity, the guide does not cover how migrations are created with `prisma migrate dev`. Rather, it focuses on the production workflow and uses the Prisma schema and SQL migration that are included in the example code.
+
+You will use Heroku's [release phase](https://devcenter.heroku.com/articles/release-phase) to run the `prisma migrate deploy` command so that the migrations are applied before the application starts.
+
+To learn more about how migrations are created with Prisma Migrate, check out the [start from scratch guide](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql)
+
+## 1. Download the example and install dependencies
+
+Open your terminal and navigate to a location of your choice. Create the directory that will hold the application code and download the example code:
+
+```no-lines wrap
+mkdir prisma-heroku
+cd prisma-heroku
+curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=3 prisma-examples-latest/deployment-platforms/heroku
+```
+
+
+
+**Checkpoint:** `ls -1` should show:
+
+```no-lines
+ls -1
+Procfile
+README.md
+package.json
+prisma
+public
+src
+```
+
+Install the dependencies:
+
+```no-lines
+npm install
+```
+
+> **Note:** The `Procfile` tells Heroku the command needed to start the application, i.e. `npm start`, and the command to run during the release phase, i.e., `npx prisma migrate deploy`
+
+## 2. Create a Git repository for the application
+
+In the previous step, you downloaded the code. In this step, you will create a repository from the code so that you can push it to Heroku for deployment.
+
+To do so, run `git init` from the source code folder:
+
+```no-lines
+git init
+> Initialized empty Git repository in /Users/alice/prisma-heroku/.git/
+```
+
+To use the `main` branch as the default branch, run the following command:
+
+```no-lines
+git branch -M main
+```
+
+With the repository initialized, add and commit the files:
+
+```no-lines
+git add .
+git commit -m 'Initial commit'
+```
+
+**Checkpoint:** `git log -1` should show the commit:
+
+```no-lines
+git log -1
+commit 895534590fdd260acee6396e2e1c0438d1be7fed (HEAD -> main)
+```
+
+## 3. Heroku CLI login
+
+Make sure you're logged in to Heroku with the CLI:
+
+```no-lines
+heroku login
+```
+
+This will allow you to deploy to Heroku from the terminal.
+
+**Checkpoint:** `heroku auth:whoami` should show your username:
+
+```no-lines
+heroku auth:whoami
+> your-email
+```
+
+## 4. Create a Heroku app
+
+To deploy an application to Heroku, you need to create an app. You can do so with the following command:
+
+```no-lines
+heroku apps:create your-app-name
+```
+
+> **Note:** Use a unique name of your choice instead of `your-app-name`.
+
+**Checkpoint:** You should see the URL and the repository for your Heroku app:
+
+```no-lines wrap
+heroku apps:create your-app-name
+> Creating ⬢ your-app-name... done
+> https://your-app-name.herokuapp.com/ | https://git.heroku.com/your-app-name.git
+```
+
+Creating the Heroku app will add the git remote Heroku created to your local repository. Pushing commits to this remote will trigger a deploy.
+
+**Checkpoint:** `git remote -v` should show the Heroku git remote for your application:
+
+```no-lines
+heroku https://git.heroku.com/your-app-name.git (fetch)
+heroku https://git.heroku.com/your-app-name.git (push)
+```
+
+If you don't see the heroku remote, use the following command to add it:
+
+```no-lines
+heroku git:remote --app your-app-name
+```
+
+## 5. Add a PostgreSQL database to your application
+
+Heroku allows your to provision a PostgreSQL database as part of an application.
+
+Create the database with the following command:
+
+```no-lines
+heroku addons:create heroku-postgresql:hobby-dev
+```
+
+**Checkpoint:** To verify the database was created you should see the following:
+
+```no-lines
+Creating heroku-postgresql:hobby-dev on ⬢ your-app-name... free
+Database has been created and is available
+ ! This database is empty. If upgrading, you can transfer
+ ! data from another database with pg:copy
+Created postgresql-parallel-73780 as DATABASE_URL
+```
+
+> **Note:** Heroku automatically sets the `DATABASE_URL` environment variable when the app is running on Heroku. Prisma uses this environment variable because it's declared in the _datasource_ block of the Prisma schema (`prisma/schema.prisma`) with `env("DATABASE_URL")`.
+
+## 6. Push to deploy
+
+Deploy the app by pushing the changes to the Heroku app repository:
+
+```no-lines
+git push heroku main
+```
+
+This will trigger a build and deploy your application to Heroku. Heroku will also run the `npx prisma migrate deploy` command which executes the migrations to create the database schema before deploying the app (as defined in the `release` step of the `Procfile`).
+
+**Checkpoint:** `git push` will emit the logs from the build and release phase and display the URL of the deployed app:
+
+```no-lines wrap
+remote: -----> Launching...
+remote: ! Release command declared: this new release will not be available until the command succeeds.
+remote: Released v5
+remote: https://your-app-name.herokuapp.com/ deployed to Heroku
+remote:
+remote: Verifying deploy... done.
+remote: Running release command...
+remote:
+remote: Prisma schema loaded from prisma/schema.prisma
+remote: Datasource "db": PostgreSQL database "your-db-name", schema "public" at "your-db-host.compute-1.amazonaws.com:5432"
+remote:
+remote: 1 migration found in prisma/migrations
+remote:
+remote: The following migration have been applied:
+remote:
+remote: migrations/
+remote: └─ 20210310152103_init/
+remote: └─ migration.sql
+remote:
+remote: All migrations have been successfully applied.
+remote: Waiting for release.... done.
+```
+
+> **Note:** Heroku will also set the `PORT` environment variable to which your application is bound.
+
+## 7. Test your deployed application
+
+You can use the static frontend to interact with the API you deployed via the preview URL.
+
+Open up the preview URL in your browser, the URL should like this: `https://APP_NAME.herokuapp.com`. You should see the following:
+
+
+
+The buttons allow you to make requests to the REST API and view the response:
+
+- **Check API status**: Will call the REST API status endpoint that returns `{"up":true}`.
+- **Seed data**: Will seed the database with a test `user` and `post`. Returns the created users.
+- **Load feed**: Will load all `users` in the database with their related `profiles`.
+
+For more insight into Prisma Client's API, look at the route handlers in the `src/index.js` file.
+
+You can view the application's logs with the `heroku logs --tail` command:
+
+```no-lines wrap
+2020-07-07T14:39:07.396544+00:00 app[web.1]:
+2020-07-07T14:39:07.396569+00:00 app[web.1]: > prisma-heroku@1.0.0 start /app
+2020-07-07T14:39:07.396569+00:00 app[web.1]: > node src/index.js
+2020-07-07T14:39:07.396570+00:00 app[web.1]:
+2020-07-07T14:39:07.657505+00:00 app[web.1]: 🚀 Server ready at: http://localhost:12516
+2020-07-07T14:39:07.657526+00:00 app[web.1]: ⭐️ See sample requests: http://pris.ly/e/ts/rest-express#3-using-the-rest-api
+2020-07-07T14:39:07.842546+00:00 heroku[web.1]: State changed from starting to up
+```
+
+## Heroku specific notes
+
+There are some implementation details relating to Heroku that this guide addresses and are worth reiterating:
+
+- **Port binding**: web servers bind to a port so that they can accept connections. When deploying to Heroku The `PORT` environment variable is set by Heroku. Ensure you bind to `process.env.PORT` so that your application can accept requests once deployed. A common pattern is to try binding to try `process.env.PORT` and fallback to a preset port as follows:
+
+```js
+const PORT = process.env.PORT || 3000
+const server = app.listen(PORT, () => {
+ console.log(`app running on port ${PORT}`)
+})
+```
+
+- **Database URL**: As part of Heroku's provisioning process, a `DATABASE_URL` config var is added to your app’s configuration. This contains the URL your app uses to access the database. Ensure that your `schema.prisma` file uses `env("DATABASE_URL")` so that Prisma Client can successfully connect to the database.
+
+## Summary
+
+Congratulations! You have successfully deployed a Node.js app with Prisma to Heroku.
+
+You can find the source code for the example in [this GitHub repository](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/heroku).
+
+For more insight into Prisma Client's API, look at the route handlers in the `src/index.js` file.
diff --git a/docs/200-orm/200-prisma-client/500-deployment/101-traditional/250-deploy-to-koyeb.mdx b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/250-deploy-to-koyeb.mdx
new file mode 100644
index 0000000000..6205ffddfb
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/250-deploy-to-koyeb.mdx
@@ -0,0 +1,202 @@
+---
+title: 'Deploy to Koyeb'
+metaTitle: 'Deploy a Prisma app to Koyeb'
+metaDescription: 'Learn how to deploy a Node.js server that uses Prisma to Koyeb Serverless Platform.'
+---
+
+
+
+In this guide, you will set up and deploy a Node.js server that uses Prisma with PostgreSQL to [Koyeb](https://www.koyeb.com). The application exposes a REST API and uses Prisma Client to handle fetching, creating, and deleting records from a database.
+
+Koyeb is a developer-friendly serverless platform to deploy apps globally. The platform lets you seamlessly run Docker containers, web apps, and APIs with git-based deployment, TLS encryption, native autoscaling, a global edge network, and built-in service mesh & discovery.
+
+When using the [Koyeb git-driven deployment](https://www.koyeb.com/docs/apps/build-from-git) method, each time you push code changes to a GitHub repository a new build and deployment of the application are automatically triggered on the Koyeb Serverless Platform.
+This guide uses the latter approach whereby you push your code to the app's repository on GitHub.
+
+The application has the following components:
+
+- **Backend**: Node.js REST API built with Express.js with resource endpoints that use Prisma Client to handle database operations against a PostgreSQL database (e.g., hosted on Heroku).
+- **Frontend**: Static HTML page to interact with the API.
+
+
+
+The focus of this guide is showing how to deploy projects using Prisma to Koyeb. The starting point will be the [Prisma Koyeb example](https://github.com/koyeb/example-prisma), which contains an Express.js server with a couple of preconfigured REST endpoints and a simple frontend.
+
+> **Note:** The various **checkpoints** throughout the guide allow you to validate whether you performed the steps correctly.
+
+
+
+## Prerequisites
+
+- Hosted PostgreSQL database and a URL from which it can be accessed, e.g. `postgresql://username:password@your_postgres_db.cloud.com/db_identifier` (you can use Supabase, which offers a [free plan](https://dev.to/prisma/set-up-a-free-postgresql-database-on-supabase-to-use-with-prisma-3pk6)).
+- [GitHub](https://github.com) account with an empty public repository we will use to push the code.
+- [Koyeb](https://koyeb.com) account.
+- Node.js installed.
+
+## Prisma workflow
+
+At the core of Prisma is the [Prisma schema](/orm/prisma-schema) – a declarative configuration where you define your data model and other Prisma-related configuration. The Prisma schema is also a single source of truth for both Prisma Client and Prisma Migrate.
+
+In this guide, you will create the database schema with [Prisma Migrate](/orm/prisma-migrate) to create the database schema. Prisma Migrate is based on the Prisma schema and works by generating `.sql` migration files that are executed against the database.
+
+Migrate comes with two primary workflows:
+
+- Creating migrations and applying them during local development with `prisma migrate dev`
+- Applying generated migration to production with `prisma migrate deploy`
+
+For brevity, the guide does not cover how migrations are created with `prisma migrate dev`. Rather, it focuses on the production workflow and uses the Prisma schema and SQL migration that are included in the example code.
+
+You will use Koyeb's [build step](https://www.koyeb.com/docs/apps/build-from-git#understanding-the-build-process) to run the `prisma migrate deploy` command so that the migrations are applied before the application starts.
+
+To learn more about how migrations are created with Prisma Migrate, check out the [start from scratch guide](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql)
+
+## 1. Download the example and install dependencies
+
+Open your terminal and navigate to a location of your choice. Create the directory that will hold the application code and download the example code:
+
+```no-lines wrap
+mkdir prisma-on-koyeb
+cd prisma-on-koyeb
+curl https://github.com/koyeb/example-prisma/tarball/main/latest | tar xz --strip=1
+```
+
+
+
+**Checkpoint:** Executing the `tree` command should show the following directories and files:
+
+```no-lines
+.
+├── README.md
+├── package.json
+├── prisma
+│ ├── migrations
+│ │ ├── 20210310152103_init
+│ │ │ └── migration.sql
+│ │ └── migration_lock.toml
+│ └── schema.prisma
+├── public
+│ └── index.html
+└── src
+ └── index.js
+
+5 directories, 8 files
+```
+
+Install the dependencies:
+
+```no-lines
+npm install
+```
+
+## 2. Initialize a Git repository and push the application code to GitHub
+
+In the previous step, you downloaded the code. In this step, you will create a repository from the code so that you can push it to a GitHub repository for deployment.
+
+To do so, run `git init` from the source code folder:
+
+```no-lines
+git init
+> Initialized empty Git repository in /Users/edouardb/prisma-on-koyeb/.git/
+```
+
+With the repository initialized, add and commit the files:
+
+```no-lines
+git add .
+git commit -m 'Initial commit'
+```
+
+**Checkpoint:** `git log -1` should show the commit:
+
+```no-lines
+git log -1
+commit 895534590fdd260acee6396e2e1c0438d1be7fed (HEAD -> main)
+```
+
+Then, push the code to your GitHub repository by adding the remote
+
+```no-lines
+git remote add origin git@github.com:/.git
+git push -u origin main
+```
+
+## 3. Deploy the application on Koyeb
+
+On the [Koyeb Control Panel](https://app.koyeb.com), click the **Create App** button.
+
+You land on the Koyeb App creation page where you are asked for information about the application to deploy such as the deployment method to use, the repository URL, the branch to deploy, the build and run commands to execute.
+
+Pick GitHub as the deployment method and select the GitHub repository containing your application and set the branch to deploy to `main`.
+
+> **Note:** If this is your first time using Koyeb, you will be prompted to install the Koyeb app in your GitHub account.
+
+In the **Environment variables** section, create a new environment variable `DATABASE_URL` that is type Secret. In the value field, click **Create Secret**, name your secret `prisma-pg-url` and set the PostgreSQL database connection string as the secret value which should look as follows: `postgresql://__USER__:__PASSWORD__@__HOST__/__DATABASE__`.
+[Koyeb Secrets](https://www.koyeb.com/docs/secrets) allow you to securely store and retrieve sensitive information like API tokens, database connection strings. They enable you to secure your code by removing hardcoded credentials and let you pass environment variables securely to your applications.
+
+Last, give your application a name and click the **Create App** button.
+
+**Checkpoint:** Open the deployed app by clicking on the screenshot of the deployed app. Once the page loads, click on the **Check API status** button, which should return: `{"up":true}`
+
+
+
+Congratulations! You have successfully deployed the app to Koyeb.
+
+Koyeb will build and deploy the application. Additional commits to your GitHub repository will trigger a new build and deployment on Koyeb.
+
+**Checkpoint:** Once the build and deployment are completed, you can access your application by clicking the App URL ending with koyeb.app in the Koyeb control panel. Once on the app page loads, Once the page loads, click on the **Check API status** button, which should return: `{"up":true}`
+
+## 4. Test your deployed application
+
+You can use the static frontend to interact with the API you deployed via the preview URL.
+
+Open up the preview URL in your browser, the URL should like this: `https://APP_NAME-ORG_NAME.koyeb.app`. You should see the following:
+
+
+
+The buttons allow you to make requests to the REST API and view the response:
+
+- **Check API status**: Will call the REST API status endpoint that returns `{"up":true}`.
+- **Seed data**: Will seed the database with a test `user` and `post`. Returns the created users.
+- **Load feed**: Will load all `users` in the database with their related `profiles`.
+
+For more insight into Prisma Client's API, look at the route handlers in the `src/index.js` file.
+
+You can view the application's logs clicking the `Runtime logs` tab on your app service from the Koyeb control panel:
+
+```no-lines wrap
+node-72d14691 stdout > prisma-koyeb@1.0.0 start
+node-72d14691 stdout > node src/index.js
+node-72d14691 stdout 🚀 Server ready at: http://localhost:8080
+node-72d14691 stdout ⭐️ See sample requests: http://pris.ly/e/ts/rest-express#3-using-the-rest-api
+```
+
+## Koyeb specific notes
+
+### Build
+
+By default, for applications using the Node.js runtime, if the `package.json` contains a `build` script, Koyeb automatically executes it after the dependencies installation.
+In the example, the `build` script is used to run `prisma generate && prisma migrate deploy && next build`.
+
+### Deployment
+
+By default, for applications using the Node.js runtime, if the `package.json` contains a `start` script, Koyeb automatically executes it to launch the application.
+In the example, the `start` script is used to run `node src/index.js`.
+
+### Database migrations and deployments
+
+In the example you deployed, migrations are applied using the `prisma migrate deploy` command during the Koyeb build (as defined in the `build` script in `package.json`).
+
+### Additional notes
+
+In this guide, we kept pre-set values for the region, instance size, and horizontal scaling. You can customize them according to your needs.
+
+> **Note:** The Ports section is used to let Koyeb know which port your application is listening to and properly route incoming HTTP requests. A default `PORT` environment variable is set to `8080` and incoming HTTP requests are routed to the `/` path when creating a new application.
+> If your application is listening on another port, you can define another port to route incoming HTTP requests.
+
+## Summary
+
+Congratulations! You have successfully deployed a Node.js app with Prisma to Koyeb.
+
+You can find the source code for the example in [this GitHub repository](https://github.com/koyeb/example-prisma).
+
+For more insight into Prisma Client's API, look at the route handlers in the `src/index.js` file.
diff --git a/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/heroku-architecture.png b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/heroku-architecture.png
new file mode 100644
index 0000000000..f501852e4c
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/heroku-architecture.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/heroku-deployed.png b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/heroku-deployed.png
new file mode 100644
index 0000000000..fb52deba4b
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/heroku-deployed.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-app-creation.png b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-app-creation.png
new file mode 100644
index 0000000000..87aeeacbf9
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-app-creation.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-architecture.png b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-architecture.png
new file mode 100644
index 0000000000..c9b98c4707
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-architecture.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-deployed.png b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-deployed.png
new file mode 100644
index 0000000000..29c3b606b1
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/images/koyeb-deployed.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/101-traditional/index.mdx b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/index.mdx
new file mode 100644
index 0000000000..145b8aa5a9
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/101-traditional/index.mdx
@@ -0,0 +1,16 @@
+---
+title: 'Traditional servers'
+metaTitle: 'Deploy Prisma apps to traditional (PaaS) servers'
+metaDescription: 'Learn how to deploy your Prisma-backed apps to PaaS providers like Heroku, Koyeb, or AWS EC2'
+tocDepth: 2
+---
+
+
+
+If your application is deployed via a Platform-as-a-Service (PaaS) provider, whether containerized or not, it is a traditionally-deployed app. Common deployment examples include [Heroku](/orm/prisma-client/deployment/traditional/deploy-to-heroku) and [Koyeb](/orm/prisma-client/deployment/traditional/deploy-to-koyeb).
+
+
+
+## Traditional (PaaS) guides
+
+
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/150-deploy-to-azure-functions.mdx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/150-deploy-to-azure-functions.mdx
new file mode 100644
index 0000000000..5e0120f978
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/150-deploy-to-azure-functions.mdx
@@ -0,0 +1,40 @@
+---
+title: 'Deploy to Azure Functions'
+metaTitle: 'How to deploy an app using Prisma to Azure Functions'
+metaDescription: 'Learn how to deploy a Prisma based REST API to Azure Functions and connect to an Azure SQL database'
+---
+
+
+
+This guide explains how to avoid common issues when deploying a Node.js-based function app to Azure using [Azure Functions](https://azure.microsoft.com/en-us/services/functions/).
+
+Azure Functions is a serverless deployment platform. You do not need to maintain infrastructure to deploy your code. With Azure Functions, the fundamental building block is the [function app](https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference#function-app). A function app provides an execution context in Azure in which your functions run. It is comprised of one or more individual functions that Azure manages, deploys, and scales together. You can organize and collectively manage multiple functions as a single logical unit.
+
+
+
+## Prerequisites
+
+- An existing function app project with Prisma
+
+## Things to know
+
+While Prisma works well with Azure functions, there are a few things to take note of before deploying your application.
+
+### Define multiple binary targets
+
+When deploying a function app, the operating system that Azure functions runs a remote build is different from the one used to host your functions. Therefore, we recommend specifying the following [`binaryTargets` options](/orm/reference/prisma-schema-reference#binarytargets-options) in your Prisma schema:
+
+```prisma file=schema.prisma highlight=3;normal
+generator client {
+ provider = "prisma-client-js"
+ binaryTargets = ["native", "debian-openssl-1.1.x"]
+}
+```
+
+### Connection pooling
+
+Generally, when you use a FaaS (Function as a Service) environment to interact with a database, every function invocation can result in a new connection to the database. This is not a problem with a constantly running Node.js server. Therefore, it is beneficial to pool DB connections to get better performance. To solve this issue, you can use the [Prisma Accelerate](/accelerate). For other solutions, see the [connection management guide for serverless environments](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas).
+
+## Summary
+
+For more insight into Prisma Client's API, explore the function handlers and check out the [Prisma Client API Reference](/orm/reference/prisma-client-reference)
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/300-deploy-to-vercel.mdx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/300-deploy-to-vercel.mdx
new file mode 100644
index 0000000000..f62f86db43
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/300-deploy-to-vercel.mdx
@@ -0,0 +1,80 @@
+---
+title: 'Deploy to Vercel'
+metaTitle: 'Deploy to Vercel'
+metaDescription: 'Learn how to deploy a Next.js application based on Prisma Client to Vercel.'
+---
+
+
+
+This guide takes you through the steps to set up and deploy a serverless application that uses Prisma to [Vercel](https://vercel.com/).
+
+Vercel is a cloud platform that hosts static sites, serverless, and edge functions. You can integrate a Vercel project with a GitHub repository to allow you to deploy automatically when you make new commits.
+
+We created an [example application](https://github.com/prisma/deployment-example-vercel) using Next.js you can use as a reference when deploying an application using Prisma to Vercel.
+
+While our examples use Next.js, you can deploy other applications to Vercel. See [Using Express with Vercel](https://vercel.com/guides/using-express-with-vercel) and [Nuxt on Vercel](https://vercel.com/docs/frameworks/nuxt) as examples of other options.
+
+
+
+## Generate Prisma during build
+
+Vercel will automatically cache dependencies on deployment. For most applications, this will not cause any issues. However, for Prisma, it may result in an outdated version of Prisma Client on a change in your Prisma schema. To avoid this issue, add `prisma generate` to the `postinstall` script of your application:
+
+```json file=package.json highlight=4;add
+{
+ ...
+ "scripts" {
+ "postinstall": "prisma generate"
+ }
+ ...
+}
+```
+
+This will re-generate Prisma Client at build time so that your deployment always has an up-to-date client.
+
+
+
+If you see `prisma: command not found` errors during your deployment to Vercel, you are missing `prisma` in your dependencies. By default, `prisma` is a dev dependency and may need to be moved to be a standard dependency.
+
+
+
+Another option to avoid an outdated Prisma Client is to use [a custom output path](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) and check your client into version control. This way each deployment is guaranteed to include the correct Prisma Client.
+
+```prisma file=schema.prisma highlight=3;add
+generator client {
+ provider = "prisma-client-js"
+ output = "./generated/client"
+}
+```
+
+## Add a separate database for preview deployments
+
+By default, your application will have a single _production_ environment associated with the `main` git branch of your repository. If you open a pull request to change your application, Vercel creates a new _preview_ environment.
+
+Vercel uses the `DATABASE_URL` environment variable you define when you import the project for both the production and preview environments. This causes problems if you create a pull request with a database schema migration because the pull request will change the schema of the production database.
+
+To prevent this, use a _second_ hosted database to handle preview deployments. Once you have that connection string, you can add a `DATABASE_URL` for your preview environment using the Vercel dashboard:
+
+1. Click the **Settings** tab of your Vercel project.
+
+2. Click **Environment variables**.
+
+3. Add an environment variable with a key of `DATABASE_URL` and select only the **Preview** environment option:
+
+ 
+
+4. Set the value to the connection string of your second database:
+
+ ```code
+ postgresql://dbUsername:dbPassword@myhost:5432/mydb
+ ```
+
+5. Click **Save**.
+
+## Connection pooling
+
+When you use a Function-as-a-Service provider, like Vercel Serverless functions, every invocation may result in a new connection to your database. This can cause your database to quickly run out of open connections and cause your application to stall. For this reason, pooling connections to your database is essential.
+
+You can use [Accelerate](/accelerate) for connection pooling, to reduce your Prisma Client bundle size, and to avoid cold starts.
+
+For more information on connection management for serverless environments, refer to our [connection management guide](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas).
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/400-deploy-to-aws-lambda.mdx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/400-deploy-to-aws-lambda.mdx
new file mode 100644
index 0000000000..fdad2c298a
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/400-deploy-to-aws-lambda.mdx
@@ -0,0 +1,325 @@
+---
+title: 'Deploy to AWS Lambda'
+metaTitle: 'Deploy your application using Prisma to AWS Lambda'
+metaDescription: 'Learn how to deploy your Prisma-backed applications to AWS Lambda with AWS SAM, Serverless Framework, or SST'
+tocDepth: 3
+---
+
+
+
+This guide explains how to avoid common issues when deploying a project using Prisma to [AWS Lambda](https://aws.amazon.com/lambda/).
+
+While a deployment framework is not required to deploy to AWS Lambda, this guide covers deploying with:
+
+- [AWS Serverless Application Model (SAM)](https://aws.amazon.com/serverless/sam/) is an open-source framework from AWS that can be used in the creation of serverless applications. AWS SAM includes the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-reference.html#serverless-sam-cli), which you can use to build, test, and deploy your application.
+- [Serverless Framework](https://www.serverless.com/framework/) provides a CLI that helps with workflow automation and AWS resource provisioning. While Prisma works well with the Serverless Framework "out of the box", there are a few improvements that can be made within your project to ensure a smooth deployment and performance. There is also additional configuration that is needed if you are using the [`serverless-webpack`](https://www.npmjs.com/package/serverless-webpack) or [`serverless-bundle`](https://www.npmjs.com/package/serverless-bundle) libraries.
+- [SST](https://sst.dev/) provides tools that make it easy for developers to define, test, debug, and deploy their applications. Prisma works well with SST but must be configured so that your schema is correctly packaged by SST.
+
+
+
+## General considerations when deploying to AWS Lambda
+
+This section covers changes you will need to make to your application, regardless of framework. After following these steps, follow the steps for your framework.
+
+- [Deploying with AWS SAM](#deploying-with-aws-sam)
+- [Deploying with the Serverless Framework](#deploying-with-the-serverless-framework)
+- [Deploying with SST](#deploying-with-sst)
+
+### Define binary targets in Prisma Schema
+
+The Prisma schema should contain the following in the `generator` block:
+
+```prisma
+binaryTargets = ["native", "rhel-openssl-1.0.x"]
+```
+
+This is necessary because the runtimes used in development and deployment differ. Add the [`binaryTarget`](/orm/reference/prisma-schema-reference#binarytargets-options) to make the compatible Prisma engine file available.
+
+#### Lambda functions with arm64 architectures
+
+Lambda functions that use [arm64 architectures (AWS Graviton2 processor)](https://docs.aws.amazon.com/lambda/latest/dg/foundation-arch.html#foundation-arch-adv) must use an `arm64` precompiled engine file.
+
+In the `generator` block of your `schema.prisma` file, add the following:
+
+```prisma file=schema.prisma
+binaryTargets = ["native", "linux-arm64-openssl-1.0.x"]
+```
+
+### Prisma CLI binary targets
+
+While we do not recommend running migrations within AWS Lambda, some applications will require it. In these cases, you can use the [PRISMA_CLI_BINARY_TARGETS](/orm/reference/environment-variables-reference#prisma_cli_binary_targets) environment variable to make sure that Prisma CLI commands, including `prisma migrate`, have access to the correct schema engine.
+
+In the case of AWS lambda, you will have to add the following environment variable:
+
+```env file=.env
+PRISMA_CLI_BINARY_TARGETS=native,rhel-openssl-1.0.x
+```
+
+
+
+`prisma migrate` is a command in the `prisma` package. Normally, this package is installed as a dev dependency. Depending on your setup, you may need to install this package as a dependency instead so that it is included in the bundle or archive that is uploaded to Lambda and executed.
+
+
+
+### Connection pooling
+
+Generally, when you use a Function as a Service (FaaS) environment to interact with a database, every function invocation can result in a new connection to the database. This is not a problem with a constantly running Node.js server. Therefore, it is beneficial to pool database connections to get better performance. You can use [Accelerate](/accelerate) to solve this issue. For other solutions, see the [connection management guide for serverless environments](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas).
+
+## Deploying with AWS SAM
+
+### Loading environment variables
+
+AWS SAM does not directly support loading values from a `.env` file. You will have to use one of AWS's services to store and retrieve these parameters. [This guide](https://medium.com/bip-xtech/a-practical-guide-to-surviving-aws-sam-d8ab141b3d25) provides a great overview of your options and how to store and retrieve values in Parameters, SSM, Secrets Manager, and more.
+
+### Loading required files
+
+AWS SAM uses [esbuild](https://esbuild.github.io/) to bundle your TypeScript code. However, the full esbuild API is not exposed and esbuild plugins are not supported. This leads to problems when using Prisma in your application as certain files (like `schema.prisma`) must be available at runtime.
+
+To get around this, you need to directly reference the needed files in your code to bundle them correctly. In your application, you could add the following lines to your application where Prisma is instantiated.
+
+```ts file=app.ts
+import schema from './prisma/schema.prisma'
+import x from './node_modules/.prisma/client/libquery_engine-rhel-openssl-1.0.x.so.node'
+
+if (process.env.NODE_ENV !== 'production') {
+ console.debug(schema, x)
+}
+```
+
+You will also need to define how to bundle these files with esbuild by adding the following lines to `Metadata.BuildProperties` in your `template.yaml`:
+
+```yaml file=template.yaml
+Loader:
+ - .prisma=file
+ - .so.node=file
+AssetNames: '[name]'
+```
+
+This will make sure that files needed by Prisma will be included in the AWS SAM build.
+
+## Deploying with the Serverless Framework
+
+### Loading environment variables via a `.env` file
+
+Your functions will need the `DATABASE_URL` environment variable to access the database. The `serverless-dotenv-plugin` will allow you to use your `.env` file in your deployments.
+
+First, make sure that the plugin is installed:
+
+```terminal
+npm install -D serverless-dotenv-plugin
+```
+
+Then, add `serverless-dotenv-plugin` to your list of plugins in `serverless.yml`:
+
+```code file=serverless.yml no-copy
+plugins:
+ - serverless-dotenv-plugin
+```
+
+The environment variables in your `.env` file will now be automatically loaded on package or deployment.
+
+
+
+
+```terminal
+serverless package
+```
+
+
+
+
+```terminal no-copy
+Running "serverless" from node_modules
+DOTENV: Loading environment variables from .env:
+ - DATABASE_URL
+
+Packaging deployment-example-sls for stage dev (us-east-1)
+.
+.
+.
+```
+
+
+
+
+### Deploy only the required files
+
+To reduce your deployment footprint, you can update your deployment process to only upload the files your application needs. The Serverless configuration file, `serverless.yml`, below shows a `package` pattern that includes only the Prisma engine file relevant to the Lambda runtime and excludes the others. This means that when Serverless Framework packages your app for upload, it includes only one engine file. This ensures the packaged archive is as small as possible.
+
+```code file=serverless.yml no-copy
+package:
+ patterns:
+ - '!node_modules/.prisma/client/libquery_engine-*'
+ - 'node_modules/.prisma/client/libquery_engine-rhel-*'
+ - '!node_modules/prisma/libquery_engine-*'
+ - '!node_modules/@prisma/engines/**'
+```
+
+If you are deploying to [Lambda functions with ARM64 architecture](#lambda-functions-with-arm64-architectures) you should update the Serverless configuration file to package the `arm64` engine file, as follows:
+
+```code file=serverless.yml highlight=4;normal
+package:
+ patterns:
+ - '!node_modules/.prisma/client/libquery_engine-*'
+ - 'node_modules/.prisma/client/libquery_engine-linux-arm64-*'
+ - '!node_modules/prisma/libquery_engine-*'
+ - '!node_modules/@prisma/engines/**'
+```
+
+If you use `serverless-webpack`, see [Deployment with serverless webpack](#deployment-with-serverless-webpack) below.
+
+### Deployment with `serverless-webpack`
+
+If you use `serverless-webpack`, you will need additional configuration so that your `schema.prisma` is properly bundled. You will need to:
+
+1. Copy your `schema.prisma` with [`copy-webpack-plugin`](https://www.npmjs.com/package/copy-webpack-plugin).
+2. Run `prisma generate` via `custom > webpack > packagerOptions > scripts` in your `serverless.yml`.
+3. Only package the correct Prisma engine file to save more than 40mb of capacity.
+
+#### 1. Install webpack specific dependencies
+
+First, ensure the following webpack dependencies are installed:
+
+```terminal
+npm install --save-dev webpack webpack-node-externals copy-webpack-plugin serverless-webpack
+```
+
+#### 2. Update `webpack.config.js`
+
+In your `webpack.config.js`, make sure that you set `externals` to `nodeExternals()` like the following:
+
+```javascript file=webpack.config.js highlight=1,5;normal;
+const nodeExternals = require('webpack-node-externals')
+
+module.exports = {
+ // ... other configuration
+ externals: [nodeExternals()],
+ // ... other configuration
+}
+```
+
+Update the `plugins` property in your `webpack.config.js` file to include the `copy-webpack-plugin`:
+
+```javascript file=webpack.config.js highlight=2,7-13;normal;
+const nodeExternals = require('webpack-node-externals')
+const CopyPlugin = require('copy-webpack-plugin')
+
+module.exports = {
+ // ... other configuration
+ externals: [nodeExternals()],
+ plugins: [
+ new CopyPlugin({
+ patterns: [
+ { from: './node_modules/.prisma/client/schema.prisma', to: './' }, // you may need to change `to` here.
+ ],
+ }),
+ ],
+ // ... other configuration
+}
+```
+
+This plugin will allow you to copy your `schema.prisma` file into your bundled code. Prisma requires that your `schema.prisma` be present in order make sure that queries are encoded and decoded according to your schema. In most cases, bundlers will not include this file by default and will cause your application to fail to run.
+
+
+
+Depending on how your application is bundled, you may need to copy the schema file to a location other than `./`. Use the `serverless package` command to package your code locally so you can review where your schema should be put.
+
+
+
+Refer to the [Serverless Webpack documentation](https://www.serverless.com/plugins/serverless-webpack) for additional configuration.
+
+#### 3. Update `serverless.yml`
+
+In your `serverless.yml` file, make sure that the `custom > webpack` block has `prisma generate` under `packagerOptions > scripts` as follows:
+
+```yaml file=serverless.yml
+custom:
+ webpack:
+ packagerOptions:
+ scripts:
+ - prisma generate
+```
+
+This will ensure that, after webpack bundles your code, the Prisma Client is generated according to your schema. Without this step, your app will fail to run.
+
+Lastly, you will want to exclude [Prisma query engines](/orm/more/under-the-hood/engines) that do not match the AWS Lambda runtime. Update your `serverless.yml` by adding the following script that makes sure only the required query engine, `rhel-openssl-1.0.x`, is included in the final packaged archive.
+
+```yaml file=serverless.yml highlight=6;add
+custom:
+ webpack:
+ packagerOptions:
+ scripts:
+ - prisma generate
+ -- find . -name "libquery_engine-*" -not -name "libquery_engine-rhel-openssl-*" | xargs rm
+```
+
+If you are deploying to [Lambda functions with ARM64 architecture](#lambda-functions-with-arm64-architectures) you should update the `find` command to the following:
+
+```yaml file=serverless.yml highlight=6;add
+custom:
+ webpack:
+ packagerOptions:
+ scripts:
+ - prisma generate
+ -- find . -name "libquery_engine-*" -not -name "libquery_engine-arm64-openssl-*" | xargs rm
+```
+
+#### 4. Wrapping up
+
+You can now re-package and re-deploy your application. To do so, run `serverless deploy`. Webpack output will show the schema file being moved with `copy-webpack-plugin`:
+
+
+
+
+```terminal
+serverless package
+```
+
+
+
+
+```terminal no-copy
+Running "serverless" from node_modules
+DOTENV: Loading environment variables from .env:
+ - DATABASE_URL
+
+Packaging deployment-example-sls for stage dev (us-east-1)
+
+asset handlers/posts.js 713 bytes [emitted] [minimized] (name: handlers/posts)
+ asset schema.prisma 293 bytes [emitted] [from: node_modules/.prisma/client/schema.prisma] [copied]
+ ./handlers/posts.ts 745 bytes [built] [code generated]
+ external "@prisma/client" 42 bytes [built] [code generated]
+ webpack 5.88.2 compiled successfully in 685 ms
+Package lock found - Using locked versions
+Packing external modules: @prisma/client@^5.1.1
+
+✔ Service packaged (5s)
+```
+
+
+
+
+## Deploying with SST
+
+### Working with environment variables
+
+While SST supports `.env` files, [it is not recommended](https://docs.sst.dev/config#should-i-use-configsecret-or-env-for-secrets). SST recommends using `Config` to access these environment variables in a secure way.
+
+The SST guide [available here](https://docs.sst.dev/config#overview) is a step-by-step guide to get started with `Config`. Assuming you have created a new secret called `DATABASE_URL` and have [bound that secret to your app](https://docs.sst.dev/config#bind-the-config), you can set up `PrismaClient` with the following:
+
+```ts file=prisma.ts
+import { PrismaClient } from '@prisma/client'
+import { Config } from 'sst/node/config'
+
+const globalForPrisma = global as unknown as { prisma: PrismaClient }
+
+export const prisma =
+ globalForPrisma.prisma ||
+ new PrismaClient({
+ datasourceUrl: Config.DATABASE_URL,
+ })
+
+if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
+
+export default prisma
+```
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/500-deploy-to-netlify.mdx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/500-deploy-to-netlify.mdx
new file mode 100644
index 0000000000..9600aa265d
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/500-deploy-to-netlify.mdx
@@ -0,0 +1,86 @@
+---
+title: 'Deploy to Netlify'
+metaTitle: 'Deploy to Netlify'
+metaDescription: 'Learn how to deploy Node.js and TypeScript applications that are using Prisma Client to Netlify.'
+---
+
+
+
+This guide covers the steps you will need to take in order to deploy your application that uses Prisma to [Netlify](https://www.netlify.com/).
+
+Netlify is a cloud platform for continuous deployment, static sites, and serverless functions. Netlify integrates seamlessly with GitHub for automatic deployments upon commits. When you follow the steps below, you will use that approach to create a CI/CD pipeline that deploys your application from a GitHub repository.
+
+
+
+## Prerequisites
+
+Before you can follow this guide, you will need to set up your application to begin deploying to Netlify. We recommend the ["Get started with Netlify"](https://docs.netlify.com/get-started/) guide for a quick overview and ["Deploy functions"](https://docs.netlify.com/functions/deploy/?fn-language=ts) for an in-depth look at your deployment options.
+
+## Binary targets in `schema.prisma`
+
+Since your code is being deployed to Netlify's environment, which isn't necessarily the same as your development environment, you will need to set [`binaryTargets`](/orm/reference/prisma-schema-reference#binarytargets-options) in order to download the query engine that is compatible with the Netlify runtime during your build step. If you do not set this option, your deployed code will have an incorrect query engine deployed with it and will not function.
+
+You should update your Prisma schema to contain the following in the `generator` block:
+
+```prisma
+binaryTargets = ["native", "rhel-openssl-1.0.x"]
+```
+
+## Store environment variables in Netlify
+
+We recommend keeping `.env` files in your `.gitignore` in order to prevent leakage of sensitives connection strings. Instead, you can use the Netlify CLI to [import values into netlify directly](https://docs.netlify.com/environment-variables/get-started/#import-variables-with-the-netlify-cli).
+
+Assuming you have a file like the following:
+
+```env file=.env
+# Connect to DB
+DATABASE_URL="postgresql://postgres:__PASSWORD__@__HOST__:__PORT__/__DB_NAME__"
+```
+
+You can upload the file as environment variables using the `env:import` command
+
+```terminal no-break-terminal
+❯ netlify env:import .env
+site: my-very-very-cool-site
+---------------------------------------------------------------------------------.
+ Imported environment variables |
+---------------------------------------------------------------------------------|
+ Key | Value |
+--------------|------------------------------------------------------------------|
+ DATABASE_URL | postgresql://postgres:__PASSWORD__@__HOST__:__PORT__/__DB_NAME__ |
+---------------------------------------------------------------------------------'
+```
+
+
+If you are not using an `.env` file
+
+If you are storing your database connection string and other environment variables in a different method, you will need to manually upload your environment variables to Netlify. These options are [discussed in Netlfiy's documentation](https://docs.netlify.com/environment-variables/get-started/) and one method, uploading via the UI, is described below.
+
+1. Open the Netlify admin UI for the site. You can use Netlify CLI as follows:
+ ```terminal
+ netlify open --admin
+ ```
+2. Click **Site settings**:
+ 
+3. Navigate to **Build & deploy** in the sidebar on the left and select **Environment**.
+4. Click **Edit variables** and create a variable with the key `DATABASE_URL` and set its value to your database connection string.
+ 
+5. Click **Save**.
+
+
+
+Now start a new Netlify build and deployment so that the new build can use the newly uploaded environment variables.
+
+```terminal no-copy
+netlify deploy
+```
+
+You can now test the deployed application.
+
+## Connection pooling
+
+When you use a Function-as-a-Service provider, like Netlify, it is beneficial to pool database connections for performance reasons. This is because every function invocation may result in a new connection to your database which can quickly run out of open connections.
+
+You can use [Accelerate](/accelerate) for connection pooling, to reduce your Prisma Client bundle size, and to avoid cold starts.
+
+For more information on connection management for serverless environments, refer to our [connection management guide](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas).
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-00-deploy-to-vercel-architecture.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-00-deploy-to-vercel-architecture.png
new file mode 100644
index 0000000000..87cab2d012
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-00-deploy-to-vercel-architecture.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-10-deploy-to-vercel-deploy-button.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-10-deploy-to-vercel-deploy-button.png
new file mode 100644
index 0000000000..affde53fdf
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-10-deploy-to-vercel-deploy-button.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-10-deploy-to-vercel-deploy-button.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-10-deploy-to-vercel-deploy-button.snagx
new file mode 100644
index 0000000000..f866b57bff
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-10-deploy-to-vercel-deploy-button.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-20-deploy-to-vercel-select-github.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-20-deploy-to-vercel-select-github.png
new file mode 100644
index 0000000000..111f6a9ce2
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-20-deploy-to-vercel-select-github.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-20-deploy-to-vercel-select-github.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-20-deploy-to-vercel-select-github.snagx
new file mode 100644
index 0000000000..0feecdb56b
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-20-deploy-to-vercel-select-github.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-30-deploy-to-vercel-create-git-repo.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-30-deploy-to-vercel-create-git-repo.png
new file mode 100644
index 0000000000..a4966e9bc7
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-30-deploy-to-vercel-create-git-repo.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-30-deploy-to-vercel-create-git-repo.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-30-deploy-to-vercel-create-git-repo.snagx
new file mode 100644
index 0000000000..8125ce49b4
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-30-deploy-to-vercel-create-git-repo.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-40-deploy-to-vercel-configure-project.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-40-deploy-to-vercel-configure-project.png
new file mode 100644
index 0000000000..84f9f2117e
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-40-deploy-to-vercel-configure-project.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-40-deploy-to-vercel-configure-project.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-40-deploy-to-vercel-configure-project.snagx
new file mode 100644
index 0000000000..ebdf0f53d1
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-40-deploy-to-vercel-configure-project.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-50-deploy-to-vercel-success.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-50-deploy-to-vercel-success.png
new file mode 100644
index 0000000000..a0dabfc0c3
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-50-deploy-to-vercel-success.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-50-deploy-to-vercel-success.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-50-deploy-to-vercel-success.snagx
new file mode 100644
index 0000000000..8f7c5c7095
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-50-deploy-to-vercel-success.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-60-deploy-to-vercel-preview-environment-variable.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-60-deploy-to-vercel-preview-environment-variable.png
new file mode 100644
index 0000000000..9d107a1046
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-60-deploy-to-vercel-preview-environment-variable.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-60-deploy-to-vercel-preview-environment-variable.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-60-deploy-to-vercel-preview-environment-variable.snagx
new file mode 100644
index 0000000000..409dae8ce8
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-60-deploy-to-vercel-preview-environment-variable.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-70-deploy-to-vercel-environment-variables.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-70-deploy-to-vercel-environment-variables.png
new file mode 100644
index 0000000000..c004aab78c
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-70-deploy-to-vercel-environment-variables.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-70-deploy-to-vercel-environment-variables.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-70-deploy-to-vercel-environment-variables.snagx
new file mode 100644
index 0000000000..e27fb6a167
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/300-70-deploy-to-vercel-environment-variables.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-01-deploy-to-netlify-architecture.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-01-deploy-to-netlify-architecture.png
new file mode 100644
index 0000000000..f332cc8d3b
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-01-deploy-to-netlify-architecture.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-02-deploy-to-netlify-example-repo-click-fork.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-02-deploy-to-netlify-example-repo-click-fork.png
new file mode 100644
index 0000000000..cb7ce5c427
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-02-deploy-to-netlify-example-repo-click-fork.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-02-deploy-to-netlify-example-repo-click-fork.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-02-deploy-to-netlify-example-repo-click-fork.snagx
new file mode 100644
index 0000000000..6851b49d96
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-02-deploy-to-netlify-example-repo-click-fork.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-03-deploy-to-netlify-example-repo-create-fork-page.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-03-deploy-to-netlify-example-repo-create-fork-page.png
new file mode 100644
index 0000000000..50dbe8d37f
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-03-deploy-to-netlify-example-repo-create-fork-page.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-03-deploy-to-netlify-example-repo-create-fork-page.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-03-deploy-to-netlify-example-repo-create-fork-page.snagx
new file mode 100644
index 0000000000..9d97a156f3
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-03-deploy-to-netlify-example-repo-create-fork-page.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-04-deploy-to-netlify-copy-supabase-connection-string.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-04-deploy-to-netlify-copy-supabase-connection-string.png
new file mode 100644
index 0000000000..90fb67a218
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-04-deploy-to-netlify-copy-supabase-connection-string.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-04-deploy-to-netlify-copy-supabase-connection-string.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-04-deploy-to-netlify-copy-supabase-connection-string.snagx
new file mode 100644
index 0000000000..e5338f1afb
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-04-deploy-to-netlify-copy-supabase-connection-string.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-05-deploy-to-netlify-netlify-init-configure-site.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-05-deploy-to-netlify-netlify-init-configure-site.png
new file mode 100644
index 0000000000..2989a7c882
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-05-deploy-to-netlify-netlify-init-configure-site.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-05-deploy-to-netlify-netlify-init-configure-site.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-05-deploy-to-netlify-netlify-init-configure-site.snagx
new file mode 100644
index 0000000000..2267e16b13
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-05-deploy-to-netlify-netlify-init-configure-site.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-06-deploy-to-netlify-site-settings.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-06-deploy-to-netlify-site-settings.png
new file mode 100644
index 0000000000..9ddf171eca
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-06-deploy-to-netlify-site-settings.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-06-deploy-to-netlify-site-settings.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-06-deploy-to-netlify-site-settings.snagx
new file mode 100644
index 0000000000..f9ae9c525d
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-06-deploy-to-netlify-site-settings.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-07-deploy-to-netlify-environment-variables-settings.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-07-deploy-to-netlify-environment-variables-settings.png
new file mode 100644
index 0000000000..97f8d42ae8
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-07-deploy-to-netlify-environment-variables-settings.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-07-deploy-to-netlify-environment-variables-settings.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-07-deploy-to-netlify-environment-variables-settings.snagx
new file mode 100644
index 0000000000..64d550ac63
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-07-deploy-to-netlify-environment-variables-settings.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-08-deploy-to-netlify-application-deployed.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-08-deploy-to-netlify-application-deployed.png
new file mode 100644
index 0000000000..050c85a379
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-08-deploy-to-netlify-application-deployed.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-08-deploy-to-netlify-application-deployed.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-08-deploy-to-netlify-application-deployed.snagx
new file mode 100644
index 0000000000..941c2310b7
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-08-deploy-to-netlify-application-deployed.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-09-deploy-to-netlify-application-deployed-call-result.png b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-09-deploy-to-netlify-application-deployed-call-result.png
new file mode 100644
index 0000000000..c86a0a2bed
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-09-deploy-to-netlify-application-deployed-call-result.png differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-09-deploy-to-netlify-application-deployed-call-result.snagx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-09-deploy-to-netlify-application-deployed-call-result.snagx
new file mode 100644
index 0000000000..936008bc12
Binary files /dev/null and b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/images/500-09-deploy-to-netlify-application-deployed-call-result.snagx differ
diff --git a/docs/200-orm/200-prisma-client/500-deployment/201-serverless/index.mdx b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/index.mdx
new file mode 100644
index 0000000000..7aa4a9f808
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/201-serverless/index.mdx
@@ -0,0 +1,16 @@
+---
+title: 'Serverless functions'
+metaTitle: 'Deploy Prisma apps to serverless function (FaaS) providers'
+metaDescription: 'Learn how to deploy your Prisma-backed apps to FaaS providers like AWS Lambda, Netlify, or Vercel Serverless Functions'
+tocDepth: 2
+---
+
+
+
+If your application is deployed via a "Serverless Function" or "Function-as-a-Service (FaaS)" offering and uses a standard Node.js runtime, it is a serverless app. Common deployment examples include [AWS Lambda](/orm/prisma-client/deployment/serverless/deploy-to-aws-lambda) and [Vercel Serverless Functions](/orm/prisma-client/deployment/serverless/deploy-to-vercel).
+
+
+
+## Guides for Serverless Function providers
+
+
diff --git a/docs/200-orm/200-prisma-client/500-deployment/210-module-bundlers.mdx b/docs/200-orm/200-prisma-client/500-deployment/210-module-bundlers.mdx
new file mode 100644
index 0000000000..0452fc3d45
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/210-module-bundlers.mdx
@@ -0,0 +1,19 @@
+---
+title: 'Module bundlers'
+metaTitle: 'Module bundlers (Reference)'
+metaDescription: 'This page gives an overview of the most important things to be aware of when using a module bundler to bundle an application that uses Prisma Client.'
+---
+
+## Overview
+
+_Module bundlers_ bundle JavaScript modules into a single JavaScript file. Most bundlers work by copying over the JavaScript code from a variety of source files into the target file.
+
+Since Prisma Client is not only based on JavaScript code, but also relies on the [**query engine binary file**](/orm/more/under-the-hood/engines#the-query-engine-file) to be available, you need to make sure that your bundled code has access to the binary file.
+
+To do so, you can use plugins that let you copy over static assets:
+
+| Bundler | Plugin |
+| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- |
+| Webpack | [`copy-webpack-plugin`](https://github.com/webpack-contrib/copy-webpack-plugin#copy-webpack-plugin) |
+| Webpack (with [Next.js monorepo](/orm/more/help-and-troubleshooting/help-articles/nextjs-prisma-client-monorepo)) | [`nextjs-monorepo-workaround-plugin`](https://www.npmjs.com/package/@prisma/nextjs-monorepo-workaround-plugin) |
+| Parcel | [`parcel-plugin-static-files-copy`](https://github.com/elwin013/parcel-plugin-static-files-copy#readme) |
diff --git a/docs/200-orm/200-prisma-client/500-deployment/301-edge/450-deploy-to-cloudflare-workers.mdx b/docs/200-orm/200-prisma-client/500-deployment/301-edge/450-deploy-to-cloudflare-workers.mdx
new file mode 100644
index 0000000000..42dffa603a
--- /dev/null
+++ b/docs/200-orm/200-prisma-client/500-deployment/301-edge/450-deploy-to-cloudflare-workers.mdx
@@ -0,0 +1,309 @@
+---
+title: 'Deploy to Cloudflare Workers'
+metaTitle: 'Deploy to Cloudflare Workers'
+metaDescription: 'Learn how to deploy a TypeScript application to Cloudflare Workers that connects to PostgreSQL.'
+---
+
+
+
+Today you'll be deploying a Cloudflare Worker that uses Prisma to save every request to a PostgreSQL database and fetches 20 of the most recent logs.
+
+This guide covers Prisma, TypeScript, PostgreSQL, Prisma Accelerate, and Cloudflare Workers.
+
+
+
+## Prerequisites
+
+- A PostgreSQL database that is publicly accessible
+- [Cloudflare Workers](https://workers.cloudflare.com/) account
+- [Prisma Data Platform](https://console.prisma.io/) account
+- Node.js & npm installed
+- Git installed
+
+## 1. Set up your application
+
+Wrangler is the official Cloudflare Worker CLI. You will use it to develop and deploy to Cloudflare Workers. This guide uses [Wrangler v3](https://developers.cloudflare.com/workers/wrangler/).
+
+Open your terminal and navigate to a location of your choice. First, initialize your project using the [create-cloudflare-cli](https://www.npmjs.com/package/create-cloudflare). To do this, run the following command in your terminal:
+
+```terminal
+npm create cloudflare@latest
+```
+
+This will ask you a few questions.
+
+```terminal
+In which directory do you want to create your application?
+```
+
+Enter the name of your project, for example: `prisma-cloudflare-accelerate`
+
+```terminal
+What type of application do you want to create?
+```
+
+Select the `"Hello World" Worker` option.
+
+```terminal
+Would you like to use TypeScript? (y/n)
+```
+
+We also want to use TypeScript, so answer yes.
+
+```terminal
+Would you like to use git to manage this Worker? (y/n)
+```
+
+We want to use Git, so answer yes.
+
+The command this will create a new project with a minimal preset configuration. Once `create-cloudflare-cli` is done, navigate to the project and open it on your editor of choice.
+
+Next, authenticate the Wrangler CLI with your Cloudflare Workers account. To do this, run the following command in your terminal:
+
+```terminal
+npx wrangler login
+```
+
+You can now verify that you're logged in by running `npx wrangler whoami`.
+
+```terminal
+npx wrangler whoami
+```
+
+## 2. Set up Prisma
+
+Now you're ready to add Prisma to the project.
+
+Install `prisma` as a development dependency:
+
+```terminal
+npm install --save-dev prisma
+```
+
+Next, initialize Prisma in your project with the following command:
+
+```terminal
+npx prisma init
+```
+
+This creates a Prisma schema in `prisma/schema.prisma`.
+
+
+
+**Note:**