A notification stream is not a complete block archive
newHeads announces observed heads. A reconnection can miss blocks, and a reorganization can produce another block hash at a height you already stored. Deduplicating only by block number can hide replacements. Treat each notification as a prompt to reconcile your local chain view.
Maintain a linked view
on_head(head):
if head.parentHash != stored_tip.hash:
reconcile_to_common_ancestor(head)
fetch_missing_blocks(stored_tip.number + 1, head.number)
store_block_by_hash(head)
update_tip(head)This pseudocode omits chain-specific finality policy. Store both the block number and hash, plus the parent hash. Preserve replaced records with a status instead of mixing their events into the canonical view.
Recover after reconnect
- Open a new subscription and buffer arriving heads.
- Read the current tip through RPC.
- Fetch the missing numeric range and check parent continuity.
- Reconcile the overlap, then drain buffered notifications through the same deduplication path.
Separate inclusion from settlement
A sequencer head on Robinhood Chain is an early view of L2 ordering. Settlement on Ethereum has additional stages. Use chain-specific finality documentation for financial acceptance rules, and monitor how far your collector lags the live head. A generic EVM subscription implementation can be reused, but assumptions about block pace, public mempools and finality cannot be copied unchanged from another chain.