arckive benchmarks

A Kubernetes-native contract-event indexer for Arc: apply an Indexer CR, get contract events as plain SQL rows in your own Postgres. Every number below was measured by running the real worker process and reading only its production surface — no benchmark instrumentation in product code. 2026-07-21 · 6be4155

block → SQL, p50 (testnet)
0.40s
ws listening mode
backfill catch-up
93 blocks/s
real USDC history
burst ingest
2,628 events/s
local write-path ceiling
Scenario 1 · Arc public testnet

Freshness — block close to SQL row

A worker subscribed to newHeads over WebSocket (listening, not polling — 26 head signals in the window) and tailed native USDC (0x360000…) Transfer events on the real Arc testnet. Latency is read from the product's own meta columns — _ingested_at − block_time — for every row that arrived in the window: 60 events of genuine third-party traffic.

p50
0.40s
block close → queryable row
p90
0.95s
p99
0.97s
fastest
0.31s

Latency budget: the RPC's own newHeads subscription first announces a block 0.89s (p50) after its validator timestamp — that provider floor is outside any indexer's control. Arckive adds only ~0ms on top: the head signal triggers an immediate round — one eth_getLogs plus the transactional SQL write. No polling interval in the hot path.

0.0s0.5s1.0s event 1 — 0.90sevent 2 — 0.90sevent 3 — 0.97sevent 4 — 0.97sevent 5 — 0.97sevent 6 — 0.31sevent 7 — 0.31sevent 8 — 0.31sevent 9 — 0.31sevent 10 — 0.31sevent 11 — 0.31sevent 12 — 0.95sevent 13 — 0.95sevent 14 — 0.95sevent 15 — 0.95sevent 16 — 0.39sevent 17 — 0.39sevent 18 — 0.39sevent 19 — 0.39sevent 20 — 0.39sevent 21 — 0.39sevent 22 — 0.39sevent 23 — 0.39sevent 24 — 0.82sevent 25 — 0.82sevent 26 — 0.82sevent 27 — 0.36sevent 28 — 0.36sevent 29 — 0.36sevent 30 — 0.80sevent 31 — 0.80sevent 32 — 0.80sevent 33 — 0.80sevent 34 — 0.80sevent 35 — 0.80sevent 36 — 0.54sevent 37 — 0.54sevent 38 — 0.54sevent 39 — 0.54sevent 40 — 0.94sevent 41 — 0.94sevent 42 — 0.94sevent 43 — 0.94sevent 44 — 0.40sevent 45 — 0.40sevent 46 — 0.40sevent 47 — 0.40sevent 48 — 0.40sevent 49 — 0.40sevent 50 — 0.40sevent 51 — 0.40sevent 52 — 0.40sevent 53 — 0.88sevent 54 — 0.88sevent 55 — 0.39sevent 56 — 0.39sevent 57 — 0.39sevent 58 — 0.39sevent 59 — 0.90sevent 60 — 0.90s p50 0.40s events in block order · blocks 52,981,525 → 52,981,538
table view (60 samples)
#latency
10.90s
20.90s
30.97s
40.97s
50.97s
60.31s
70.31s
80.31s
90.31s
100.31s
110.31s
120.95s
130.95s
140.95s
150.95s
160.39s
170.39s
180.39s
190.39s
200.39s
210.39s
220.39s
230.39s
240.82s
250.82s
260.82s
270.36s
280.36s
290.36s
300.80s
310.80s
320.80s
330.80s
340.80s
350.80s
360.54s
370.54s
380.54s
390.54s
400.94s
410.94s
420.94s
430.94s
440.40s
450.40s
460.40s
470.40s
480.40s
490.40s
500.40s
510.40s
520.40s
530.88s
540.88s
550.39s
560.39s
570.39s
580.39s
590.90s
600.90s
Scenario 2 · Arc public testnet

Backfill — catching up on real USDC history

The worker started 5,107 blocks behind (≈ 0.7 hours of chain time) on Arc testnet's native USDC contract and reached Live in 55s93 blocks/s over a public RPC, decoding and writing 20,452 transfer events along the way (batchBlocks: 1000).

catch-up rate
93 blocks/s
~48× faster than the chain
time to Live
55s
5,107 blocks
events
20,452
USDC transfers
02,0004,000 Live t=13s — 4,107 blocks behindt=15s — 4,107 blocks behindt=17s — 4,107 blocks behindt=19s — 4,107 blocks behindt=21s — 4,107 blocks behindt=23s — 3,107 blocks behindt=25s — 3,107 blocks behindt=27s — 3,107 blocks behindt=29s — 3,107 blocks behindt=31s — 3,107 blocks behindt=33s — 2,107 blocks behindt=35s — 2,107 blocks behindt=37s — 2,107 blocks behindt=39s — 2,107 blocks behindt=41s — 2,107 blocks behindt=43s — 2,107 blocks behindt=45s — 1,107 blocks behindt=47s — 1,107 blocks behindt=49s — 1,107 blocks behindt=51s — 1,107 blocks behindt=53s — 1,107 blocks behindt=55s — 0 blocks behind 0s20s40s
Scenario 3 · local network

Burst — the write-path ceiling

2,000 Ping events were packed into 8 dense blocks on a local anvil chain, then a worker cold-started and ingested all of them in 0.8s2,628 events/s through the full decode + single-transaction SQL write path, with WAN latency out of the picture.

ingest rate
2,628 events/s
decode + transactional SQL write
events
2,000
in 0.8s
avg DB write
340ms
per batch
Methodology. Each scenario spawns the actual arclight-worker binary and observes it only through Postgres rows and its Prometheus /metrics endpoint — the same surface you would monitor in production. Freshness = _ingested_at − block_time per row, where block_time is the validator timestamp and _ingested_at is the database clock at insert (local clock assumed NTP-synced). The freshness worker runs in WS-hybrid mode: an eth_subscribe(newHeads) subscription triggers an immediate fetch round the moment a block is announced, and interval polling remains only as a safety net — the run is invalidated unless the WS connection stayed up for the whole window (arclight_ws_connected). Arc testnet RPC: drpc.org public endpoint. Reproduce with pnpm bench · Node v24.13.0.