Research turso source review - kmosoti/FabricO11y GitHub Wiki

Historical report imported 2026-10-10 from docs/research/turso-source-review.md. Original SHA-256: b1ea46418d7318eb5712535a0ce0cebfee379f03db035635a08147a2b4e03739. Measurements and outcomes retain their stated revisions. Links and local environment labels are normalized; $FABRIC_DATA is the mounted experiment drive. See evidence policy.

Turso source review: lessons for Fabric

Status: exploratory source review, 2026-10-08; tier 6 of the source-of-truth order. No implementation, performance comparison, qualification or dependency adoption is recorded here.

The cross-system program incorporates this review with the subsequent Comet, Feldera, Vortex and broader research agenda. Its draft queue carries the next lab assignments and resource gates.

Scope and provenance

The subject is the Rust database engine tursodatabase/turso at ff97ec42cdef94651a6985eb47e8f9d07e4608cd, not the hosted service or the separate libSQL repository. Its README describes a SQLite-compatible in-process engine and SQL frontends compiling to a common execution engine. This review follows selected storage, allocation, execution and testing paths; it does not audit the entire engine or assess its release.

GitHub supplied 24 complete source/document files and lines 1–60 of README.md. Selected ranges were inspected. The source manifest (local checkout reference docs/research/turso-source-manifest.json; not present at origin/main) records their Git blob identities and hashes of the relevant Fabric working-tree files. Fabric HEAD was d6669a2353b11e43039aaae34d5a2ce6fa00d9c6, with existing uncommitted work; HEAD alone does not identify the inspected implementation.

During the initial review, the requested local checkout could not be placed on the required data drive. Read-only inspection with findmnt -T $FABRIC_DATA -o TARGET,FSTYPE,OPTIONS exited 0 and reported ext4 mounted ro,nosuid,nodev,relatime,seclabel,errors=remount-ro. That observation does not diagnose why the mount is read-only. Source retrieval used the GitHub connector; there is no local Turso checkout or vendored copy. No system-disk scratch, project workload, installation or remote-host workload was started.

Execution continuation: the registered readiness slice (local checkout reference docs/experiments/benchmarks/catalog-cross-system-readiness-protocol.md; not present at origin/main) downloaded the pinned archive to the now-writable data drive (curl exit 0). It inventoried 4,180 regular files, 77,779,672 decoded bytes, matched the 24 previously reviewed complete Git blobs, and retained five compressed source snapshots with exact readback. The 17,004,455-byte download was removed after recording its digest and complete member inventory. No checkout was extracted and no Turso build or benchmark ran. See the execution receipt (local evidence omitted from stage).

Findings and transfer limits

1. Storage resolves the physical location at a logical snapshot

Observed: Turso's pager read path first looks for an eligible WAL frame and otherwise reads the database file. The WAL lookup uses page-to-frame metadata and a snapshot range; latest_frame_in_range uses a partition point in the ordered frame list. Query execution need not rediscover whether a page currently lives in the WAL or database file.

Fabric already moves in this direction: ReadCatalog (local checkout reference crates/fabric-server/src/read_catalog.rs; not present at origin/main) owns Walk discovery, tail locations, bounds and filters. Scan still acquires sources in query.rs. The useful extension is one storage-owned snapshot resolution boundary for both plans, with exact evidence and unavailable coverage explicit. Fabric's append-only observations do not need Turso's page-version machinery to achieve that separation.

Transfer limit: a metadata handle must not become a retention lease. Fabric returns Gone for expired page snapshots. Its range-evidence work also distinguishes conservative pruning bounds from exact freshness. A cached maximum cannot replace required raw digest checks or reconstruct arbitrary clipped ranges. An epoch or cache key alone does not prove that stored bytes are intact.

2. A cache size is not a complete memory bound

Observed: Turso's page cache uses a SIEVE/GClock variation, with a small access counter and eviction sweeps. It tracks dirty/spilled state and considers pins and live references when deciding what can be reclaimed. Its forced insertion paths explicitly exceed capacity when normal eviction cannot make room, including rollback restoration. The buffer pool also falls back to temporary allocations when its arena is full. These are documented progress choices, not evidence of a process memory ceiling.

