Backfill Ethereum event logs without skipping a block

An indexer can finish half of a long log scan before an RPC limit interrupts it. Number the windows explicitly so the next run can continue from the first unfinished block.

Freeze the upper boundary

Read eth_getBlockByNumber with ["finalized",false] and save the returned number. Use this height as the last block of the job. For an example window on mainnet, the filter below requests logs emitted by the WETH contract from block 16,000,000 through 16,000,015, inclusive. Send the body to the HTTP RPC endpoint.

{"jsonrpc":"2.0","id":1,"method":"eth_getLogs","params":[{"address":"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2","fromBlock":"0xf42400","toBlock":"0xf4240f"}]}

Commit the interval with its results

The next window begins at 0xf42410. In one database transaction, insert the logs and record that scanning completed through 0xf4240f. An empty result array also completes this window. If the process restarts before commit, replay the same window. Within a given chain, a unique key on block hash and log index keeps retries from inserting an event twice.

Split a range that exceeds the endpoint limit

If the endpoint rejects this range as too large, retry 0xf42400–0xf42407 and 0xf42408–0xf4240f. A rate-limit response instead calls for a pause. If even one block exceeds a result limit, narrow the filter by event signature where the application permits it, or use a backend that serves the full result. Keep the cursor at the last complete block. ethereum.org Ethereum log-filter parameters