Operating
Practical notes for running a long-lived connection in production: how to resume after a drop, how the server keeps connections alive, and the limits to design around.
Reconnects & replay
The server retains a REPLAY_SECONDS window per package on disk (default 600s). On reconnect, pass ?from_timestamp=<n> — every retained block with block_num > n is replayed oldest-first before the live stream resumes.
wss://ws.pinax.network/ws/solana@swaps?from_timestamp=1715619600 wss://ws.pinax.network/ws/solana@swaps?from_timestamp=2026-05-13T17:00:00Z
If n falls below the oldest retained block, a gap lifecycle message is emitted instead — backfill the hole via Substreams gRPC. Wildcards skip replay.
Heartbeats
The server sends WebSocket ping frames every 180s. Standard clients pong automatically. Connections that don't pong within 600s are closed.
Limits
- Bounded replay. 600s window per package. For older history, use Substreams gRPC directly with a
start_block. - One output type. Only
sf.substreams.sink.database.v1.DatabaseChanges. - Per-connection buffer. Slow consumers are dropped per-message rather than blocking ingest. Default 1024 messages.
- Beta: per-key concurrency capped at 4 connections during the beta window.