Remix.run Logo
Prisma's pgbouncer=true on Supabase made every query 4 round-trips (postmortem)(blog.simbastack.com)
3 points by asenna a day ago | 2 comments
WhenItRuns 2 hours ago | parent | next [-]

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.
asenna a day ago | parent | prev [-]

[flagged]