Real-time streams with durable history. Powered by open-source, self-hostable infrastructure.
Guide · Announcement · Discord
Durable Streams are an open standard for real-time data streaming with durable history. You write data to a stream, and readers can read from any offset in the stream: catch up from the beginning, resume from where they left off, or tail it live.
They are a good fit for:
- Agent sessions: prompts and responses survive restarts, and clients reconnect without losing a token.
- CRDT sync: a durable, ordered log of updates for collaborative editing with Yjs and similar libraries.
- Database sync: stream changes to every client and replay from any offset.
This repository is the Rivet implementation of the protocol, powered by Rivet Actors. It supports binary and JSON streams, catch-up reads, long polling, SSE, idempotent producers, TTLs, stream closure, forks, and a read-only inspector. Existing Durable Streams clients work unchanged.
- Bottomless SQLite: streams are not capped by a per-object SQLite size limit.
- SSD-backed with S3-tiered storage: hot reads and writes are served from local SSDs, and history is tiered to S3 so storage is cheap, durable, and independent of any single machine.
- Multi-region edge network: each stream lives in the region closest to the clients reading and writing it.
- Same code locally and in production: what runs on your laptop is what runs in production. No mocks and no emulators.
- Built in Rust: the server is native Rust for high-performance streams.
- Open-source and self-hostable: run it in your own VPC or on-prem, so your data stays with you.
Start the server
Already running Rivet Actors with the RivetKit TypeScript SDK? Durable Streams are already available to you on RivetKit 2.3.12 and later. No separate server needed.
Otherwise, start a local Rivet Engine and the Durable Streams server:
npx @rivet-dev/services devYour streams are at http://127.0.0.1:8642/durable-streams/v1/stream/<path>.
Use it via curl
# Create a stream with an initial record
curl -i -X PUT \
-H 'content-type: application/json' \
--data '[{"message":"hello"}]' \
http://127.0.0.1:8642/durable-streams/v1/stream/demo
# Append to it
curl -i -X POST \
-H 'content-type: application/json' \
--data '{"message":"world"}' \
http://127.0.0.1:8642/durable-streams/v1/stream/demo
# Read from the beginning
curl 'http://127.0.0.1:8642/durable-streams/v1/stream/demo?offset=-1'Use it via TypeScript
Install the official client:
npm install @durable-streams/clientimport { DurableStream } from "@durable-streams/client";
const stream = await DurableStream.create({
url: "http://127.0.0.1:8642/durable-streams/v1/stream/demo",
contentType: "application/json",
});
await stream.append(JSON.stringify({ message: "hello" }));
const res = await stream.stream<{ message: string }>();
res.subscribeJson(async (batch) => {
for (const item of batch.items) {
console.log(item.message);
}
});Durable Streams runs as a single service on Rivet Cloud or on your own Rivet Engine. See the integration guide for both.
- Integration guide: run locally, deploy to Rivet Cloud, or self-host.
- Announcement post: why Durable Streams on Rivet, and how it works.
- Durable Streams protocol: the full protocol, JSON mode, StreamDB, and the Yjs, TanStack AI, and Vercel AI SDK integrations.
- Discord: questions and support.
See CONTRIBUTING.md for running the server from source and testing.
Apache 2.0