Ethereum
Chain Reorganizations
A chain reorganization is the moment Ethereum decides that a block your app already saw was the wrong one. The canonical chain switches to a competing branch, and one or more blocks at the head get dropped and replaced. On post-Merge Ethereum these are almost always shallow — a single block at the tip, reorged out before it was justified. They happen because two validators' views briefly disagree across a 12-second slot, usually from propagation latency, and the fork-choice rule then settles on one branch.
The crucial nuance for chain 1 is finality. Short head reorgs are possible before a block justifies, but once a block reaches the finalized tag, reverting it would force the protocol to slash a third of the validator set's stake — so deep reorgs of finalized history simply don't happen. The danger zone is the unfinalized tail. If your app credited a deposit, fired a webhook, or updated a balance off a block at latest that then gets reorged away, your state now reflects a transaction that no longer exists on the canonical chain. Handling that gap is what this guide is about.
Understanding Reorgs
- What triggers one. Two validators can briefly build on different views of the head when a block propagates slowly across the network, or when a proposer is late. Gasper's fork-choice rule (LMD-GHOST with Casper FFG finality) then picks the branch with the most attestation weight, and the losing branch's tip is reorged out.
- Shallow is the norm, deep is effectively ruled out. On Ethereum a reorg is typically one block deep, occasionally two, and lives entirely in the unfinalized tail. Reorgs of finalized blocks don't occur without mass slashing, so you're only ever defending against the short reorgs near
latest, not a Bitcoin-style multi-block rewrite of settled history. - What it does to transactions. A reorged transaction returns to the mempool as pending — it isn't lost, but its block number, position, and gas outcome can all change when it's re-included, and it may pay a different effective fee. A receipt you fetched at
latestcan become stale; only inclusion at or belowfinalizedis safe to treat as permanent. - Detecting it over JSON-RPC. There's no dedicated reorg event, so you infer it. The reliable signal is a
parentHashmismatch: when a new head'sparentHashno longer matches the recorded hash one block below it, or the hash at a height you already saved has since changed, the chain reorganized. WatchingnewHeadsand re-checking finalized vs. latest gives you the same signal in near real time.
Implementation Examples
Mitigation Strategies
- Wait for finality on anything irreversible. Rather than picking a confirmation count, treat the
finalizedtag as your bar: a block at or below the finalized height (about two epochs, ~12.8 minutes back) won't reorg. For lower-stakes flows thesafetag is a reasonable middle ground. Whatever you read atlatest, assume it can still vanish. - Detect via parentHash, by polling or subscription. In a polling loop, store the hash at each height and compare each new block's
parentHashagainst the previous stored hash. In a subscription model, do the same on everynewHeadspush. Either way, the mismatch is your reorg trigger; subscriptions just catch it a slot sooner. - Resubmit idempotently. When a transaction is reorged back to pending, it usually gets re-included on its own — you rarely need to rebroadcast. If you do resubmit, reuse the same nonce so the network treats it as the same transaction, never a second one, which is how you avoid accidentally sending value twice. Guard every state change with an idempotency key tied to the transaction hash so a re-included transaction can't double-apply.
- Roll back to the common ancestor. On detecting a reorg, walk both branches back until their hashes meet (the helper above finds that ancestor), undo every state change derived from the orphaned blocks above it, then replay the new canonical blocks forward. Only the unfinalized tail should ever be in scope for rollback — finalized-derived state stays put.
- Subscriptions for liveness, polling for the floor. A
newHeadssubscription overwss://ethereum.therpc.io/YOUR_API_KEYgives you the fastest reorg signal and the lowest cost. Keep a slower polling loop as a backstop, since a dropped WebSocket can miss the exact block where the reorg happened — the poller re-derives it from stored hashes on reconnect.
See also
- eth_getBlockByHash - Retrieve block by hash
- Block Confirmations Guide - Understanding transaction finality
- Working with Blocks - General block handling