TraceResolveSRE Platform
MCP ServerAdmin
Back to CatalogPgBouncer / PostgreSQL

PostgreSQL / PgBouncer: Prepared statement "s0" already exists or does not exist

error: prepared statement "s0" already exists (or "unnamed prepared statement does not exist") with PgBouncer transaction pooling
Immediate Remediation
typescript
// In your database client URL or config, disable prepared statements for transaction pooler:
// For Prisma schema.prisma:
datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL") // pooled URL with ?pgbouncer=true
  directUrl = env("DIRECT_URL")   // unpooled URL (port 5432 without pooler)
}

// For node-postgres (pg) or Drizzle:
// Append ?statement_cache_size=0 or pass prepare: false to client pool
Root Cause Analysis

Transaction pooling mode in PgBouncer assigns subsequent queries to different backend connections, causing session-level named prepared statements to desynchronize.

Verification & Guardrails

  • Always provide a directUrl for database migrations (e.g. prisma migrate dev) and a pooled url for runtime queries.
  • In Prisma, append ?pgbouncer=true to the pooled connection string.

Have a custom or uncategorized crash?

Run your trace through our in-memory client privacy sandbox for instant SRE remediation.

Open Diagnostic Studio