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.
table view (60 samples)
#
latency
1
0.90s
2
0.90s
3
0.97s
4
0.97s
5
0.97s
6
0.31s
7
0.31s
8
0.31s
9
0.31s
10
0.31s
11
0.31s
12
0.95s
13
0.95s
14
0.95s
15
0.95s
16
0.39s
17
0.39s
18
0.39s
19
0.39s
20
0.39s
21
0.39s
22
0.39s
23
0.39s
24
0.82s
25
0.82s
26
0.82s
27
0.36s
28
0.36s
29
0.36s
30
0.80s
31
0.80s
32
0.80s
33
0.80s
34
0.80s
35
0.80s
36
0.54s
37
0.54s
38
0.54s
39
0.54s
40
0.94s
41
0.94s
42
0.94s
43
0.94s
44
0.40s
45
0.40s
46
0.40s
47
0.40s
48
0.40s
49
0.40s
50
0.40s
51
0.40s
52
0.40s
53
0.88s
54
0.88s
55
0.39s
56
0.39s
57
0.39s
58
0.39s
59
0.90s
60
0.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 55s —
93 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
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.8s — 2,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.