Fabric's tail reader caches 64 decoded frames and builds blocks using a record-count threshold. Its process-wide entries and compressed blocks follow uncovered journal history. The optional descriptor cache (local checkout reference crates/fabric-server/src/coupled_catalog.rs; not present at origin/main) estimates 8 MiB for its own domain; the two HTTP query permits bound concurrency. None of those facts alone establishes aggregate query memory. A large payload and a backlog make the difference between count and byte bounds consequential.

Inference: account resident derived data, in-flight buffers, decode working sets, retained output and old metadata generations together. Reserve before allocation or expensive admission; a check after allocation cannot prevent the peak. Release the charge with its actual owner. Keep a bounded progress reserve so all capacity is not held by work waiting for another allocation.

A useful ownership equation is:

tracked_live = base + resident_cache + inflight + decode + output

These categories must be disjoint: pinned cache bytes are part of resident_cache, not counted twice. Shared allocations are charged once to an owner, while estimated reservations remain distinguishable from measured live bytes. Allocator totals, RSS and cgroup memory are different observations; file cache and kernel charges still require operating-system measurement and containment.

For optional derived cache data, eviction or bounded bypass can preserve exact journal reads. An evicted block must also release or repair its entry-to-block mapping so fallback never becomes silent omission. Whether that policy improves latency is a hypothesis. Copying Turso's soft-cap overflow would not satisfy Fabric's boundedness objective.

3. Borrowed views and reusable buffers are separate optimizations

Observed: Turso's record references represent borrowed, owned and shared payloads. Its cursor payload fast path can return a slice directly from a page; overflow and restoration use other paths. The cursor also retains reusable record/write buffers and invalidates cached offsets when movement or writes make them stale.

Fabric already borrows raw Batch fields and log strings, moves decoded log Strings and uses dense Top-k payload slots. The concrete remaining inspection targets in segment.rs are owned metric/span construction and the attribute map still constructed for each in-window borrowed log before its callback. That is an allocation opportunity, not yet a measured bottleneck.

Preserve existing malformed-data detection and error order. Moving ownership later is different from skipping validation of rejected records. Reusing a buffer also needs a retention cap: one exceptional payload should not leave a large allocation attached to every long-lived worker. Turso uses unsafe code inside some storage/record internals; this is not evidence that Fabric needs unsafe code or a custom arena. Prefer its existing safe lifetime-bound views.

4. Explicit progress makes unfinished work inspectable

Observed: Turso's IOResult distinguishes completed work from pending I/O. The pager pending-read path preserves the same read across re-entry after a spill yield; it also yields instead of handing out a cache-resident page whose load has not finished. This is a specific pager re-entry mechanism, not a claim that all requests throughout Turso share one read.

Its completion groups link children before submission, and the I/O interface provides cancellation and draining of owned completions. Fabric's worker ownership (local checkout reference crates/fabric-server/src/lifecycle_workers.rs; not present at origin/main) and query permit corrections express the same requirement: losing the caller does not erase unfinished work or its cost.

Inference: retain explicit ownership and observable transition cuts when extending storage work. A wholesale replacement of Tokio with a manual state machine would add re-entry hazards without an established benefit. Likewise, Turso's Unix PlatformIO alias uses UnixIO; UringIO is separately feature-gated. An asynchronous engine design does not by itself demonstrate an io_uring performance win for Fabric.

5. Calibrate costs against work that actually happened

Observed: Turso's scan cost model separates first/repeated page reads and row CPU. Its parameters include explicit fallback cardinality/selectivity and relative operation costs. Structured explain output labels estimates separately from execution counters. These constants are heuristics, not coefficients measured on Fabric's workload.

The useful Fabric model extends the earlier source/group/row/materialization model with costs that the recent range investigation could not yet separate:

T = Tdiscover + Tread/decompress + Thash + Ttyped_validate
    + Tfilter/select + Town_result + Tencode_response

Instrument counts and bytes alongside time: sources considered, groups read, compressed/decoded bytes, bytes hashed, typed records visited, rows owned, allocation requests and output bytes. Use existing phase-probe support (local checkout reference crates/fabric-frame/src/probe.rs; not present at origin/main), while respecting its documented overlapping allocator observations. Avoid fitting several coefficients from workloads where their explanatory variables always move together. Hold out workloads and retain fixed-policy baselines.

