npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

stream-coalescer

v0.2.0

Published

In-flight coalescing cache microservice for streamed service responses

Readme

stream-coalescer

An in-flight coalescing cache for streamed responses. Point several concurrent requests at the same resource and only the first one actually does the work — everyone else piggybacks on it live, catches up on what already streamed, and gets told when it's done.

The gap this fills

Request coalescing (a.k.a. singleflight, collapsed forwarding, dogpile prevention) is a solved problem — for atomic responses. Varnish does it by default. nginx has proxy_cache_lock. Go has singleflight. And pub/sub brokers (Centrifugo, Mercure, Pushpin) solve fan-out with catch-up for already-decided, already-published data.

Neither covers this shape: a client connects, doesn't know if anyone else is already fetching the same thing, and needs to either become the producer or transparently join one already in flight — receiving everything already streamed plus the live tail, over one connection, in one protocol. That's what this is.

How it works

Connect to ws(s)://<service>/v0/<resource-key>. The first connection for a given key becomes the writer by construction — there's no role negotiation, no election, just event-loop ordering. Anyone connected can send data; it gets broadcast to every attached connection (including the sender) and buffered for whoever joins later.

ws1 -> connect /v0/report-42        ws1 <- {"order":1,"data":[]}
ws1 -> {"chunk":"row 1"}            ws1 <- {"data":[{"chunk":"row 1"}]}
                                     ws2 -> connect /v0/report-42
                                     ws2 <- {"order":2,"data":[{"chunk":"row 1"}]}
ws1 -> {"chunk":"row 2"}            ws1 <- {"data":[{"chunk":"row 2"}]}
                                     ws2 <- {"data":[{"chunk":"row 2"}]}
ws1 -> {"end":true}                 ws1 <- {"end":true}  (closes)
                                     ws2 <- {"end":true}  (closes)

ws3 -> connect /v0/report-42        ws3 <- {"order":3,"data":[{"chunk":"row 1"},{"chunk":"row 2"}],"end":true}  (closes)

ws3 joined after the flight already finished — a successful result stays cached for late piggybackers (see maxAgeMs below), so it gets the full catch-up plus the terminal status in one shot instead of triggering a new fetch.

Protocol

Every message is JSON. The connection's first inbound message is the opening frame:

| Field | Type | Meaning | |---|---|---| | order | number | This connection's permanent, never-reused rank for this resource. 1 means you were first. | | data | array | Everything already streamed, in order — empty on a fresh resource. | | end | boolean? | Present and true only if the resource already finished successfully. | | error | {code, msg}? | Present only if the resource already failed. |

After that, any connection may send data — it gets echoed to every attached connection as {"data": [...]}. Sending {"end": true} or {"error": {"code", "msg"}} ends the resource for everyone: every connection gets that exact frame and closes with code 1000.

Synthesized errors — the resource can fail on its own, not just on request:

  • WRITER_GONE — a connection that had sent data disconnected without an end/error.
  • CONNECTION_TIMEOUT — same, but caused by hitting connectionMaxDurationMs rather than a raw drop.
  • END_TIMEOUT — the resource never reached a terminal state within endMaxTimeMs.

A resource that ends in error never lingers — it's torn down immediately so the next request gets a clean retry, not a cached failure.

Quickstart

pnpm add stream-coalescer
pnpm exec stream-coalescer server -l 'http://*:0'
# Web application available at http://0.0.0.0:54321/

Port 0 picks a random free port and prints the real URL — handy for spawning it from a test harness in any language, not just Node: read the URL off stdout, talk WebSocket/HTTP to it, tear it down when done. Unix domain sockets work too: -l 'http+unix:///tmp/stream-coalescer.sock'.

No language lock-in on the client side — it's plain WebSocket framing over HTTP. If your stack can open a WebSocket, it can use this.

Configuration

Three timers, each with a sane default, overridable via config.json in the working directory (no CLI flag needed — just drop the file):

{
  "maxAgeMs": 20000,
  "endMaxTimeMs": 30000,
  "connectionMaxDurationMs": 60000
}
  • maxAgeMs — how long a successfully completed resource stays cached for piggybackers after the last connection leaves. Anchored at resource creation, not renewed by traffic. An errored resource ignores this entirely and is destroyed right away.
  • endMaxTimeMs — the resource-wide ceiling on how long a stream may stay unfinished before it's force-errored (END_TIMEOUT) for everyone attached.
  • connectionMaxDurationMs — a per-connection ceiling; only that one connection gets closed if it's exceeded, not the whole resource.

A concrete use case: coalescing LLM completions

Point several identical concurrent chat/completion requests at one resource key (e.g. a hash of the prompt): only the first caller actually hits the model API and pays for the tokens; every other caller streams the same tokens live, for free, from the one in-flight call. (Cradle does this same trick baked into an LLM-specific gateway — this generalizes it to any streamed resource, as a standalone service any language can talk to.)

Development

pnpm install
pnpm test     # builds, then runs node:test with coverage
pnpm lint
pnpm run dev  # --watch, port 3000

Node >= 22, pnpm. See CHANGELOG.md for release notes.

Security note

There's no auth on the wire protocol — any connection can write. This is meant to run as an internal microservice on a trusted network (e.g. behind a web server that's the only thing talking to it), not exposed directly to untrusted clients.

License

MIT