A Durable Streams protocol server built as a portable pure-Effect (v4) app: the protocol core is written once and each platform is a swappable set of Layers. The same vendored conformance suite validates every host.
See docs/ARCHITECTURE.md for the design and
docs/BUILD-NOTES.md for the Effect v4 specifics and
results.
| Package | What it is |
|---|---|
packages/effect-durable-streams-server |
@humanlayer/durable-streams-effect-server-core — the substrate-agnostic protocol core (domain + 6 substrate Service tags + StreamService engine + HTTP router + in-memory substrate). |
packages/node-durable-streams-server |
@humanlayer/node-durable-streams-server — Node host (@effect/platform-node + in-memory shared store). |
packages/durable-object-durable-streams-server |
@humanlayer/durable-object-durable-streams-server — Cloudflare Workers + Durable Objects host (SQLite, alarms, cross-DO RPC). |
packages/server-conformance-tests |
Vendored @humanlayer/durable-streams-server-conformance-tests (the black-box HTTP oracle). |
bun install
bun run check # typecheck every server package
bun run test # core unit tests (pure domain + StreamService over the in-memory substrate)The root harness (conformance/run.test.ts +
scripts/conformance.sh) is black-box and BYO-server:
bring a server up on :8787, then run the vendored suite against it.
# one command per host (starts the server, runs the suite, tears it down):
bun run conformance:node # Node host
bun run conformance:do # Durable Object host (wrangler dev)
# or BYO-server + run the suite (optionally filter a section for TDD):
# (terminal 1) cd packages/durable-object-durable-streams-server && bun run dev
# (terminal 2)
bun run conformance
CONFORMANCE_TEST_URL=http://localhost:8787 bash scripts/conformance.sh -t "SSE Mode"Both hosts pass 326 / 332 (the 6 skipped are the opt-in metadata-subscription
feature, gated off in conformance/run.test.ts).
flowchart TD
subgraph core["effect-server-core — written once"]
HTTP["routes (HttpRouter) + StreamService engine"]
DOM["domain (pure) + StreamConfig"]
end
subgraph subs["substrate Services — one Layer per platform"]
S["StreamStore / StreamHub / ExpiryScheduler<br/>ForkPeer / StreamMutex / StreamRegistry"]
end
HTTP --> S
S --> NODE["node-server (in-memory shared store, Semaphore mutex)"]
S --> DO["durable-object-server (SQLite, identity mutex, alarm, RPC fork)"]
Porting from a Durable Object to Node cost exactly six small substrate Layers and
a registry; the router, the engine, and every domain/* module are unchanged. The
DO's three donated properties — commit serialization, co-located notification,
per-key lifecycle — are named as Services (StreamMutex = identity, StreamHub =
PubSub, StreamRegistry = reprovide) so the cost of living without them off-DO is
visible and localized.
Built on Effect v4 (effect@4.0.0-beta); HTTP lives in core
effect/unstable/http (no @effect/platform dependency).