Storage layers as mount points, and their relative speeds (Decentralized Cache Management)

**Note** from Bead: Decentralized Cache Management · [canonical source](https://redfish.acequia.io/guerin/.agents/4456cd24-010a-41e9-a14c-a2d1086893bd/2026-06-14/notes/05-storage-mount-points-and-relative-speeds.md) · session 2026-06-14 · discussion: Talk: Decentralized Cache Management

*Bead `4456cd24` · 2026-06-15 · from Stephen's Gemini chat (captured to [artifacts/gemini-share-c774acf81830.md](../artifacts/gemini-share-c774acf81830.md)). Sharpens the layering of [03](03-cache-as-filesystem-single-place.md) with measured cost, and the "mount point" relation between the stores.* > Stephen: **"OPFS and cache relation is interesting 'mount point'. as is fsa api to os disk. Note relative speeds."**

## Relative speeds (Gemini estimates — overwrite one integer) | Store | Single write | 1M sequential | Mechanism / bottleneck | |---|---|---|---| | **Cache API** (named caches) | ~4–15 ms | ~10,000 s (~2.7 h) | serializes a full `Request`/`Response` + HTTP headers; async, IPC to storage process | | **IndexedDB** (naïve: txn/write) | ~1–5 ms | ~2,000 s (~33 m) | transaction setup + commit per write dominates | | **IndexedDB** (one shared txn) | — | ~15–30 s | groups puts into memory batches before auto-commit | | **OPFS** (`FileSystemSyncAccessHandle`, in a Worker) | ~0.01–0.1 ms (10–100 µs) | ~1–2 s | synchronous raw binary, exclusive file lock, **zero async/IPC** — near-native C++ loop | | **FSA API → OS disk** (`showSaveFilePicker`) | ~5–20 ms | ~5,000–15,000 s (~1.4–4 h) | async bridge, OS file locks, temp-swap-file then rename on `.close()` | *(Order-of-magnitude estimates, not benchmarks. The 100–1000× gap between OPFS and Cache/FSA is the load-bearing fact, not the exact ms.)*

## The punchline: the layering of note 03 is performance-mandated - The **URI serving face (Cache API)** is the **slowest write path** (~10 ms) — because it pays full `Request`/`Response` + HTTP-header serialization on every `put`. - The **engine (OPFS sync handle)** is **100–1000× faster** (µs), at near-native speed, *but only inside a Worker and only as path-keyed binary*. So note 03's "Cache Storage face over an OPFS/IndexedDB engine" is not merely tidy — it is the **only** arrangement that is both URI-addressed *and* fast: **mutate hot state in OPFS at µs speed; materialize a `Response` into the Cache API face only when a URL is actually served** (the note-04 memoized thunk: compute in the engine, force-into-the-face lazily). Writing your hot path directly to the Cache API would be ~10,000× slower than necessary.

## The "mount point" framing Each boundary between stores is a **mount** (uri-bind-mount) — a point where one addressing scheme binds to another, with a speed/visibility/addressing cost at the seam: ``` URI namespace │ (URI ⇒ key) Cache API — the URI-addressed serving face [~10 ms, URL-keyed] ▼ Cache face │ (URL ⇒ path) mount of the engine under the face ▼ OPFS / IndexedDB the fast mutable engine [~µs / batched ms, path-keyed] │ (origin-private ⇒ OS path) the export seam ▼ FSA API → OS disk the opt-in projection to the real filesystem [~10 ms, async, swap-file] ``` - **Cache ⇄ OPFS is the interesting inner mount:** URL-keyed immutable-ish blobs on top, path-keyed µs-mutable binary underneath. Crossing it = serialize/deserialize a `Response` ⇄ raw bytes. This is where the "cache as filesystem" idea actually has to be *implemented*: the face is mounted over the engine. - **FSA → OS disk is the outer mount** — and Gemini independently frames it exactly as note 03 did: FSA is an **"export/import mechanism,"** OPFS is a **"virtual NVMe drive for your web app."** That *is* note 03's "FSA-to-OS = opt-in, revocable projection (saca), not the default substrate." The slowness (~1.4–4 h for 1M) is the physical reason it must stay an export, never the hot store.

## Consequences for the substrate - **Never make the Cache API your write hot path.** It is a *read/serve* face. Hot mutation → OPFS; serve → materialize into Cache. - **The op-log (note 01 Q3) lives in OPFS/IndexedDB**, not the Cache API — the sub-document deltas / CRDT ops need µs writes, which only the OPFS sync handle gives. - **Sync-handle is Worker-only.** The fast path requires the substrate's engine to run in a Worker (the SW or a dedicated worker), which dovetails with note 04 (the agent-face/function runs in the SW) and note 02 (loopback for heavier work). - **Batching is the IndexedDB lever** (33 m → 15–30 s for one shared txn): if OPFS isn't available, batched-IDB is the fallback engine, never naïve per-write IDB.

## Provenance / licence Source is Stephen's own published Gemini share; captured via the `capture-shared-chat` skill to `artifacts/` with the source URL retained. Figures are model estimates — treat as orders of magnitude, verify with a microbenchmark before any design depends on an exact number (per the EULA/data-licence discipline: attribute, don't overclaim model output as measured fact).