Production void/db (Postgres/Hyperdrive) caches pg.Pool across requests → Worker hangs (1101) on every request after the first

Open Beginner friendly
#74 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
postgresql, typescript

Research direction

Start in void/dist/index.mjs at the dialect === "postgresql" template and compare the production branch of getInstance() with the local branch. Reproduce repeated requests against a warm Cloudflare Workers isolate using database: "pg" and verify that DB-backed routes no longer hang after the first request.】【。

Written by the indexing model from the issue text.

Description

With database: "pg", the generated prod void/db caches its pg.Pool in module scope and reuses it across requests. That doesn't work on workerd: a TCP socket belongs to the request that opened it and is dead by the next one, so any query after the first in a warm isolate hangs and Cloudflare kills the request with:

1101 — "The Workers runtime canceled this request because it detected that your Worker's code had hung and would never generate a response."

In practice every DB-backed route 500s in prod as soon as the isolate warms up. no-DB routes are fine; the first request after a cold start works, everything after it hangs.

The generated module (void/dist/index.mjs, the dialect === "postgresql" template):

let _prodInstance;

function getInstance() {
  if (getRuntimeBinding("DATABASE_URL")) {
    // local dev: fresh pool per chain, because workerd kills sockets between requests
    return drizzle(new pg.Pool({ connectionString: getRuntimeBinding("DATABASE_URL"), max: 1 }), { schema });
  }
  // prod (Hyperdrive): cached across requests
  _prodInstance ??= drizzle(getConnectionString(), { schema });
  return _prodInstance;
}

The local branch comment already mentions the problem ("workerd kills TCP sockets between requests, so pg.Pool's cached connections go stale and hang").

Fix is to drop the cache and do what the local branch does:

function getInstance() {
  return drizzle(new pg.Pool({ connectionString: getConnectionString(), max: 1 }), { schema });
}

Hyperdrive pools on the origin side anyway, so a fresh pool per chain is cheap. We're running this as a pnpm patch against void@0.9.2 and it fixes the outage.

Env: void@0.9.2, database: "pg" over Hyperdrive, deployed to Cloudflare Workers.

Dominant language
TypeScript
Stars
149
Forks
2
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from void-sdk/void

All issues in void-sdk/void

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.