A dropped eth_subscribe connection leaves two jobs behind: recover the missed data and pay for the recovery requests. A slow consumer can cause the same disconnect repeatedly. Without a saved block cursor, each retry risks missing logs or scanning history you already processed.
This guide covers the operating costs and failure checks for Ethereum WebSocket subscriptions. For subscription setup and a recovery implementation, start with WebSockets for blockchain developers.
What a WebSocket subscription costs
Count subscription requests, delivered notifications, and recovery requests separately. Alchemy bills standard Ethereum subscription traffic by bytes. Infura uses event-specific credits. Dwellir counts each notification as one response.
| Operation | Alchemy | Infura | Dwellir |
|---|---|---|---|
eth_subscribe | 10 compute units | 5 credits | 1 credit |
eth_unsubscribe | 10 compute units | 10 credits | 1 credit |
newHeads | 0.04 compute units per byte | 50 credits per block | 1 credit per notification |
logs | 0.04 compute units per byte | 300 credits per block | 1 credit per notification |
| Pending transactions | 0.04 compute units per byte | 200 credits at approximately one-second intervals | 1 credit per notification |
These published billing units were checked on September 22, 2026. They are not equivalent units of currency. Apply your plan's allowance and price to estimate the bill.
For example, 1,000 bytes delivered through an Alchemy Ethereum subscription consume 40 compute units. Measure your payloads before using that size in a forecast. Full transaction objects and transaction hashes produce different byte totals.
Infura's stated pending-event cadence gives an illustrative daily estimate of 200 × 86,400 = 17.28 million credits. Actual usage depends on the delivered event stream. Its logs charge applies per block, so do not multiply that rate by every matching log.
On Dwellir, estimate the notification count and add request responses. One credit per notification simplifies that calculation, but a rise in events still increases usage. Compare the total against your plan allowance.

Include recovery in the usage estimate
A reconnect creates a new subscription. Recovering missed logs also requires HTTP requests. Each retry adds usage, even when it restores a stream you already paid to consume.
For illustration, assume 60 disconnects in an hour. Each recovery uses one eth_subscribe call and one eth_getLogs call:
| Provider | Calculation | Additional usage |
|---|---|---|
| Alchemy | 60 × 10 + 60 × 60 | 4,200 compute units |
| Infura | 60 × 5 + 60 × 255 | 15,600 credits |
| Dwellir | 60 × 1 + 60 × 1 | 120 credits |
This example excludes live notifications, head checks, retries, and additional log-query windows. Actual recovery costs depend on the gap and the provider's query limits. See the eth_getLogs limits guide for window sizing.
Use exponential backoff with jitter and a retry limit. Alert when a stream repeatedly exhausts that limit. A retry limit should trigger investigation or failover, while the application records that its data is incomplete.
Persist the last durably processed block, including its hash. After reconnecting, subscribe before recovering the missing range, and buffer new events during recovery. Re-read an overlap to check for chain reorganizations. Deduplicate logs by block hash, transaction hash, and log index, and reverse records from replaced blocks.
HTTP recovery can retrieve canonical blocks and logs. It cannot reconstruct every pending transaction that appeared and disappeared while you were disconnected. A mempool feed needs an explicit data-loss policy.

Handle slow consumers before the connection closes
Geth buffers notifications before sending them. Its pub/sub documentation describes a 10,000-notification limit, after which it closes the connection. This is a Geth limit, not a guarantee for every hosted endpoint.
Separate socket reads from database writes and other slow work. Measure the application's queue depth and the age of its oldest unprocessed event. Those measurements show whether processing is falling behind before a disconnect occurs.
Bound the queue and decide what happens when it fills:
- For an indexer or accounting stream, preserve the last committed cursor and recover missing canonical events. Do not silently discard logs.
- For a display that needs only the newest value, coalescing updates can be acceptable. Count discarded updates and label stale data.
- For pending transactions, record any loss because canonical log recovery cannot restore the original stream.
Narrow logs subscriptions with contract addresses and topics where possible. This reduces work for the consumer. It also reduces byte-based or per-notification usage, though per-block billing does not necessarily fall with the log count.
Repeated disconnects during traffic bursts justify checking consumer capacity, gateway limits, and the network path. The disconnect alone does not prove which component failed.
Detect a stalled stream while the socket is open
A connection state of OPEN does not prove that subscription data is current. Track transport health and chain progress separately.
| Observation | Check | Response |
|---|---|---|
| No frames or heartbeat replies | WebSocket ping/pong timeout | Reconnect with backoff and recover the gap |
| Heartbeats arrive but heads stop | Compare with an independent HTTP head | Reconnect if the chain advanced and the stream did not |
| Processing lag grows during a burst | Queue depth and processing time | Reduce subscription volume or increase consumer capacity |
| Two workers process the same stream | Subscription ownership and consumer IDs | Keep intended redundancy; remove accidental duplicates |
| HTTP health check passes but WSS fails | An authenticated WebSocket subscription | Alert on the affected transport |
Choose staleness thresholds for each chain and application. Account for missed blocks and upstream delays. Do not force every replica to reconnect because one expected block was late.
WebSocket protocol ping/pong checks connection liveness. Browsers do not expose protocol ping frames to application code. Browser clients need an application heartbeat or another supported liveness check.

Check the stream before increasing the plan
Use one record per subscription to track its filter, owner, notification rate, last processed block, and recovery requests. Keep credentials out of those records. Compare notification growth with changes to filters and worker counts.
Before increasing capacity, check whether a pending feed is required and whether duplicate workers are intentional. Then measure the consumer's processing rate under a representative burst. A larger request allowance will not fix a blocked reader.
Dwellir's WebSocket pricing counts each notification as one credit. Include HTTP recovery in your estimate and check which plans support eth_getLogs. Contact the Dwellir team with your peak event rate and recovery window to size the endpoint.


