Why we didn't use Hyperdrive
· AKHBaig
The premise we had to check
When we looked at deploying the AutoSugges control plane to Cloudflare Workers, the working assumption was that Cloudflare Hyperdrive was required to reach PostgreSQL at all — every server-side data-access module in apps/web builds its SQL executor over postgres, a raw TCP driver, and raw TCP was believed unavailable on Workers.
That premise turned out to be false, and we checked it rather than argued it. postgres@3.4.9 ships a first-class workerd export whose polyfill opens connections with connect() from cloudflare:sockets. A probe run inside a workerd test pool opened a socket straight to the Supabase transaction pooler, sent the PostgreSQL SSLRequest packet, and got S back — SSL supported. Outbound TCP from a Worker to Postgres just works.
Why we still didn’t adopt Hyperdrive
Hyperdrive is a pooling and caching optimization, not a prerequisite — and adopting it anyway would have cost more than it bought.
- It changes a boundary for no proven gain. Hyperdrive supplies its connection string through a Worker binding, not an environment variable, which would ripple a contract change into every data-access module in the app.
- next dev has no bindings, so a binding-shaped contract needs a second, conditional connection path for local development — meaning the path that runs in production is not the one anyone develops against.
- Supabase's own pooler already pools; Hyperdrive would place a second pool in front of a pool, with neither measured.
- And plainly: YAGNI. A product, a binding, a config resource and a per-environment id, added against a problem nobody had actually observed.
The bug that was actually there
The investigation assumed a connection-pressure risk: many short-lived Workers isolates hammering the pooler. That framing was wrong, and it was wrong immediately rather than under load. A socket opened through cloudflare:sockets belongs to the request that opened it. A module-scoped connection cache — the ordinary Node.js pattern of caching a pool at module scope — hands a later request a socket that belongs to an earlier request's I/O context. workerd will not deliver on it, the driver awaits a reply that never comes, and the request hangs until the runtime cancels it.
That surfaced as a Cloudflare 1101 on roughly 30 to 50 percent of requests to every database-backed route on deployed staging — not an exception, not a connection error, and nothing in the application logs, because nothing had thrown.
The fix was a per-request connection rather than a per-module one, closed explicitly at the end of the request. Hyperdrive would not have fixed this either way — the fault was connection lifetime against the isolate model, not pooling. On Workers, a connection's lifetime is a correctness constraint before it is a performance one.