Around Go: blockchain infrastructure · 3 MIN READ

Index events through disconnects and reorgs, not just the happy subscription

Persist canonical checkpoints and reconcile removed or missing events before final effects.

A WebSocket subscription is a live notification channel, not a durable ledger cursor. A process can disconnect, a provider can drop a slow subscriber and a chain can reorganize recently observed blocks. Store a checkpoint that includes chain identity and block hash, backfill a bounded range after reconnect and make the projection’s rollback or rebuild behavior explicit.

blockchain · A MAP OF THE IDEA

  1. Read canonical checkpoint
  2. Backfill bounded overlap
  3. Apply idempotent projection
  4. Reconcile hash + finality

Useful when

  • Persist canonical checkpoints and reconcile removed or missing events before final effects.
  • Makes the owner and the failure boundary explicit.

Watch out

  • A receipt or one observed block is not universal finality.
  • Run native service and failure tests in your own development environment.

Implementation & operation cost: Additional state and tests must be justified by the demonstrated failure; this lesson is not a requirement for every Go program.

01

The contract and the failure

A WebSocket subscription is a live notification channel, not a durable ledger cursor. A process can disconnect, a provider can drop a slow subscriber and a chain can reorganize recently observed blocks. Store a checkpoint that includes chain identity and block hash, backfill a bounded range after reconnect and make the projection’s rollback or rebuild behavior explicit.

02

Work through the example

Use FilterLogs for bounded backfill and SubscribeFilterLogs for live delivery where supported. Record chain ID, block hash/number, transaction hash and log index as required by the projection. Treat removed logs as a signal to reconcile; reconnect with overlap and deduplicate. Bound queues and scan ranges, and checkpoint only after the corresponding durable effect is safe to replay.

go
package main

import "fmt"

type Block struct {
	Height       uint64
	Hash, Parent string
}

func appendBlock(chain []Block, b Block) ([]Block, error) {
	if len(chain) > 0 {
		tip := chain[len(chain)-1]
		if b.Height != tip.Height+1 || b.Parent != tip.Hash {
			return chain, fmt.Errorf("reconcile canonical ancestor before append")
		}
	}
	return append(chain, b), nil
}
func main() {
	chain := []Block{{Height: 10, Hash: "A10", Parent: "A9"}}
	chain, _ = appendBlock(chain, Block{Height: 11, Hash: "A11", Parent: "A10"})
	_, err := appendBlock(chain, Block{Height: 11, Hash: "B11", Parent: "A10"})
	fmt.Println(err) // replacement is not silently appended
}
Read the code

The second block at height 11 does not extend the current canonical tip, so the model demands reconciliation. It is not a full fork-choice algorithm. A real indexer locates the common ancestor, reverses or rebuilds affected projection state and checkpoints atomically before continuing along the new canonical branch.

03

Production decisions

A receipt or one observed block is not universal finality. Finality guarantees and acceptable confirmation policy depend on the network, consensus state and business consequence. Do not permanently credit an irreversible external effect solely from an unfinalized subscription event. Test a missed block, duplicate event, removed log, competing hash at one height, crash during projection update and provider history limits.

04

Explain it in an interview

After reconnecting, can an indexer continue from only the next live WebSocket event? No. Backfill from a persisted canonical checkpoint with overlap, deduplicate and reconcile reorgs before advancing durable or irreversible effects. Describe the state before the operation, its owner, the failure between steps and the evidence you would test. Distinguish what this example demonstrates from the infrastructure a production service still needs.

TAKE THIS WITH YOU

Persist canonical checkpoints and reconcile removed or missing events before final effects. No. Backfill from a persisted canonical checkpoint with overlap, deduplicate and reconcile reorgs before advancing durable or irreversible effects.

Check your understanding

After reconnecting, can an indexer continue from only the next live WebSocket event?

Go to the source

Progress stays in this browser. No account needed.