
Every prompt, tool call, and generation is appended at a known offset on a persistent, real-time stream. Replay from any offset, branch off, or fan out to humans, agents, and Electric Agents — over plain HTTP.
Streams aren't single-consumer. Any number of agents — and humans — can attach to the same stream, see each other's events as they land, and pick up exactly where they left off. The shared stream is the coordination layer.
Four curl commands. Create a stream, append a message, read it back, then tail it live.
Install the client, create a stream, and start appending events. Subscribe live from anywhere on the network.
Go deeper on Electric Streams, the Durable Streams protocol, and what teams are building on them.
SSE drops on a refresh. Tokens get lost on flaky networks. Resuming means re-running the request and re-billing the LLM.
Real apps need streams that survive disconnects, persist across sessions, and let many users and agents read and write the same conversation. That's what an Electric Stream is.
Electric Streams is a protocol, not a SaaS. The protocol is the product.
Every stream lives at its own URL. Works with curl, fetch, any load balancer, any CDN.
Once data is at an offset, it never changes. Offsets are opaque cursors that always sort in order.
Reads return Stream-Next-Offset. Reconnect with ?offset=… and pick up exactly where you left off.
Producers identify themselves with three headers. Servers de-dupe. Clients resume from the last offset they saw. No external coordination required.
If your runtime can speak HTTP, it can read and write an Electric Stream. No SDK lock-in. No proprietary transport. No WebSocket infrastructure.
Pick the layer you need. Bytes → JSON messages → typed CRUD events → reactive type-safe DB. Every layer above adds power; every layer below remains available.
Append bytes, replay from any offset. The HTTP base protocol every other layer is built on.
Append JSON values, GET arrays. Message boundaries are preserved on the wire — no framing logic in your code.
Typed insert / update / delete events on the wire, plus snapshot markers. Materialise them into a live key-value view.
Live, typed collections with queries and optimistic actions, layered on top of MaterializedState.
Electric Streams is one implementation. The protocol spec, conformance suite and reference clients live on durablestreams.com — independent, fully open.
From token streams to multi-agent collaboration — Electric Streams plugs into the AI stack you already use.
Self-host the server with one binary, or run it on Electric Cloud. Producers and consumers are anything that speaks HTTP.
import { DurableStream, IdempotentProducer } from "@durable-streams/client"
const handle = await DurableStream.create({
url: STREAM_URL,
contentType: "application/json",
})
const producer = new IdempotentProducer(
handle, "llm-relay-1", { autoClaim: true }
)
for await (const chunk of llm.stream(prompt))
producer.append(chunk)
await producer.flush()Create a stream. Append a message. Subscribe live. Three steps, one package, real APIs.
import { DurableStream, stream } from "@durable-streams/client"
const url = "https://streams.example.com/v1/stream/chat"
const handle = await DurableStream.create({
url,
contentType: "application/json",
})
await handle.append(JSON.stringify({
role: "user", text: "Hello"
}))
const res = await stream<{ role: string; text: string }>({
url,
offset: "-1",
live: "sse",
})
res.subscribeJson(async (batch) => {
for (const msg of batch.items) console.log(msg)
})DurableStream for read/write handles. stream() for fetch-style consumption.
DurableStream.create opens or createsIdempotent: returns the existing handle if the stream already exists.
application/json enables JSON mode — message boundaries are preserved.
Each append is a single POST. Wrap with IdempotentProducer for exactly-once delivery and batching.
"-1" = beginning. Pass a saved offset to resume from exactly that point. "now" = skip the backlog.
"sse" opens a long-lived Server-Sent Events stream. "long-poll" works in environments that can't hold a connection open.
subscribeJson calls your handler with a batch.items array. The batch carries the next offset — save it to resume from later.
Reference apps you can clone, run locally, and learn from.

Doom on Durable Streams. Live spectating, time-travel, and fork-to-continue — all client-side, no backend.

Collaborative rich text editor where an AI agent is a server-side CRDT peer.

Multiplayer territory capture game built with Yjs CRDTs on Durable Streams.
Create a stream, append events, subscribe live.