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