Consuming the firehose
This page picks up from the Relay overview and walks through
actually consuming the firehose: opening the connection, decoding events, and
processing them in order. We use Bluesky's relay
(relay1.us-east.bsky.network) in the examples, but the same code works against
any relay.
The firehose is a binary stream: efficient, but more work to decode. If you'd rather receive filtered JSON and skip the CBOR/CAR decoding entirely, use Jetstream.
Open the connection
The firehose is served from the com.atproto.sync.subscribeRepos endpoint over
a WebSocket. No authentication is required.
- Go
- Shell
uri := "wss://relay1.us-east.bsky.network/xrpc/com.atproto.sync.subscribeRepos"
con, _, err := websocket.DefaultDialer.Dial(uri, http.Header{})
websocat wss://relay1.us-east.bsky.network/xrpc/com.atproto.sync.subscribeRepos
Each message that arrives is binary-encoded CBOR. Commit events carry a CAR slice of the repository holding the changed records. Most SDKs provide a wrapper that handles the framing and decoding for you. Our Go SDK is currently the most feature-complete for working with the firehose directly.
Handle each event
Once the bytes are decoded, you work with a stream of repository operations: things like "create post", "create like", or "delete follow". The example below sets up a handler that prints each operation as it arrives:
- Go
rsc := &events.RepoStreamCallbacks{
RepoCommit: func(evt *atproto.SyncSubscribeRepos_Commit) error {
fmt.Println("Event from ", evt.Repo)
for _, op := range evt.Ops {
fmt.Printf(" - %s record %s\n", op.Action, op.Path)
}
return nil
},
}
sched := sequential.NewScheduler("myfirehose", rsc.EventHandler)
events.HandleRepoStream(context.Background(), con, sched)
Here we set up a sequential scheduler, which handles events one at a time, in order. Other schedulers run handlers in parallel, or do limited concurrency keyed on the event's repo. This is useful once a single-threaded handler can't keep up with the network's volume, while still preserving per-repo ordering.
HandleRepoStream does the actual decoding of the data coming over the
WebSocket and dispatches each event to the handler you wrote.