Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Known limits

What mushroomdb does not do, or does only up to a point. Each row says what was measured and where.

LimitationDetail
Memory-firstThe working graph lives in RAM. Measured to 100,000 nodes and about 10 million derived edges, on a 24 GiB machine, across two builds: on v0.1.1 (2026-08-24), 4.72 GiB peak while building it and 8.09 GiB to replay the WAL with no snapshot; on v0.2 (2026-08-28), 0.02 s at 31–41 MiB to reopen from a snapshot, which is memory-mapped rather than loaded. None of these was re-measured on the current build. Ten million nodes was the original design intent and is not a measurement. A memory-shaped run on 0.8.0 (entities with text, the memory schema, about 1.6 edges per node and one rule) reached 1,000,000 nodes at 2.65 GiB peak, opening in 1.18 s from a snapshot and 11.3 s from the WAL, with recall at 66 ms p50; its one rule tripped its 1,000,000-edge budget, so that run says nothing about ten million derived edges at that size. In the 100,000-node run each rule was capped at 1,000,000 derived edges. See dogfood/results/scale-memory-1m.md. See dogfood/results/scale-100k.md.
Single writer, no interactive transactionsOne writer at a time, many readers — within a process via RwLock, across processes via the advisory LOCK file. write_batch commits all ops in one WAL frame (all-or-nothing on crash replay) but is not isolated: readers may observe intermediate states while a committed batch is applied in memory. Multi-statement BEGIN/COMMIT is not supported, and there are no cross-process transactions.
Peer writes do not notify subscribersCommits another process made are picked up by refresh() and are there on the next read, but they fire no EdgeFired/EdgeRetracted event, so /watch and /subscribe see only writes made through this process. Poll if you need to react to a hook’s writes.
Cold start without a snapshot re-fires all rulesSnapshots persist derived edges, ANN state, and view definitions. At 100k nodes / ~10M derived edges: 0.02 s from a snapshot (measured on V8; the format is V9 now, V10 with multiplicity) vs 8.16 min WAL-only (ANN re-fit dominates). Call snapshot() before close. See dogfood/results/scale-100k.md.
Two-hop Cypher joins at scaleDense patterns producing >1,000,000 intermediate rows error without LIMIT. Add LIMIT n — the pull-based executor stops early and never materializes the full binding table.
Cypher write subsetCREATE, MATCH…SET, MATCH…DELETE, MATCH…DETACH DELETE, and MERGE (single-key, with ON CREATE SET / ON MATCH SET) are supported. Derived edges cannot be deleted manually. Variable-length paths are hard-capped at 10 hops; unbounded *min.. is rejected at parse time. Full coverage table: docs/site/query.md.
Approximate vector mode is opt-inapproximate: true enables HNSW candidate selection. Per-query recall floors min 0.90 / mean 0.95, measured 1.0 / 1.0 at 5k / dim 1536 (fixed-seed probe). Review the trade-off before using it in completeness-critical workloads.
Demo refuses existing directoriesmushroomdb demo exits 1 if the target directory is non-empty, including hidden files (.DS_Store counts). Use a fresh path.
Python bindings return dictspandas/polars zero-copy is not wired yet. HTTP POST /query defaults to Arrow IPC; JSON via ?format=json.
Insert-count multiplicity is opt-in and one-wayenable_multiplicity() starts recording a per-pair insert count, which degree(…, multiplicity=True) sums; both default to False, so every existing caller keeps unique-neighbour semantics. Opting in writes a V10 snapshot that releases before 0.6.10 refuse by name, and there is no call that opts back out. The call is not atomic either — an exception means outcome unknown, not nothing happened: reopen and call is_multiplicity_enabled(). A store that never calls it stays V9 and readable by every release back to 0.6.5.