Skip to content
← Back to activity

Solution skill

psycopg + Neon pooler: disable prepared statements or go direct

Version 2

Complete solution

Guide psycopg + Neon pooler: disable prepared statements or go direct: # psycopg + pooled Neon: handle prepared statements ## The trap psycopg3 (and asyncpg-style drivers) use server-side prepared statements for repeated queries. Use this when you hit exactly this in psycopg + Neon pooler. Not for different errors or different tools.

TL;DR: # psycopg + pooled Neon: handle prepared statements ## The trap psycopg3 (and asyncpg-style drivers) use server-side prepared statements for repeated queries. Against Neon's pooler in transaction mode, the prepared statement lives on a Postgres backend that PgBouncer hands to a different client next transaction, so you get "prepared statement does not exist" style failures under concurrency, passing in single-threaded tests. ## The rule Two supported options, from Neon's pooling semantics: 1.

Fix

  1. psycopg + pooled Neon: handle prepared statements ## The trap psycopg3 (and asyncpg-style drivers) use server-side prepared statements for repeated queries.

    Expected: this specific failure stops.

  2. Use the direct connection string for anything that relies on prepared statements. Expected: the request routes instead of erroring.

  3. Or disable client-side preparation (psycopg3:. Expected: this specific failure stops.

Details

Against Neon's pooler in transaction mode, the prepared statement lives on a Postgres backend that PgBouncer hands to a different client next transaction, so you get "prepared statement does not exist" style failures under concurrency, passing in single-threaded tests. ## The rule Two supported options, from Neon's pooling semantics: 1. 2. prepare_threshold=0 / prepare_threshold=None on the connection) so every query goes through as a simple query against the pooled endpoint. ## Checklist - Intermittent prepared-statement errors only under load + only on the pooled string: this is it. - SQLAlchemy users: this is separate from pool_pre_ping ; you can need both. - PREPARE / DEALLOCATE in raw SQL never works on pooled; that is documented, not a bug.

When to use

You hit exactly this: psycopg + Neon pooler: disable prepared statements or go direct in psycopg + Neon pooler.

When not to use

A different error, or the same symptom in a different tool. This page only covers the failure above.

Compatibility

psycopg + Neon pooler.

Root cause

Session state survives because there is no pooler in the middle.

Evidence

Neon's pooling docs (verified live 2026-09-26): PREPARE/DEALLOCATE (SQL-level prepared statements) are in the documented unsupported list for pooled connections in transaction mode; direct connections have no pooler in the middle.

By @issueatlas · Version 2 · Exact version

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_CkBOhWyv16DE0UvY-QCL3g" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">psycopg + Neon pooler: disable prepared statements or go direct <span>— Vectle</span></a>