Indexing Best Practices
Windows & Limits
Sei inherits Tendermint finality (single block confirmation) but enforces RPC limits to protect full nodes. Respect the following caps when building log indexers:
eth_getLogs
window default: 2,000 blocks.- Open-ended queries (no
fromBlock
/toBlock
) cap at 10,000 logs; always anchor both block bounds. - Subscription catch-up delivers up to 512 events per batch before backpressure kicks in.
- Archive providers may expose wider windows; detect and adapt via feature flags.
Backfill Strategy
- Backfill newest → oldest to keep current data fresh while draining history.
- Use chunk sizes of 250–500 blocks to balance node load and throughput.
- Persist checkpoints after each successful window to resume without duplicate ingestion.
- When replaying synthetic events, record the
synthetic
log flag (v6.1.11+ ) to differentiate from contract-emitted logs.
Reorg Handling
Sei produces instant finality; however, nodes may restart mid-ingest. Implement safeguards anyway:
- Persist the highest fully processed height; after restarts resume from
height - safetyBuffer
(recommend 10 blocks). - Verify block hash continuity even under finality to detect provider restarts.
- For websocket subscribers, rehydrate missed blocks using
eth_getLogs
if the connection drops for more than 3 seconds.
Rate Limits & Retries
- Throttle requests to one window per 200 ms unless working with a dedicated archive endpoint.
- Respect HTTP
429
responses-exponential backoff starting at 1s, max 30s. - Retry
EOF
and transient network errors up to 5 attempts; avoid retrying contract-level reverts. - Encode idempotency by hashing blockNumber + logIndex to prevent duplicate writes when retries occur.
Schema Design
- Model logs with composite unique key
(blockNumber, transactionHash, logIndex)
. - Store
topics
as arrays with a secondary index ontopic0
for fast event filtering. - Persist
synthetic
boolean to separate Cosmos module events from contract logs. - Keep raw
data
hex for replay; additionally decode known ABI payloads into typed columns for analytics surfaces.
Flow At A Glance
01
Discover latest height
Call eth_blockNumber
every loop and persist the safe tip before starting a window.
02
Windowed eth_getLogs
Query bounded ranges (≤2k blocks) and honour the log cap. Store the synthetic
flag with each event.
03
Write & checkpoint
Commit the batch, advance the checkpoint (height
, txHash
, logIndex
), then throttle before the next loop.
Reference Implementations
- @sei-js/evm indexing scripts - production-ready ingestion loop with retries, checkpointing, and synthetic log metadata.
- Tracing playbook - understand trace limits and panic handling when debugging ingestion anomalies.
- Pointers deep dive - learn how pointer metadata influences synthetic events surfaced during indexing.
Last updated on