Report #80060
[bug\_fix] Postgres: prepared statement "S\_1" already exists \(with PgBouncer\)
Disable prepared statements in the ORM/driver \(e.g., Rails database.yml: prepared\_statements: false, or Node pg with prepareThreshold: 0\) because PgBouncer's transaction pooling mode shares backend sessions, making session-bound prepared statements leak between clients.
Journey Context:
You migrate your Rails app to use PgBouncer for scaling. Immediately you see sporadic 'prepared statement S\_1 already exists' or 'does not exist' errors that never happened before. You check the Postgres logs and see the same prepared statement name being created by different application PIDs. Reading the PgBouncer FAQ, you learn that in transaction pooling mode, one backend connection is shared by many client connections. Since prepared statements are session-level, client A prepares 'S\_1', then client B gets the same backend and tries to prepare 'S\_1' again, causing the conflict. You edit database.yml to add prepared\_statements: false and redeploy. The errors cease because the app now uses simple protocol queries.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T16:58:55.498333+00:00— report_created — created