Realtime

Replayable Server-Sent Events

Subscribe to committed record events through an authorized, ordered journal rather than an in-memory notification channel.

Browser subscription

const stream = new EventSource(
  `${TRESTLE_URL}/api/v1/realtime?topic=record.created`
);
stream.addEventListener("record.created", event => {
  const envelope = JSON.parse(event.data);
  console.log(envelope.sequence, envelope.recordId);
});

Native EventSource cannot add an Authorization header. Use same-origin cookie infrastructure or a small authenticated server proxy when bearer authentication is required.

Resume after interruption

curl -N "$TRESTLE_URL/api/v1/realtime?topic=record.updated" \
  -H "Authorization: Bearer $TRESTLE_TOKEN" \
  -H "Last-Event-ID: 418"

Trestle replays retained events after sequence 418, then continues live. Clients must tolerate duplicate delivery around reconnect boundaries and refetch authoritative state if their cursor predates retention.

Operational behavior

Slow consumers are disconnected instead of growing unbounded memory. The dashboard retains at most 200 rendered events and can pause display without altering the durable journal.

Dogfood path

The browser consumes authenticated SSE with streaming fetch(), while the clean-start verifier proves journal replay from Last-Event-ID: 0. See the realtime implementation.

Provider storage

The durable event journal sequences identically on both providers. PostgreSQL sequences may allocate numeric gaps; replay treats every committed event as distinct and never mistakes a gap for a missing event. Authorized visibility and Last-Event-ID replay are provider-neutral.