cqlite-flight — v0.15.0 Milestone Verdict

v0.15.0 milestone snapshot (condensed) · flight v0.15.0@sha256:30c2b10c (multi-arch INDEX) · connector 0.15.0 · Trino 481 · Cassandra 5.0 RF=3 · 3× i4i.xlarge · ~1.93M partitions/node, 2 SSTable gens · 2026-07-17

Is 0.15 sound? Yes. 7 / 8 VERIFIED Every claim a condensed run can test passed; multi-day stability (claim 8) is out of scope by design and its short-horizon proxies are all green. The milestone's key open flag — the background snapshot grace-sweep (#2452) — is confirmed fixed in the field. Three things to report, none a blocker on the milestone verdict: a fan-out skew that caps throughput, a 0.89% server-side do_get error rate that is client-invisible, and a harness metrics-pipeline bug that inflated the dashboard's rate() panels ~1000× — found, fixed in easy-db-lab, and verified during this run (future runs are correct). All three detailed below.

Claims table

#ClaimVerdictEvidence
1~15× warm throughput (snapshot lifecycle, lazy index, point-read streaming)VERIFIED90 min @ 32-thr: 211,373 queries, ~39 qps, p50 798ms, p99 1366ms, 0 client errors. Parity+ vs R12 (~33 qps@8-thr).
2Admission control under overloadVERIFIED80-thr burst: admission peak 4 (≪64 limit), qps flat (graceful queuing, not collapse), 0 client err, clean recovery to baseline.
3Saturation observability (blocking/egress/fd/threads/RSS)VERIFIEDAll gauges legible and returned to 0 after load. Caveat: OTLP ~15s (and our 10s sampler) undersamples the ~2s gauge — peaks are lower bounds.
4Snapshot retirement — background grace-sweepVERIFIED660→6 snapshots at t=5min with ZERO queries. The R12 regression (query-triggered only, held 738 while idle) is FIXED. This was the key open flag.
5No silent row loss on large cells (≥1MB)VERIFIEDIntegrity sweep #1 == sweep #2 == 1,927,467 rows. Zero delta across 90-min load + 80-thr burst.
6Query-semantics correctness under concurrencyVERIFIED6 concurrent identical point-reads → 1 distinct result hash (byte-identical); mixed concurrent queries all correct.
7Cold start / restart behaviorVERIFIEDCold first-query 2.2s (≈ JDBC floor), 0 index parses at boot. Killed-pod failover returned identical count; Trino coordinator restart clean, catalog + add-opens survived.
8Multi-day stabilityCOULD-NOT-OBSERVEOut of scope for a condensed ~2.5h run. Proxies all green: RSS flat 301–357Mi, 0 OOMKills, 0 unplanned restarts, no fd/thread drift.

Headline — throughput & latency (90-min steady state, 32 threads)

Metrics note: the kit dashboard's rate()-based panels (RPC req/s, rows/s, error-rate) are unreliable this run — a metrics-pipeline bug inflates them ~1000× (see the metrics-pipeline bug section). The numbers below come from the loadtest driver (persistent-connection counts) and raw counter deltas, which are correct.
Metric (loadtest driver, 32-thr, 5400s)Value
total queries / rows211,373 / 3,373,635
steady-state qps~38–40
p50 / p99 latency798ms / 1366ms
client errors0
warm ramp (cache fill)p50 2033ms (30s) → 1262ms (90s) → ~800ms steady

Grafana latency panels are shown for shape only — they derive from rate() over histogram _bucket counters and are subject to the same pipeline bug. The authoritative p50/p99 are the driver numbers in the table above.

RPC duration p50 by method (shape only — see metrics note)
RPC duration p50 by method (shape only — see metrics note)
RPC duration p99 by method (shape only)
RPC duration p99 by method (shape only)

Findings (report, not pass/fail)

1. Fan-out skew — the throughput ceiling FINDING

One flight pod carried the bulk of the work (~650m CPU / 297Mi) while the other two sat at 140–300m / 28–39Mi. All three participated (0 client errors), but the load is single-pod-heavy — the same token-range-dependent pattern seen in R9/R10b. This is why throughput landed ~39 qps, short of the Lane-B B2 goal (≥100 qps @ 32 threads). Not a correctness or stability problem; a distribution-evenness one.

2. do_get server-side errors — 0.89%, client-invisible FINDING

0 client-visible errors the entire run (loadtest final: errors: 0). But the server-side counter shows do_get error = 8,563 vs ok = 951,762 = 0.89% (R12 was ~1.2%), all in category other. What the investigation found:

Best interpretation (consistent with, not proven in-field): aborted / superseded scan splits — when a multi-split scan has enough data, the coordinator abandons the remaining in-flight do_get streams and the server records them as errors. Load-proportional + client-invisible + busy-pod-concentrated all fit that. Why it can't be closed here: category other is too coarse to name the cause, and there is no log line to trace. To reach 0: finer error categorization + a debug trace on the do_get abort path, then stop counting superseded-split teardown as an error if that is the cause. Recommended as a P2 follow-up.

(The 0.89% is computed from raw counter totals — do_get ok 951,762 vs error 8,563 — not from the rate() panels below, which are shape-only per the metrics bug.)

Flight error rate (% of requests) — shape only; magnitude distorted by the counter bug
Flight error rate (% of requests) — shape only; magnitude distorted by the counter bug
Flight errors/sec by category — all in 'other'
Flight errors/sec by category — all in 'other'

Metrics-pipeline bug — rate() panels inflate ~1000× FIXED

The "RPC Requests/sec" panel (and the other rate()-based panels) show a rising, accumulating line reaching ~2.35 million/s. Actual throughput was ~39 qps (~176 do_get/s). Investigation:

Verdicts unaffected. The counter data is correct — raw per-collection increments are clean and monotonic (~15,600/15s). Every throughput/latency figure in this report comes from the loadtest driver (persistent-connection counts) or raw counter deltas, never from rate(). Gauges (RSS/threads/fds/admission/egress) are instantaneous, not counters — also unaffected.
FIXED & verified (easy-db-lab-side). Root cause was the harness OTel config, not cqlite: the collector's metrics/otlp pipeline lacked resourcedetection, so OTLP-received flight metrics carried no per-node label. Fix: added resourcedetection to that pipeline in otel-collector-config.yaml (matching the EMR config, which already had it). Verified live on this cluster — after the change, metrics gained host_name=db0/db1/db2 and sum(rate(...)) by (host_name) read do_get ok db0 63 / db1 125 / db2 257 = 445/s total (sane; the fan-out skew is even visible in the split), errors 7.45/s — no longer millions. Future runs are correct. This run's pre-fix window stays distorted, so every figure in this report is sourced from the driver / raw deltas.