Skip to main content

Avoiding RPC Rate Limits

When the container first starts it replays historical events by scanning blocks in batches using eth_getLogs. Free-tier and public RPC endpoints enforce strict rate limits — too many requests too fast will result in 429 Too Many Requests errors and missed events.

The following config fields let you tune replay speed to stay within your RPC's limits.


Key Fields

FieldDefaultWhat it controls
replayBatchSize2000Max number of blocks scanned per eth_getLogs call
replayDelayMs0Pause between each batch in milliseconds
confirmations1Blocks to wait after a transaction before delivering the event
pollIntervalMschain defaultHow often HTTP-polling chains (Stability, Astron) check for new blocks

How Replay Works

On startup the container scans from replayFromBlock to the current block in chunks of replayBatchSize:

Block 6,000,000 ──► [batch 1: 6,000,000 – 6,002,000] ──wait replayDelayMs──►
[batch 2: 6,002,000 – 6,004,000] ──wait replayDelayMs──►
...
[current block] ──► switch to live subscription

Reducing replayBatchSize means more requests, each covering fewer blocks. Adding replayDelayMs spaces them out so you don't burst past the RPC's per-second limit.


Public / free-tier RPCs

Free public endpoints (e.g. publicnode.com, Infura free) typically allow 5–10 requests/second and cap eth_getLogs at 2,000 blocks per call.

{
"chainKey": "ethereum-sepolia",
"rpcUrl": "wss://ethereum-sepolia-rpc.publicnode.com",
"replayFromBlock": 6000000,
"replayBatchSize": 500,
"replayDelayMs": 1000,
"confirmations": 1
}

Paid plans support much larger batch sizes and higher throughput.

{
"chainKey": "ethereum-sepolia",
"rpcUrl": "wss://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}",
"replayFromBlock": 6000000,
"replayBatchSize": 10000,
"replayDelayMs": 100,
"confirmations": 1
}

HTTP-polling chains (Stability, Astron)

These chains use polling instead of WebSocket subscriptions. pollIntervalMs controls how often new blocks are checked — set it no lower than your RPC's minimum polling window.

{
"chainKey": "stability",
"rpcUrl": "https://rpc.stabilityprotocol.com/zgt/${STABILITY_API_KEY}",
"replayFromBlock": 35000000,
"replayBatchSize": 5000,
"replayDelayMs": 5000,
"pollIntervalMs": 10000,
"confirmations": 1
}

Diagnosing Rate Limit Errors

Check logs for these patterns:

Log messageCauseFix
missing response / timeoutBatch too large, RPC dropped the connectionLower replayBatchSize
rate limit exceeded / 429Too many requests per secondIncrease replayDelayMs
could not decode result dataWrong registry address or RPC returned emptyVerify registryAddresses and rpcUrl

Enable debug logging to see each batch request:


Full Example — Multi-Chain with Conservative Rate Limits

{
"chains": [
{
"chainKey": "ethereum-sepolia",
"rpcUrl": "wss://ethereum-sepolia-rpc.publicnode.com",
"registryAddresses": ["0xYourRegistryAddress"],
"replayFromBlock": 6000000,
"replayBatchSize": 500,
"replayDelayMs": 1000,
"confirmations": 1
},
{
"chainKey": "polygon-amoy",
"rpcUrl": "wss://polygon-amoy-bor-rpc.publicnode.com",
"registryAddresses": [],
"replayFromBlock": 39000000,
"replayBatchSize": 1000,
"replayDelayMs": 500,
"confirmations": 1
},
{
"chainKey": "stability",
"rpcUrl": "https://rpc.stabilityprotocol.com/zgt/${STABILITY_API_KEY}",
"registryAddresses": [],
"replayFromBlock": 35000000,
"replayBatchSize": 5000,
"replayDelayMs": 5000,
"pollIntervalMs": 10000,
"confirmations": 1
}
],
"webhook": {
"url": "https://your-system.example.com/trustvc/events"
},
"server": {
"logLevel": "info"
}
}