Kubernetes-native Soroban event indexer for Stellar

Your contract events,
in your own Postgres.

Give it an event spec and a contract ID. Sorolog streams every Soroban event into your own PostgreSQL — one table per event, reliable and gap-free — from a single YAML manifest. Point it at any stellar-rpc, or run your own captive core in-pod and read straight from the validators — chain to SQL as low as 244ms.

runs in your cluster · apache-2.0 · sorolog.com/v1alpha1
sorolog — usdc-stellar
$
The gap

Hosted indexers are delayed, rate-limited, and keep your data on their side. Raw stellar-rpc leaves paging, the retention window and XDR decoding to you. SubQuery means projects 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 — schema, tables, worker, status.

STEP 1

Write one manifest

Contracts, event-spec ref, source (rpc or your own core), storage — the whole setup.

kind: Indexer
metadata: { name: usdc-stellar }
spec:
  rpc: # health-checked failover
    - https://soroban-testnet.stellar.org
  contracts:
    - contractId: "CBIEL…DAMA"
      eventSpec: { configMapRef: usdc-events }
      startLedger: 0
STEP 2

The operator provisions

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

Indexer CR — 1 YAML
Sorolog Operator
schema · tables · worker · status
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", amount
FROM usdc_transfer
WHERE amount > 1000000000
ORDER BY ledger DESC;
GA7Q…PZWM GDRX…H2LV3,020.95GB2K…4JTA GCQL…X59W3,454.57GDKI…M3UB GA5T…B7DA60,884.96

event spec in → tables out · empty events list = every event in the spec · startLedger: 0 backfills from the RPC retention window

02Two ways to run it

Bring an RPC, or be the source.

One field decides where your events come from. Start on any stellar-rpc; run your own captive core when latency matters. Same schema, same rows either way — source: rpc | core.

source: rpcdefault

Point at any stellar-rpc

A public endpoint or your own. Sorolog polls it with phase-locked, gap-free ingestion — no paging, retention, or XDR decoding left on you. Nothing extra to run.

infra
none beyond the worker
latency
as low as 747ms
nodes
any architecture

Best for most indexers. Start here.

source: corelowest latency

Run your own node, in-pod

Sorolog runs captive stellar-core inside the worker and reads events straight from the validators — no RPC and no provider queue anywhere in the path.

infra
captive core · amd64 node
latency
as low as 244ms
reads
straight from the validators

When every millisecond counts.

Both modes write byte-identical rows into your Postgres — same tables, same event ids — so you can switch a running indexer by changing one field. Deleting the CR cleans up the worker; your data stays.

03Reliability

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 ledger 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.

No reorgs on Stellar

Ledgers are final the moment they close — what Sorolog writes never gets rolled back.

RPC failover

A passphrase-checked pool with rotation and backoff. A blip never becomes a gap.

chaos lab — try to lose datasimulated
soroban-rpc-1soroban-rpc-2worker pod
ledger head
3,591,310
cursor
3,591,310
lag
0
gaps
0
t+0.0s✓ usdc-stellar · phase=Live · cursor=head · lag=0 · gaps=0
the invariant: gaps stay 0
04Benchmarks

Measured, not promised.

Every number comes from running the real worker against the public Stellar testnet and reading only its production surface — Postgres rows and /metrics. Two ingestion modes, same data: point it at any stellar-rpc, or run your own captive core in-pod and read straight from the validators.

chain → SQL · source: core
as low as 244ms

Own node, straight from the overlay — and that's under x86 emulation; native hardware is faster still. Full distribution in docs/benchmarks/.

chain → SQL · source: rpc
as low as 747ms

Public RPC (gateway.fm + SDF), bounded below by the provider's ~0.87s visibility floor — which source: core deletes entirely.

throughput
7,913 ev/s

Burst-ingest ceiling (multi-row transactional writes); backfill catches 50,000 real ledgers at 2,626 ledgers/s.

Measured on the same live ledgers into the same Postgres, source: core delivered every ledger a median 579ms sooner than the public-RPC path and never slower — while producing byte-identical rows (277/277 shared events matched). rpc mode needs zero extra infra and stays the default; core deletes the provider floor for the lowest latency. Methodology and raw results live in docs/benchmarks/.

05Compare

A specific combination nobody else offers.

MercurySubQueryRaw RPCSorolog
Data in your own DBNoVia subquery-nodeIf you build it✓ Yes
Plain SQL accessGraphQLGraphQLRaw XDR/JSON✓ Yes
Retention & gap handlingTheirsYesOn you✓ Built-in
Setup effortLowMed–highHigh✓ One YAML
Measured latencyNot publishedNot published✓ as low as 244ms own node · 747ms public

Honest positioning: Mercury stays great for hosted zero-ops indexing; SubQuery for multi-chain projects. Sorolog 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://sorolog.com/install.yaml
runs in your cluster · apache-2.0 · v1alpha1