Kubernetes-native event indexer for Arc

Your chain events, in your own Postgres.

Give it an ABI, a contract address, and an RPC. Arckive streams every on-chain event into your own PostgreSQL — one table per event, reliable and gap-free — from a single YAML manifest.

Runs in your cluster · Apache-2.0 · arckive.org/v1alpha1

usdc-arc · Provisioningkubectl get indexers -w
NamePhaseCurrentHeadLag
usdc-arcProvisioning

Status is patched onto the resource itself. No dashboard to log into.

The gap

Dune is delayed and rate-limited. Raw logs leave reorgs and back-fill to you. The Graph means subgraphs and heavy ops. There was no declarative path to your events, in your Postgres, in plain SQL.

01How it works

Declare it. The operator does the rest.

One Indexer resource describes what you want. A Kubernetes operator keeps it true — database, schema, listener, optional read API.

Step 1

Write one manifest

Contracts, ABI ref, RPC pool, storage mode — the whole setup.

kind: Indexer
metadata: { name: usdc-arc }
spec:
  rpc: # health-checked failover
    - https://rpc.arc.example
  storage: { mode: Embedded }
  contracts:
    - address: "0xA0b8…eB48"
      abi: { configMapRef: usdc-abi }
      startBlock: 0
Step 2

The operator provisions

A reconcile loop turns the spec into running parts — and heals them.

Indexer CR — 1 YAML
Arckive Operator
postgres · schema · worker · read API

Pod dies? Config drifts? It converges back.

Step 3

Query plain SQL

Each event is a table in your Postgres. No API between you and your data.

-- one table per event
SELECT "from", "to", value
FROM usdc_transfer
WHERE value > 1000000000
ORDER BY block_number DESC;
0x3786…39b3 0xdbcc…38db3,020.950xb51a…159a 0xa7b3…59933,454.570x9f21…c04a 0x53d0…b7da60,884.96

ABI in → tables out · empty events list = every event · startBlock: 0 backfills from genesis

On the shelves now

Schema idx_usdc_arc · one table per event, typed from the ABI, unique on (block, tx, log).

Event tablesControl tables
usdc_
transfer
idx_usdc_arc
usdc_transferTransfer(address,address,uint256)
from, to text · value numeric(78,0)
usdc_
approval
idx_usdc_arc
usdc_approvalApproval(address,address,uint256)
owner, spender text · value numeric(78,0)
_cursorcontrol
_cursorlast_block, updated_at
the checkpoint a restart resumes from
_metacontrol
_metakey, value
reserved for indexer metadata
_dead_
letter
control
_dead_letterlogs that failed to decode
empty when healthy
02Reliability

Even if the network blips, no data is lost.

A poll-based backbone chosen for loss-free, self-healing ingestion — not just latency. Don't take our word for it: break something.

Cursor + checkpoint

The last processed block lives in Postgres. After any crash it resumes exactly there.

Gap-free backfill

Event inserts and cursor advance share one transaction — a commit, or nothing.

Reorg-safe on Arc

Indexes to the finalized tag — BFT finality means finalized blocks never reorg.

RPC failover

A health-checked pool with rotation, backoff, circuit-breaker. A blip never becomes a gap.

Chaos lab — try to lose datasimulated
rpc-primary.arcrpc-backup.arcworker pod
chain head8,123,456
cursor8,123,456
lag0
gaps0
the invariant: gaps stay 0
t+0.0susdc-arc · phase=Live · cursor=head · lag=0 · gaps=0

Latest events

Open in SQL

Provisioning — the first row lands once the worker is up.

03Benchmarks

Measured, not promised.

Every number comes from running the real worker against the public Arc testnet and reading only its production surface — Postgres rows and /metrics. Reproduce it with pnpm bench.

block → SQL, p50395 msBlock close to queryable row on Arc testnet — live USDC traffic, WebSocket newHeads listening, not polling. Even p99 stays under a second (0.97 s).
backfill catch-up92.6 blocks/s5,107 blocks of real USDC history caught up in 55 seconds over a public RPC — about 48× faster than the chain. Zero RPC errors.
burst ingest2,628 events/sThe decode + transactional-SQL write ceiling, measured with WAN latency out of the picture.

The budget is published too: the head signal is consumed straight from the newHeads payload and one parallel eth_getLogs round-trip later the row is committed. The engine itself adds about 40 ms; the rest belongs to how fast the RPC announces blocks, and it shrinks further with a cluster-local Arc node. Full methodology and raw results: benchmark report · docs/benchmarks.

04Compare

A specific combination nobody else offers.

DuneThe GraphRaw RPCArckive
Data in your own DBNoVia graph-nodeIf you build itYes
Plain SQL accessDune SQL onlyGraphQLRaw JSONYes
Reorg & gap handlingTheirsYesOn youBuilt-in
Setup effortLowMed–highHighOne YAML

Honest positioning: Dune stays great for ad-hoc analytics; The Graph for hosted multi-chain. Arckive is for teams that want their own Postgres, plain SQL, and K8s-native ops — together.

Get started

One YAML. A running indexer.

Runs in your cluster. Your data never leaves it.

kubectl apply -f https://arckive.org/install.yaml

Runs in your cluster · Apache-2.0 · v1alpha1