#50358·supabase

Hosted transaction pooler reproduces dropped pipelined replies addressed by Supavisor #1079/#1176

Author: alanxchen85Created Sep 14, 2026Updated Sep 16, 2026
Labelsbugsupavisorexternal-issue

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

I searched the Supabase documentation and existing GitHub issues. The closest existing report is supabase/supavisor#1061, with fixes merged in supabase/supavisor#1079 and the follow-up supabase/supavisor#1176.

Describe the bug

The hosted Supabase transaction pooler on port 6543 still reproduced the dropped-reply/hanging-client behavior described in supabase/supavisor#1061.

A postgres.js 3.4.7 client using prepare: false and max_pipeline: 1 sent another extended-query batch before receiving ReadyForQuery for the preceding batch. In the captured failing run, the frontend sent 11 Parse/Describe sequences, but only 10 corresponding ParseComplete/ParameterDescription replies returned. The outstanding postgres.js promise then waited indefinitely.

This appears consistent with the backend being released after an earlier ReadyForQuery while replies from a later pipelined batch are still outstanding—the behavior addressed by supabase/supavisor#1079 and supabase/supavisor#1176.

This affected ordinary read-only application queries. Prepared statements were disabled.

To Reproduce

Client shape:

import postgres from 'postgres'

const sql = postgres(process.env.DATABASE_URL, {
  max: 1,
  prepare: false,
  ssl: 'require',
  max_pipeline: 1,
})

// Six independent read-only SELECTs are started concurrently by one loader.
await Promise.all([read1(sql), read2(sql), read3(sql), read4(sql), read5(sql), read6(sql)])
  1. Use the hosted transaction-pooler connection string on port 6543.
  2. Run six distinct unprepared read-only queries concurrently on one postgres.js connection.
  3. Repeat the loader call. Our incident harness used 20 uncached calls with a 12-second deadline.
  4. Trace frontend Parse/Describe/Sync and backend ParseComplete/ParameterDescription/ReadyForQuery messages.
  5. With max_pipeline: 1, we captured a missing reply and a permanently unresolved client promise.

Our public application workaround and regression harness are in alanxchen85/gradschooldb#1581:

The deterministic local gate has a max_pipeline: 1 canary that strands and records the dropped frame. The hosted acceptance gate verifies the workaround at client pool sizes 1 and 5.

Expected behavior

The hosted transaction pooler should retain the backend until every expected ReadyForQuery has arrived and return every reply to the client. Concurrent ordinary queries should either complete or fail explicitly; they should not leave a postgres.js promise unresolved.

Screenshots

Not applicable. The useful evidence is the PostgreSQL protocol trace and the linked executable regression harness.

System information

  • Client OS: macOS
  • Deployment environment affected: Vercel Linux functions/builds
  • Client library: postgres.js 3.4.7
  • Node.js: 22.22.3
  • Supabase connection: hosted shared transaction pooler, port 6543
  • Client options: prepare: false, TLS required

Additional context

Our current client-side workaround disables postgres.js pipelining with max_pipeline: 0. Because postgres.js 3.4.7 does not run the sql.begin() reservation hook correctly at that limit, our application also carries a small ordering patch. With that workaround:

  • pool size 1: 20 loader calls x 6 queries = 120/120 completed
  • pool size 5: 20 loader calls x 6 queries = 120/120 completed
  • zero hangs, zero dropped replies, balanced protocol counters
  • p95 below 3 seconds in both hosted-pooler acceptance runs

We are not proposing that client patch as the Supabase fix. We would like to establish whether the hosted service has received the existing Supavisor fixes.

Could Supabase confirm:

  1. Which Supavisor version is currently deployed to hosted shared transaction poolers?
  2. Does the hosted deployment include supabase/supavisor#1079 and supabase/supavisor#1176?
  3. If not, what is the rollout timeline?
  4. If those fixes are already deployed, what additional tenant/region and packet-trace information should we provide privately to support?

We can share the affected project and region privately with Supabase staff, but have intentionally omitted tenant identifiers and connection details from this public report.