Something went wrong. Try again.
Connects to the Bluesky Jetstream WebSocket firehose and republishes post-create events to a Redis Pub/Sub channel.
Something went wrong. Try again.
Files
README.md
jetstream-relay #
Connects to the Bluesky Jetstream WebSocket firehose and republishes post-create events to a Redis Pub/Sub channel. This allows multiple downstream consumers to subscribe to the Redis channel independently, without each needing its own Jetstream connection.
How it works #
- Opens a WebSocket connection to one of the Jetstream endpoints (US-East / US-West, with automatic failover across four servers).
- Filters for
app.bsky.feed.postevents and validates them with Zod via@vinerima/jetstream-types. - Publishes each validated post-create event as JSON to a configurable Redis Pub/Sub channel.
- Tracks the
time_uscursor of the last successfully published event, persists it to Redis, and resumes from it on reconnects and restarts.
Delivery semantics #
- At-least-once across reconnects. The relay resumes from the cursor of the last event that reached Redis, so events around a disconnect or restart are replayed and consumers may see duplicates. Deduplicate by
time_us+did(orcommit.rev) if duplicates matter to you. - Pub/Sub is fire-and-forget. Redis Pub/Sub does not buffer for disconnected subscribers — consumers only receive events while subscribed. If consumers must not miss events while offline, put a Redis Streams consumer behind the channel (or adapt the relay to
XADD). - Fail-fast on outages. While Redis is unreachable, publishes fail immediately (nothing buffers in process memory) and the cursor stops advancing, so the missed window is replayed once Redis recovers. If every Jetstream endpoint stays unreachable through all reconnect cycles, the process exits with code 1 — run it under a supervisor (systemd, Docker
--restart, pm2) so it gets restarted.
Prerequisites #
- Node.js (v20+)
- A running Redis instance
Configuration #
| Variable | Default | Description |
|---|---|---|
REDIS_URL |
redis://localhost:6379 |
Redis connection string |
REDIS_CHANNEL |
jetstream:posts |
Pub/Sub channel name |
REDIS_CURSOR_KEY |
jetstream:cursor |
Redis key the cursor is persisted to (every 5s and on shutdown) |
Running the relay #
1. Install dependencies #
pnpm install
2. Start Redis #
The relay requires a running Redis instance. If you don't have one, install and start it:
# macOS (Homebrew)
brew install redis
brew services start redis
# or run in the foreground
redis-server
# Docker
docker run -d --name redis -p 6379:6379 redis:7-alpine
To use a remote or non-default Redis instance, set REDIS_URL:
export REDIS_URL=redis://your-host:6379
3. Start the relay #
# development
pnpm start
# production
pnpm build
node dist/index.js
You can verify events are flowing by subscribing to the channel in a separate terminal:
redis-cli SUBSCRIBE jetstream:posts
Tests #
pnpm test
Dependencies #
@vinerima/wah— WebSocket client with reconnection, failover, and schema-based message handling@vinerima/jetstream-types— Zod schemas for Jetstream event typesioredis— Redis client
License #
MIT
·
Copy SHA
·
Copy SHA
·
Copy SHA
·
Copy SHA
·
Copy SHA
- TypeScript 100%