Benchmark indexer JSON-RPC load on localnet and reduce rate-limit risk #306
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:open_issues
agents
agent:security_audit
agent:verify
area
timecurve
arena
arena-v2
audit
block:feature_review
block:security
bug
contracts
design
devops
docs
documentation
enhancement
epic
feature
frontend
indexer
low priority
megaeth
operations
ops
performance
QA
qa checklist
referrals
removal
security
smart-contracts
tech-debt
testing
time-arena
timecurve
visual-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/yieldomega#306
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The indexer is a steady JSON-RPC consumer with two long-running loops that share
RPC_URL:indexer/src/ingestion.rs) — per indexed block:eth_getBlockByNumber+eth_getLogs; optional ancestor fetches on reorg; extraeth_calls during live podium snapshots (arena_podium_live,warbow_score) on qualifying events.indexer/src/chain_timer.rs) — ~1 Hz when healthy (RPC_FAST_POLL_MSinrpc_poll_health.rs, aligned withfrontend/src/lib/rpcConnectivity.ts): each cycle iseth_blockNumber,eth_getBlockByNumber, many sequentialeth_calls (timer fields, 4×podium(), sale state, sale-head metadata), plus optionalPodiumVaultspool balances.We have backoff for failures and HTTP 429 (5s → 15s → 30s), but no measured baseline for calls/minute, burst peaks, or per-method breakdown on realistic localnet traffic. Without that, we cannot confidently size RPC quotas, compare mainnet vs Anvil, or prioritize optimizations that keep
/arenareactive without hammering shared RPC infra.Related: #168 (timeouts/liveness), #237 (deferred WSS lane), #301 (indexer-first display — UI should not duplicate head polling when indexer is healthy).
Goals
scripts/start-local-anvil-stack.shorscripts/start-qa-local-full-stack.sh).eth_blockNumber,eth_getBlockByNumber,eth_getLogs,eth_call) and by subsystem (ingestion vs chain-timer vs ingestion-side live podium RPC).START_BLOCKlag or paused Anvil then fast-forward)scripts/verify-podium-live-anvil.sh, vault-funding verify, optional bot swarm)RpcPollHealthbackoff does not cause thundering herds.Suggested approach
Instrumentation (deliverable 1)
Add lightweight RPC metrics in the indexer (feature-flagged or always-on at
debug/info):ingestion,chain_timer,podium_live,reorg, …)GET /v1/status(schema bump) or structured log line every N seconds for CI/scriptsPrefer hooking at the shared transport layer (
rpc_http.rs/ provider wrapper) so all paths are counted consistently.Benchmark harness (deliverable 2)
Script under
scripts/(e.g.scripts/benchmark-indexer-rpc-anvil.sh) that:docs/indexer/or pasted in this issueDocument exact env knobs:
RPC_URL,INGESTION_ENABLED,INDEXER_RPC_REQUEST_TIMEOUT_SEC, Anvil block time.Analysis & recommendations (deliverable 3)
Document findings and prioritized strategies, for example:
eth_callfan-outeth_callat same block tag within one pollpoll_onceeth_callduring live podium snapshots (derive from decoded logs where possible)INV-INDEXER-PODIUM-PREDICT-LIVEInclude target SLOs proposal (e.g. max steady-state calls/min per instance, max lag for
GET /v1/arena/timersfreshness) for operator runbooks.Acceptance criteria
Verification
References
indexer/README.md— RPC resilience, chain-timer cadenceindexer/src/rpc_poll_health.rs,indexer/src/rpc_http.rsindexer/src/ingestion.rs,indexer/src/chain_timer.rs,indexer/src/arena_podium_live.rsdocs/indexer/design.md— ingestion vs future WSS lane (#237)docs/testing/qa-local-full-stack.mdmentioned in commit
3277fda5b8mentioned in merge request !454
Implementation (MR !454)
Branch
local1/306-impl-rpc-benchmarkadds indexer JSON-RPC instrumentation, localnet benchmark harness, and operator documentation for #306.Deliverables
indexer/src/rpc_metrics.rs+ hooks inrpc_http.rs,ingestion,chain_timer,reorg,warbow_score,arena_podium_live. Structured logs everyINDEXER_RPC_METRICS_LOG_SEC(default 60s).GET /v1/statusschema 2.11.0 includesrpc_metrics(1m/5m rates,peak_calls_10s,by_method,by_caller).bash scripts/benchmark-indexer-rpc-anvil.sh(idle, catch-up, active arena). Sample artifacts:docs/indexer/benchmarks/rpc-benchmark-20260610T111415Z.{json,md}.docs/indexer/rpc-load-benchmark.md,INV-INDEXER-306-*in invariants, design.md §306, play skill crosslink.Sample baseline (Anvil, 30s scenarios)
chain_timereth_callfan-out dominates; ingestion spikes on catch-up and arena buys.Verification checklist
bash scripts/verify-indexer-rpc-metrics.shBENCHMARK_SCENARIO_SEC=120 bash scripts/benchmark-indexer-rpc-anvil.sh(optional longer run)bash scripts/verify-podium-live-anvil.shcd indexer && cargo testGET /v1/status→rpc_metrics.by_caller.chain_timergrows ~1 Hz when idleFollow-ups (not in this MR)
Issue stays open until MR !454 merges and checklist is signed off.
mentioned in commit
15b4923c38mentioned in commit
98259e2723These need to be brought down to 50/10s in peak
mentioned in issue #307
mentioned in issue #308
Child issues opened (agent triage)
Parent baseline landed in MR !454 (instrumentation,
GET /v1/statusrpc_metrics,scripts/benchmark-indexer-rpc-anvil.sh,docs/indexer/rpc-load-benchmark.md). Follow-up directive:peak_calls_10s≤ 50 (from ~354 idle).Opened
poll_onceeth_callfan-out + coalesce duplicate calls at same block tag; target idlepeak_calls_10s≤ 50read_block_number/ epochs stable; stay ≤ 3spolled_at_msfreshness near deadlinesBoth issues reference the shared operator target from the 2026-06-10 comment and may be implemented in either order; combined they should close the ~7× gap to 50 calls / 10s.
Skipped — already done (parent / MR !454)
rpc_metrics.rs, transport hooks)GET /v1/statusschema 2.11.0rpc_metricsfieldscripts/benchmark-indexer-rpc-anvil.sh+scripts/verify-indexer-rpc-metrics.shINV-INDEXER-306-*invariantsdocs/indexer/rpc-load-benchmark.mdSkipped — rejected / deferred / shipped
Skipped — undecided (no approval in issue comments)
podium()RPC)RPC_URLfor head poller vs ingestion (operator isolation only)podium_live/warbow_scoreRPC reduction beyond current metricseth_getBlockByNumbernull handling) — not triaged as approved proposals on #306Bundling rationale
#307 groups multicall batching + same-block coalesce (same
poll_oncerefactor). #308 is separate poll-loop timing logic per MR !454 (“multicall batching, adaptive poll interval) as separate issues”).mentioned in issue #309
mentioned in merge request !455
mentioned in merge request !488
Rerun benchmarks and report potential improvements with tradeoffs.
mentioned in commit
b4c514ccdementioned in merge request !503
mentioned in commit
52664c73bfmentioned in issue #341
marked as related to #356
mentioned in issue #356