What I love about this is the detection method—it's highly reusable because it works before you even know the cause. If per-query cost doesn't scale with payload/result size, it's a round-trip problem. Period.
You can diagnose this with just two numbers:
1. TCP RTT from app to DB (ss -ti, 47 ms here)
2. Server-side time per statement from pg_stat_statements (9.6s total for 4M DEALLOCATE ALL calls—essentially nothing)
A client time of 240 ms vs near-zero server time with a 47 ms RTT implies 4–5 crossings. The call counts in pg_stat_statements (BEGIN, DEALLOCATE ALL, COMMIT all at ~4M) immediately expose what those extra crossings are.
It's worth noting the configuration context. Prisma frames pgbouncer=true as a transaction-mode requirement due to named prepared statement limitations in poolers. Supabase recommends the session-mode string for server-based setups and the port-6543 transaction-mode string for serverless. So the config made sense for a different infrastructure shape.
Also, a good footnote for the writeup: Prisma now explicitly recommends not setting pgbouncer=true if you're on PgBouncer 1.21.0+. Handy alternative escape route if you aren't using Supavisor.
What I love about this is the detection method—it's highly reusable because it works before you even know the cause. If per-query cost doesn't scale with payload/result size, it's a round-trip problem. Period. You can diagnose this with just two numbers:
A client time of 240 ms vs near-zero server time with a 47 ms RTT implies 4–5 crossings. The call counts in pg_stat_statements (BEGIN, DEALLOCATE ALL, COMMIT all at ~4M) immediately expose what those extra crossings are. It's worth noting the configuration context. Prisma frames pgbouncer=true as a transaction-mode requirement due to named prepared statement limitations in poolers. Supabase recommends the session-mode string for server-based setups and the port-6543 transaction-mode string for serverless. So the config made sense for a different infrastructure shape. Also, a good footnote for the writeup: Prisma now explicitly recommends not setting pgbouncer=true if you're on PgBouncer 1.21.0+. Handy alternative escape route if you aren't using Supavisor.[flagged]