feat(indexer): N-block reorg detection + rewind#47
Merged
Conversation
Pre-Tier-3 sync only checked the immediate parentHash of the new block —
that catches a 1-block reorg but silently loses data on any reorg that
lands a different block at a height already indexed. BFT chains rarely
reorg deep but the indexer should be correct against the worst case
(validator re-org during binary swap + chain.db rsync recovery).
New module apps/indexer/src/reorg.ts exports checkAndRewindReorg:
1. Read last_synced_height from _meta.
2. SELECT block hashes from blocks for [synced - DEPTH, synced].
3. Refetch the canonical hash for each height via chain RPC. With
viem batch transport (Tier 1) these collapse to one HTTP request.
4. Walk forward, find first divergence.
5. On divergence: DELETE FROM blocks (FK cascade clears txs + logs)
+ DELETE FROM token_transfers + rewind last_synced_height to
divergedAt - 1, all in one SQL transaction. Bumps the reorg_count
observability counter in _meta.
Wired into apps/indexer/src/index.ts via setInterval — default 60 s
cadence (env INDEXER_REORG_INTERVAL_MS), default depth 16 blocks
(env INDEXER_REORG_CHECK_DEPTH). Cleared on graceful shutdown alongside
the stats_daily_mv refresh timer.
The remaining Tier 3 items from the audit — declarative event handlers,
GraphQL surface, table partitioning — are each multi-day refactors and
land in their own follow-up PRs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Tier 3 of the indexer audit — first arch-level fix lands. Builds on top of #45 (Tier 1) + #46 (Tier 2).
Pre-Tier-3 `sync.ts` only checked the immediate parentHash of the new block — that catches a 1-block reorg but silently loses data on any reorg that lands a different block at a height already indexed. BFT chains rarely reorg deep but the indexer should be correct against the worst case (validator re-org during binary swap or chain.db rsync recovery).
What lands
New module `apps/indexer/src/reorg.ts` exports `checkAndRewindReorg`:
Wired into `apps/indexer/src/index.ts` via `setInterval`:
Cleared on graceful shutdown alongside the `stats_daily_mv` refresh timer.
Deferred Tier 3 items (separate follow-up PRs)
The remaining Tier 3 work is each a multi-day refactor and lands in its own PR:
Test plan