# Works direct, fails pooled: the session-feature check

## Symptom
A query or flow works from `psql` or a local script but fails from the application, with errors about relations not found, listeners never firing, or prepared statements missing.

## Cause
`psql` used the direct string; the app uses the pooled string. PgBouncer transaction mode does not support SET/RESET, LISTEN/NOTIFY, WITH HOLD cursors, PREPARE/DEALLOCATE, qualifying temp tables, LOAD, or session-level advisory locks. The classic is `SET search_path` appearing to work then failing on the next transaction.

## Confirm
1. Compare the two connection strings: `-pooler` in the app's hostname, absent in psql's.
2. Run the exact failing sequence in `psql` on the pooled string; it reproduces there.
3. Scan the code for SET, LISTEN, PREPARE, advisory locks.

## Fix
- Schema-qualify queries instead of SET search_path, or set it at role level with ALTER ROLE.
- Move LISTEN/NOTIFY, advisory locks, and prepared-statement workloads to the direct string.
- Keep everything else on pooled.

## Verify
The failing flow passes on the chosen string under concurrency, not just once.