Turso's scan-loop benchmark contrasts traversal with decoding; its record-recycling benchmark checks that the intended operations are present and keeps setup outside the measured closure. This is particularly relevant after Fabric's earlier observer-overhead finding. Diagnostic ablations may isolate stages, but a serving candidate must retain the full integrity contract.

6. Schedule failures where the implementation can actually yield

Observed: Turso has a seeded yield injector, selected-site allocation failures, and FTS recovery/cancellation cuts. Its simulator documentation explicitly limits what those runs establish. Inspection of SimulatorIO confirms writes modify mapped bytes before completion delivery and sync is a simulated no-op. Those paths do not establish physical power-loss durability.

Fabric already has simulation and deterministic native regressions, including snapshot publication/retention (local checkout reference crates/fabric-server/tests/query_snapshot_transition.rs; not present at origin/main). The next useful extension is a compact schedule of real accepted-work, publication, reclaim, cancellation and reopen cuts, graded by the unchanged producer-derived delivery/query oracles. Record executed cuts, not merely attempted fault probabilities. Retain minimized failures. Native filesystem tests and power-loss assumptions remain separate from a simulated schedule.

What should remain different

Fabric's durable unit is an exact telemetry Batch; Turso's conventional WAL stores database pages. Fabric needs stable telemetry ordering, freshness, completeness and bounded retention across its journal and compressed Segments. This review supplies no evidence that a B-tree/SQL replacement improves those workloads. SQLite adoption is also outside the current product profile.

Preserve Fabric's two-sync journal commit and publish-before-reclaim rules. Turso's WaitSync state waits for write completion before syncing, and its sync behavior depends on mode. That is a useful ordering example, not permission to borrow a weaker durability setting or change Fabric's ACK semantics. Its transaction guide is not sufficient evidence for all current paths; source contains mechanisms beyond that guide's description.

Next experiments, in order

These are nominations for the existing labs, not registered runs or dispatched jobs. Register finite workloads, seeds, decision thresholds and evidence limits before execution. All runs and validators require the existing resource-group launcher and writable data-drive scratch; preserve failures before cleanup.

Lab First experiment Hypothesis and null Evidence required
Query Census complete paginated queries over tail-only, sealed-only and boundary-crossing history; vary payload width and row count separately H: a small number of measured stages explain cost on held-out cells. H0: interactions/reader costs defeat the model Stage CPU/wall, actual bytes/counts, allocation/peak, full oracle answers, cold/warm and mixed-ingestion cases, instrumented/plain overhead
Memory/storage Byte-budget optional tail/frame data, then compare simple eviction with SIEVE-style eviction at the same budget H: derived resident memory plateaus under increased backlog while exact fallback preserves answers. H0: pinned/pending/output memory escapes the charge or fallback causes unacceptable tails Ownership totals, largest frame, old generations, cgroup peak/RSS, ACK/query p99, offered/accepted/rejected Batch rates, drain progress; eviction-mapping negative control
Lifecycle Seeded schedules around accepted submission, absent ACK, canceled query, Segment publication and retention H: every observed cut preserves custody, snapshot metadata and owned-work accounting. H0: a schedule leaks work, loses/duplicates custody, changes an old snapshot or revives expired coverage Exact cut transcript and replay, unchanged independent oracles, restart/retry, Gone controls, bounded failure artifacts, zero residual owned work after join

After the census, compare borrowed/reused metric or span projections only where materialization is a measured contributor. Extend snapshot resolution only where duplicated discovery is material. Test an I/O backend change only if read/queue wait remains dominant after those measurements. The present review predicts no speedup percentage and selects no production default.

Review outcome and remaining work

The immediate lesson is to connect the existing storage map, borrowed readers, resource ownership and independent tests with better measurements of work and bytes. Turso provides concrete implementations of those mechanisms and useful counterexamples to the idea that Rust or a configured cache size automatically ensures bounded memory.

This Turso review added its research record, source manifest and navigation link; the subsequent cross-system program is linked above. No source tree or experiment scratch was created, so there was no workload cleanup. Rust tests, Turso benchmarks and manual documentation validators were not run at that point: the required scratch/build volume was read-only. The local checkout and executable comparisons remain outstanding. This record is static evidence for candidate selection, not a performance or reliability result.