<TopBlock>

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).

:::warning

This guide focuses on **relational databases** and how to configure and tune the Prisma ORM connection pool (MongoDB uses the MongoDB driver connection pool).

:::

</TopBlock>

## 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**.

:::info

`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/generated/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/generated/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()
```

## Connections Created per CLI Command

In local tests with Postgres, MySQL, and SQLite, each Prisma CLI command typically uses a single connection. The table below shows the ranges observed in these tests. Your environment *may* produce slightly different results.

| Command | Connections | Description |
|---------|-------------|-------------|
| [`migrate status`](/orm/reference/prisma-cli-reference#migrate-status) | 1 | Checks the status of migrations |
| [`migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev) | 1–4 | Applies pending migrations in development |
| [`migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) | 1–2 | Compares database schema with migration history |
| [`migrate reset`](/orm/reference/prisma-cli-reference#migrate-reset) | 1–2 | Resets the database and reapplies migrations |
| [`migrate deploy`](/orm/reference/prisma-cli-reference#migrate-deploy) | 1–2 | Applies pending migrations in production |
| [`db pull`](/orm/reference/prisma-cli-reference#db-pull) | 1 | Pulls the database schema into the Prisma schema |
| [`db push`](/orm/reference/prisma-cli-reference#db-push) | 1–2 | Pushes the Prisma schema to the database |
| [`db execute`](/orm/reference/prisma-cli-reference#db-execute) | 1 | Executes raw SQL commands |
| [`db seed`](/orm/reference/prisma-cli-reference#db-seed) | 1 | Seeds the database with initial data |

## 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**:

![An AWS Lambda function connecting to a database.](./serverless-connections.png)

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:

![Three AWS Lambda function connecting to a database.](./serverless-connections-2.png)

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:

<TabbedContent code>
<TabItem value="PostgreSQL">

```
postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=public&connection_limit=1
```

</TabItem>
<TabItem value="MySQL">

```
mysql://USER:PASSWORD@HOST:PORT/DATABASE?connection_limit=1
```

</TabItem>
</TabbedContent>

:::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/generated/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 ORM).

#### 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

:::note

As of Prisma ORM v7, [driver adapters](/orm/overview/databases/database-drivers) are the default for relational databases, providing better performance and developer experience. Learn more [here](/orm/prisma-client/setup-and-configuration/no-rust-engine).

**In Prisma ORM v7, the default generator configuration uses driver adapters**:

```prisma
generator client {
  provider = "prisma-client"
  output   = "../generated/prisma"
}
```

With driver adapters, connection pool configuration is handled by the Node.js driver you provide (like `pg`, `mariadb`, or `mssql`). See the [connection pool guide](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) for v7 defaults and configuration details.

Prisma ORM also has its own configurable timeouts that are separate from the database driver timeouts. If you run into a timeout error and are unsure whether it comes from the specific driver or from Prisma Client, see the [Prisma Client timeouts and transaction options documentation](/orm/prisma-client/queries/transactions#transaction-options).

You can [read about the performance and DX improvements](https://www.prisma.io/blog/prisma-orm-without-rust-latest-performance-benchmarks) of this change on our blog.

:::


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.

To keep Prisma Client on the pooled connection while allowing Prisma CLI commands (for example, migrations or introspection) to connect directly, define two environment variables:

```env file=.env highlight=4-6;add showLineNumbers
# 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 Prisma CLI commands.
DIRECT_URL="postgres://root:password@127.0.0.1:5432/postgres"
```

Configure `prisma.config.ts` to point to the direct connection string. Prisma CLI commands always read from this configuration.

```ts file=prisma.config.ts showLineNumbers
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config'

export default defineConfig({
  schema: 'prisma/schema.prisma',
  datasource: {
    url: env('DIRECT_URL'),
  },
})
```

At runtime, instantiate Prisma Client with a driver adapter (for example, `@prisma/adapter-pg`) that uses the pooled connection string:

```ts file=src/db/client.ts showLineNumbers
import { PrismaClient } from '../prisma/generated/client'
import { PrismaPg } from '@prisma/adapter-pg'

const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL })
export const prisma = new PrismaClient({ adapter })
```

### 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.
---

# Custom model and field names