hydrant

jetstream stream

created 5 days ago :: modified 5 days ago :: 3.88 KB .md

Tools

download raw

hydrant implements a jetstream-compatible websocket subscription endpoint when compiled with the jetstream feature. it allows clients to consume atproto repository updates (commits, identity updates, and account state transitions) via a simplified, JSON-based format.

GET /subscribe#

subscribe to the jetstream websocket stream.

query parameters#

paramtypedescription
wantedCollectionsseq<string>list of collection NSIDs to receive (e.g. app.bsky.feed.post). supports namespace wildcards (e.g. app.bsky.feed.*).
wantedDidsseq<string>list of DIDs to receive (e.g. did:plc:abc123xyz).
wantedEventTypesseq<string>list of event types to receive: live or historical. if not specified, both are returned.
maxMessageSizeBytesintegerfilters out events whose serialized JSON size exceeds this value.
cursorintegerunix microseconds timestamp (time_us) to replay historical events from.
compressbooleanif true (or if header Socket-Encoding contains zstd), compresses frames using zstd and sends them as binary websocket frames.
requireHellobooleanif true, the socket will not stream any events until the client sends a hello / options_update message first.

in-stream options update#

clients can dynamically modify filtering criteria (wantedCollections, wantedDids, maxMessageSizeBytes, and wantedEventTypes) without reconnecting by sending a text frame with the following JSON format:

{
  "type": "options_update",
  "payload": {
    "wantedCollections": ["app.bsky.feed.post", "app.bsky.like.*"],
    "wantedDids": ["did:plc:abc123xyz"],
    "maxMessageSizeBytes": 5000000,
    "wantedEventTypes": ["live"]
  }
}

event payload formats#

all jetstream events are serialized as JSON objects containing:

  1. did: string (did of the repository)
  2. time_us: integer (unix microseconds timestamp)
  3. kind: string ("commit", "identity", or "account")

commit#

fired when a record is created, updated, or deleted:

{
  "did": "did:plc:abc123xyz",
  "time_us": 1716823456789012,
  "kind": "commit",
  "commit": {
    "rev": "3kpjxabc123",
    "operation": "create",
    "collection": "app.bsky.feed.post",
    "rkey": "3kpjxabc123",
    "record": {
      "$type": "app.bsky.feed.post",
      "text": "hello, world!",
      "createdAt": "2026-05-27T12:00:00.000Z"
    },
    "cid": "bafyreihy..."
  }
}

if hydrant is running in indexer mode with HYDRANT_ONLY_INDEX_LINKS=true, record content blocks are not persisted. consequently, record and cid may be omitted from commit payloads.

identity#

fired when a did document or handle updates:

{
  "did": "did:plc:abc123xyz",
  "time_us": 1716823456789012,
  "kind": "identity",
  "identity": {
    "did": "did:plc:abc123xyz",
    "seq": 1234567,
    "time": "2026-05-27T12:00:00Z",
    "handle": "user.bsky.social"
  }
}

account#

fired when a repository's status changes (active, deactivated, or deleted):

{
  "did": "did:plc:abc123xyz",
  "time_us": 1716823456789012,
  "kind": "account",
  "account": {
    "active": false,
    "did": "did:plc:abc123xyz",
    "seq": 1234567,
    "time": "2026-05-27T12:00:00Z",
    "status": "deactivated"
  }
}

additional details#

  • live stream scope: jetstream subscribers receive both live firehose events (live: true) and historical backfill / sync replay events (live: false) by default. be aware that historical backfills will interleave with live events unless filtered using the wantedEventTypes query parameter.
  • slow consumers: if a socket's send buffer remains full for longer than the configured timeout, the server sends a {"type":"error","error":"ConsumerTooSlow"} message and drops the connection.