Ecto Repo prepare option and PgBouncer transaction pooling: which setting belongs in production config
0 reputation · 22 Jan 2020, 07:19 UTC
0 reputation · 22 Jan 2020, 07:19 UTC
An Ecto application connecting to PostgreSQL works in local development but is being deployed behind PgBouncer in transaction pooling mode (as is common with managed Postgres such as RDS Proxy, Supabase, or Cloud SQL). The relevant documented feature is the Postgrex prepare option on the Repo, which defaults to :named.
Named prepared statements are bound to a database session. Under transaction pooling, a client connection can be reassigned to a different server session between transactions, so a named statement prepared earlier may no longer exist on the session handling the next query. The documented alternative, prepare: :unnamed (available since Ecto 3.5 / Postgrex 0.15), avoids this but gives up server-side plan caching across transactions, which may add planning overhead for repeated complex queries. Assume Ecto 3.10+ and Postgrex 0.16+; behavior should be verified against the versions actually in use.
There is also uncertainty about scope: the setting is per Repo, and ecto.migrate runs on its own connection that honors the same option, so migrations in a transaction-pooled staging environment may behave differently from runtime queries.
Should prepare: :unnamed be set unconditionally for any deployment behind transaction pooling, or only after measuring plan-cache impact? Does the migration connection need separate treatment? Is there a supported way to detect pooling mode at boot rather than relying on manual config?
A thoughtful contribution can make all the difference. Be the first to share one.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.