Wavelength / Ark stack · regtest, never reset · bottleneck snapshot

Wavelength Growth Bench

One operator (lumosd, postgres) and ten clients (waved, lwwallet on sqlite) on a regtest chain that only advances when the harness mines. Every epoch runs 30 random client-to-client OOR payments and one all-client refresh round, on top of everything prior epochs created. The question is not how fast the stack is on a clean network, but what the same payments and rounds cost once the operator's round history, indexer and mailbox have real volume in them.

Load cases

Time to complete each case

Wall clock per case, measured separately. Because state is never reset, an upward slope is the cost of accumulated history rather than run-to-run noise. The refresh number includes the harness-mined confirmation, so its floor is set by the round protocol, not the daemons.

Payments

OOR send latency

Per-payment time from submitting the send to the OOR session reaching its terminal state, across the 30 sends of the epoch. Sends run ten at a time (every client sends at once), so the spread between the median and the slowest send is the contention signal.

Rounds

Refresh round completion

Per-client time from queueing the refresh to that client's round reaching a terminal state, all ten clients in the same round. The median and the slowest client should track each other; a widening gap means some clients wait on work the round does per participant. A client whose quoted refresh fee would leave too little residual value refuses to join ("insufficient_residual"): those fee-quote rejections count in the epoch detail as their own bucket, not as failures, and are excluded from the timing percentiles.

Capital

Deployed against user capital

Three views of the system's money. Deployed is the operator ledger's deployed_capital: every sat locked in unexpired on-chain batch outputs, including the operator's own refresh liquidity and fully-forfeited history the sweeper has not reclaimed yet. User spendable is the sum of all ten clients' confirmed offchain balances. Live vtxo value is the operator indexer's total for live vtxos, an independent measurement that should track user spendable exactly. The gap between deployed and the other two is capital the operator has committed beyond what users can spend; batch expiry (1008 blocks after a round confirms) is when the sweeper starts winning it back.

Capital efficiency

Sats locked per sat of user balance

Deployed capital divided by user-spendable capital: how much the operator has locked on chain to give users one spendable sat. Every refresh round adds newly-committed outputs while the forfeited batch stays locked until its expiry, so this ratio is expected to climb between sweeps and fall when the sweeper reclaims expired batches. A ratio that only ever climbs means reclamation is not keeping up.

Capital conservation

Where every sat is

Every sat in the system entered through a harness-made boarding deposit, so total-deposited is known exactly, and conservation residual = deposited − user spendable − pending − operator fees must be zero: any other non-null value means sats appeared or vanished somewhere in the stack. claims residual cross-checks the operator ledger's own user_vtxo_claims liability against what clients report; as wired it trails by exactly the cumulative refresh fees, so it tracking the fee line is the known baseline and a departure from that is the signal. Epochs before this was measured render as gaps.

Operator storage

Operator database

Total size postgres reports for the lumos database. Postgres carries a fixed multi-megabyte catalog baseline: read the slope, not the offset. The largest tables behind this number are in the snapshot.

Storage growth

Storage added per epoch

Marginal cost of one epoch's work: the operator's postgres growth against the summed sqlite growth of all ten clients (main files plus WAL). Flat means the cost per unit of work is holding; a rising line means each epoch stores more than the last for the same 30 payments and one round.

Client storage

Client databases

Summed sqlite footprint of all ten clients, and wb-client01 alone as the representative client (clients are symmetric by construction). Includes each database's WAL, so a stalled checkpoint shows up here as growth the main file never sees.

Memory · operator

lumosd memory

Resident set sampled once after the epoch's cases finish, so it is where memory settles rather than a peak during the run. The high water mark is memory.peak from the container's cgroup: it cannot be reset without root, so it only ever rises, and a mark that keeps climbing epoch after epoch is the leak signal.

Memory · client

wb-client01 memory

Same measurements on the observed client. One client stands for all ten: they run the same binary against the same operator with the same workload shape.

Runtime

Goroutines

Live goroutine count on the operator and the observed client at the end of each epoch. A count that grows with the series and never settles is a leaked-goroutine signal; growth proportional to load that returns to a floor is normal.

Every epoch, as measured