Cloudflare Workers
A Worker cannot hold a stream open. A Durable Object can — and that single fact is the product.
BridgeHook forwards a webhook from the public internet to your localhost by holding a Server-Sent Events stream open to a browser tab. The stream is the product — and a Worker has a 30-second CPU limit per request, so an SSE connection held in a Worker dies.
Durable Objects are the answer, and not as a workaround. A Durable Object is a single addressable instance with its own state that can hold connections indefinitely and hibernate when nothing is happening. One per channel, woken by an incoming webhook, asleep the rest of the day.
Hibernation is what makes leaving a bridge open all day cost nothing.
The Worker is stateless and finishes in milliseconds. The Durable Object holds the long-lived connection and sleeps between events. Neon Postgres stores every request and response, which is what turns a tunnel into an observability layer. The relay has no key to your machine — it can only deliver bytes to a tab holding the channel secret, and the secret was generated in your browser, hashed with SHA-256 before it was ever sent, and is compared in constant time.
Durable Objects give you a single-instance, consistent, addressable actor at the edge. Most edge platforms give you stateless functions and tell you to go elsewhere for coordination.
A connection that costs nothing while idle is what makes “leave it open all day” a reasonable thing to offer for free.
The dashboard and the docs site are static builds on Pages. There is no server to run for the part that does not need one.
Anything wanting a long-running process, a big dependency tree, or a normal Postgres connection pool. The runtime is not Node, and pretending otherwise is how people end up fighting it.
I searched for the article and it is not in anything I can reach, so nothing here quotes it.
- Where I looked
~/devand this repo, every markdown file in them, the GitHub repositories and gists. The four article repositories on disk are bachs, language, mcp and t3code — each one blog assets and figures, with no Cloudflare piece among them. - What this page is insteadBuilt from the code: BridgeHook’s relay, its
wrangler.toml, and the Durable Object that holds the stream. Everything above is checkable against the repository. - What I would addSend me the link and the argument goes in properly, quoted and attributed. Writing the thesis for you from memory would be putting words in your mouth on your own portfolio.
Close the tab and the bridge dies. There is no daemon left behind.
BridgeHook, on the flip side of removing the installbridgehook — relay/
relay/src/channel-do.ts is the Durable Object and it is about a hundred lines. relay/src/index.ts is the Worker. Note the repo ships no tests and the hosted domain does not currently resolve — both stated on the project page.
The constraint came first, and the architecture followed from it.
That is the honest order. I did not choose Durable Objects and find a use; I hit a 30-second ceiling and there was exactly one thing on the platform that could hold a connection past it.