serving event streams
serving event streams
he emitting side of the firehose — what a PDS or jetstream-class service
does so that consumers get a resumable, ordered stream.
evidence from two zig implementations:
zds, a PDS (the subscribeRepos emitter),
and stream, a reimplementation of
bluesky's jetstream (the JSON-simplified firehose mirror) — which inherited
twelve incident-derived rules from zlay,
a relay (docs/lessons-from-zlay.md).
precompute frames at commit time
zds builds each event frame once, inside the write transaction, and stores it
verbatim in seq_events(seq, did, commit_cid, evt) (store.zig:2008).
subscribeRepos streams stored bytes; it never re-encodes on the hot path,
and a replay from cursor N serves exactly the bytes a live subscriber saw.
durability before emission
never broadcast a seq a subscriber could try to replay before it's durable.
the working shape is an atomic committed_seq watermark that emission reads —
zlay's alternative (broadcasting from inside the flush) "serialized 2,670
producers and OOM'd" (stream/docs/lessons-from-zlay.md #3,
stream/archive.zig).
fan out by letting readers pull
stream keeps one bounded deque of encode-once frames; each subscriber thread
reads at its own index and blocks on a condvar at the tip (tail.zig:1-9).
there are no per-subscriber queues, so a slow reader costs nothing but its own
lag — backpressure can't propagate from one consumer to the ingest path or to
other consumers. filters apply at read time and swap atomically on
options_update (server.zig:63-77).
the cursor contract has sharp edges
jetstream v1's /subscribe cursor semantics, as actually implemented
(stream/docs/upstream-subscribe-protocol.md, server.zig:104-113,
tail.zig:98-108):
- absent → live tail; malformed or negative → HTTP 400 before the upgrade
- future cursor → silently live; cursor 0 → floored to the first event
- too-old cursor → silently clamped to the oldest retained event — a consumer that was offline past the retention window resumes with a gap and no error
- replay is inclusive-overlapping (first event with
witnessed_at >= cursor); clients are expected to dedupe
a durable upstream cursor needs the same honesty: stream fsyncs its cursor on
a 5s interval and documents the consequence plainly — "at-least-once on
restart within the flush window" (cursor.zig:6-10).
drop, count, never crash — and never log per-event
hostile or malformed input is table stakes on a public stream. stream's
validation gate drops a bad op (or event) and increments a per-reason counter
(dropped_events_total{reason=...}), with no log line — "hostile input must
not drive log volume" (convert.zig, docs/upstream-harness.md:29).
relatedly: a create whose record block is missing from the CAR is spec-legal —
drop that op, keep the event.
count what your checks do
verification counters exist to prove verification is verifying — "a check
that silently passes everything is indistinguishable from a working one
without them" (stream/metrics.zig:4-7). same family: a
build_info{git_sha} metric proves which binary is even running.
sources
- zds —
src/atproto/store.zig(seq_events),src/http/sync.zig(hand-rolled websocket write path) - stream —
tail.zig,server.zig,convert.zig,cursor.zig,docs/upstream-subscribe-protocol.md,docs/lessons-from-zlay.md - event stream spec
Did you enjoy this article?
Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.