diff --git a/cSpell.json b/cSpell.json index 64e73a0743..13b402dc94 100644 --- a/cSpell.json +++ b/cSpell.json @@ -55,7 +55,8 @@ "backoff", "Replibyte", "Snaplet", - "Kysely" + "Kysely", + "Turso" ], "ignoreWords": [ "Ania", diff --git a/content/200-concepts/100-components/database-drivers.mdx b/content/200-concepts/100-components/database-drivers.mdx new file mode 100644 index 0000000000..6d7a022377 --- /dev/null +++ b/content/200-concepts/100-components/database-drivers.mdx @@ -0,0 +1,54 @@ +--- +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](./prisma-engines/query-engine) . 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. + +![Query flow from the user application to the database with Prisma Client](./images/drivers/qe-query-execution-flow.png) + +## 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. + +![Query flow from the user application to the database using Prisma Client and driver adapters](./images//drivers/qe-query-engine-adapter.png) + +### Serverless driver adapters + +- [Neon](/guides/database/neon#how-to-use-the-neon-serverless-driver-with-prisma-preview) +- [PlanetScale](/guides/database/planetscale#how-to-use-the-planetscale-serverless-driver-with-prisma-preview) + +### Database driver adapters + +- [Turso](/guides/database/turso#connect-and-query-your-primary-database) + +### 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](/guides/database/neon#how-to-use-the-neon-serverless-driver-with-prisma-preview) + - [PlanetScale](/guides/database/planetscale#how-to-use-the-planetscale-serverless-driver-with-prisma-preview) + - [Turso](/guides/database/turso#connect-and-query-your-primary-database) diff --git a/content/200-concepts/100-components/images/drivers/qe-query-engine-adapter.png b/content/200-concepts/100-components/images/drivers/qe-query-engine-adapter.png new file mode 100644 index 0000000000..068f9c76c5 Binary files /dev/null and b/content/200-concepts/100-components/images/drivers/qe-query-engine-adapter.png differ diff --git a/content/200-concepts/100-components/images/drivers/qe-query-execution-flow.png b/content/200-concepts/100-components/images/drivers/qe-query-execution-flow.png new file mode 100644 index 0000000000..aca500b4fe Binary files /dev/null and b/content/200-concepts/100-components/images/drivers/qe-query-execution-flow.png differ diff --git a/content/300-guides/050-database/850-planetscale.mdx b/content/300-guides/050-database/850-planetscale.mdx index d919317118..5706f7c9e3 100644 --- a/content/300-guides/050-database/850-planetscale.mdx +++ b/content/300-guides/050-database/850-planetscale.mdx @@ -225,6 +225,74 @@ model User { 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 { connect } 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 connection = connect({ url: connectionString, fetch: undiciFetch }) +const adapter = new PrismaPlanetScale(connection) +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: diff --git a/content/300-guides/050-database/890-neon.mdx b/content/300-guides/050-database/890-neon.mdx new file mode 100644 index 0000000000..1b74ac4d6a --- /dev/null +++ b/content/300-guides/050-database/890-neon.mdx @@ -0,0 +1,174 @@ +--- +title: 'Using Prisma with Neon' +metaTitle: 'Using Prisma with Neon' +metaDescription: 'Guide to using Prisma with 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's logo + +[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](/concepts/components/prisma-schema) +- use Prisma's [`postgresql` database connector](/concepts/database-connectors/postgresql) in your schema, along with the [connection string Neon provides you](https://neon.tech/docs/connect/connect-from-any-app) +- use [Introspection](/concepts/components/introspection) for existing projects if you already have a database schema on Neon +- use [`prisma migrate dev`](/concepts/components/prisma-migrate/migrate-development-production) to track schema migrations in your Neon database +- use [`prisma db push`](/concepts/components/prisma-migrate/db-push) to push changes in your schema to Neon +- use [Prisma Client](/concepts/components/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](/reference/api-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](https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/), 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](/concepts/components/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 +``` + +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/content/300-guides/050-database/900-turso.mdx b/content/300-guides/050-database/900-turso.mdx new file mode 100644 index 0000000000..8c14deec49 --- /dev/null +++ b/content/300-guides/050-database/900-turso.mdx @@ -0,0 +1,213 @@ +--- +title: 'Using Prisma with Turso' +metaTitle: 'Using Prisma with Turso (Early Access)' +metaDescription: 'Guide to using Prisma with 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](/about/prisma/releases#early-access). We would appreciate your feedback in this [GitHub discussion](https://github.com/prisma/prisma/discussions/21345). + + + +## What is Turso? + +Turso's logo + +[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](/about/prisma/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](/concepts/components/prisma-schema) +- use Prisma's existing [`sqlite` database connector](/concepts/database-connectors/sqlite) in your schema +- use [Prisma Client](/concepts/components/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`](/reference/api-reference/command-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: + +![Embedded Replica: First remote read](./images/embedded-replica-remote-read.png) + +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: + +![Embedded Replica: Remote DB Copy](./images/embedded-replica-create-replica.png) + +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. + +![Embedded Replica: Local DB reads](./images/embedded-replica-read.png) + +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. + +![Embedded Replica: Write operation propagation](./images/embedded-replica-write-propagation.png) + +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/content/300-guides/050-database/images/embedded-replica-create-replica.png b/content/300-guides/050-database/images/embedded-replica-create-replica.png new file mode 100644 index 0000000000..830501d9c2 Binary files /dev/null and b/content/300-guides/050-database/images/embedded-replica-create-replica.png differ diff --git a/content/300-guides/050-database/images/embedded-replica-read.png b/content/300-guides/050-database/images/embedded-replica-read.png new file mode 100644 index 0000000000..0edaebcf2e Binary files /dev/null and b/content/300-guides/050-database/images/embedded-replica-read.png differ diff --git a/content/300-guides/050-database/images/embedded-replica-remote-read.png b/content/300-guides/050-database/images/embedded-replica-remote-read.png new file mode 100644 index 0000000000..7762e8bfaa Binary files /dev/null and b/content/300-guides/050-database/images/embedded-replica-remote-read.png differ diff --git a/content/300-guides/050-database/images/embedded-replica-write-propagation.png b/content/300-guides/050-database/images/embedded-replica-write-propagation.png new file mode 100644 index 0000000000..fa36c87335 Binary files /dev/null and b/content/300-guides/050-database/images/embedded-replica-write-propagation.png differ diff --git a/content/400-reference/200-api-reference/050-prisma-client-reference.mdx b/content/400-reference/200-api-reference/050-prisma-client-reference.mdx index 557a323f1a..d88753b792 100644 --- a/content/400-reference/200-api-reference/050-prisma-client-reference.mdx +++ b/content/400-reference/200-api-reference/050-prisma-client-reference.mdx @@ -376,6 +376,36 @@ const prisma = new PrismaClient({ }) ``` +### adapter + +Defines an instance of a [driver adapter](/concepts/components/database-drivers#driver-adapters). See also [Database drivers](/concepts/components/database-drivers) . + + + +This is available from version 5.4.0 and newer behind the `driverAdapters` feature flag. + + + +#### Example + +The example below uses the [Neon driver adapter](/guides/database/neon#how-to-use-the-neon-serverless-driver-with-prisma-preview) + +```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 }) +``` + ### rejectOnNotFound