Disabling Prepared statements

Direct connections and the shared pooler (Supavisor) in session mode support prepared statements. The dedicated pooler supports them on PgBouncer 1.21 and later. The shared pooler in transaction mode doesn’t support them.

How to disable prepared statements for the shared pooler in transaction mode

Each ORM or library configures prepared statements differently. Here are settings for some common ones. If you don’t see yours, make a comment

Prisma:

add ?pgbouncer=true to end of connection string:

postgres://[db-user].[project-ref]:[db-password]@aws-0-[aws-region].pooler.supabase.com:6543/[db-name]?pgbouncer=true

Drizzle:

Add a prepared false flag to the client:

export const client = postgres(connectionString, { prepare: false })

Node Postgres

Omit the “name” value in a query definition:

const query = {
name: 'fetch-user', // <--------- DO NOT INCLUDE
text: 'SELECT * FROM user WHERE id = $1',
values: [1],
}

Psycopg

set the prepare_threshold to None.

asyncpg

Follow the recommendation in the asyncpg docs

disable automatic use of prepared statements by passing statement_cache_size=0 to asyncpg.connect() and asyncpg.create_pool() (and, obviously, avoid the use of Connection.prepare());

JDBC

Set prepareThreshold to 0:

jdbc:postgresql://[POOLER-HOST]:6543/postgres?prepareThreshold=0

Rust’s Deadpool or tokio-postgres:

Go to the GitHub discussion