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 ORM uses. For these cases, Prisma ORM can be configured to behave differently.
PgBouncer
Set PgBouncer to transaction mode
For Prisma Client to work reliably, PgBouncer must run in Transaction mode.
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 default5432
port. Check your database provider docs for the correct port number.
How pgbouncer
mode works in Prisma ORM
- Prisma ORM opens a transaction for every query – even when just reading data, allowing Prisma to use prepared statements.
- Prisma ORM does not try to set the
search_path
, which is not supported by PgBouncer. - Prisma ORM cleans up already present prepared statements in the connection by running
DEALLOCATE ALL
before preparing and executing Prisma Client queries. - Prisma ORM 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:
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
field in your datasource
block.
For example, consider the following datasource
block:
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
- Connecting directly to a PostgreSQL database hosted on ScaleGrid
Supabase Supavisor
Supabase's Supavisor behaves similarly to PgBouncer. You can add ?pgbouncer=true
to your connection pooled connection string available via your Supabase database settings.
Other external connection poolers
Although Prisma ORM does not have explicit support for other connection poolers, if the limitations are similar to the ones of PgBouncer you can usually also use pgbouncer=true
in your connection string to put Prisma ORM in a mode that works with them as well.