TriportRPC

Why a WebSocket subscription goes silent

Last updated:

At a glance

Symptom details
PropertyValue
Subscription lifetime (Geth)Coupled to one WebSocket connection; removed when it closes
After a reconnectResubscribe and use the new subscription ID
Missed eventsNo documented replay; backfill with regular RPC calls
Abnormal closeCode 1006 (RFC 6455): closed without a Close frame being received
newHeads during a reorgCan emit several headers at the same height

What you see

A long-running listener stops printing new blocks or logs. The process is alive, the socket reconnected, and there is no error — just silence. Or events resume after a reconnect but some blocks in between are missing, and newHeads occasionally delivers two different blocks at the same height.

Why this happens

Geth's documentation is explicit: subscriptions are coupled to a connection, and if the connection is closed, all subscriptions created over it are removed. A new connection therefore starts with none, and the subscription ID the server returned on the old connection identifies nothing on the new one. Solana's pub/sub also returns a subscription ID per subscribe request and pushes notifications to it; its documentation does not describe subscriptions surviving a reconnect, so resubscribing is the safe assumption there too. Connections close for ordinary reasons: a server restart or deploy, an idle timeout on a proxy, a network change on the client. When the connection is lost without a Close frame being received, RFC 6455 defines the close code the client sees as 1006 — a reserved value meaning the connection closed abnormally. Subscriptions deliver events from the moment they exist; neither API documents a replay of what was emitted while you were disconnected. Separately, during a chain reorganisation an EVM newHeads subscription emits the last header of the new chain, so it can deliver several headers at the same height, and a node catching up after being out of sync may emit only the last of several blocks.

What to do

  1. On every reconnect, create all subscriptions again and replace the stored subscription IDs.
  2. Remember the last block number or slot you processed; after resubscribing, backfill the gap with regular calls (eth_getLogs or eth_getBlockByNumber on EVM chains, getSignaturesForAddress or getBlock on Solana).
  3. Make handlers idempotent and key events by block hash and log index (or signature), so replays from the backfill and duplicates after a reorg are harmless.
  4. Send periodic ping frames (or a cheap request) to detect a dead connection early, and reconnect with backoff.
  5. Treat newHeads as "the chain head changed", not as a strictly increasing sequence: handle repeated heights and gaps.

When this is not our problem

Connection-scoped subscriptions and the lack of a documented replay come from the JSON-RPC pub/sub model itself, whoever operates the node, Triport included. Any long-lived WebSocket can be closed by either side, so resubscribe-and-backfill logic is needed with every provider.

FAQ

Do RPC subscriptions survive a WebSocket reconnect?
No. Geth documents that subscriptions are removed when their connection closes, and Solana's pub/sub documents no way to carry them over. After reconnecting, call eth_subscribe (or the Solana *Subscribe method) again and use the new subscription ID.
How do I get events I missed while disconnected?
Record the last block or slot you processed and backfill from there with regular RPC calls such as eth_getLogs, then continue with the new subscription.

Sources