# 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. Use the direct connection string for anything that relies on prepared statements. Session state survives because there is no pooler in the middle.
2. Or disable client-side preparation (psycopg3: `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.