Vector storage: is sqlite-vec really the best fit for Synapse?
| Field | Value |
|---|---|
| Date finalised | 2026-06-02 |
| Author | Rômulo Febasi <romulo@febasi.com.br> (analysis assisted by Claude Code) |
| Scope | Owner-prompted critical review (2026-06-02) of the ADR-008 decision to adopt sqlite-vec. Survey of the 2026 alternative options: LanceDB, SurrealDB embedded, DuckDB + VSS, vectorlite, usearch, Qdrant embedded: measured against Synapse’s actual constraints, not generic benchmarks. |
| Status | accepted: confirms ADR-008 stays as written; registers vectorlite as the documented upgrade path for v0.7+ if we hit the flat-scan ceiling |
| Inputs | ADR-003 (rusqlite bundled); ADR-008 (this week’s decision); v0.5 brief §2.2; live walks of asg017/sqlite-vec, lancedb/lancedb, surrealdb/surrealdb, 1yefuwang1/vectorlite, unum-cloud/usearch repositories; 2026 benchmark write-ups on slashdot, peerspot, thedataquarry, lancedb.com; Alex Garcia’s roadmap statements on the sqlite-vec issue tracker. |
| Out of scope | Migrating FTS5, the audit trail, Workspace::tx, the pending queue, or any other SQLite-resident feature out of SQLite; this brief evaluates the vector storage slot only. |
Executive summary
Three honest answers to the owner’s question:
- For Synapse’s actual workload (≤ 10k entities per workspace,
federation handles scale by chunking),
sqlite-vecis the right pick. It is recent, maintained, and fits our existing.synapse/index.dbmodel cleanly. ADR-008 stays as written. - For a 2026 greenfield project starting from scratch with no
SQLite baggage, the answer would be LanceDB. It is the
architectural option born for the workload. We are not greenfield.
Migrating from SQLite to LanceDB costs more than the upside
delivers at our ceiling:
Workspace::tx, FTS5 ranking, audit trail, pending queue, federation registry are all tightly coupled to the SQLite engine. Re-implementing them is a v1.0-shaped task, not a v0.5 spike. - The honest upgrade path exists. If a Synapse user ever exceeds
~100k entities per workspace and the flat-scan latency becomes
visible, the drop-in replacement is
vectorlite(HNSW-based, ~10× faster searches thansqlite-vec’s flat scan, same loadable- extension shape, still SQLite). Registered as the v0.7+ pre-staged ticket so the option is not lost.
1. The constraint set that actually matters here
The vector storage choice has to satisfy seven hard constraints before any benchmark number is relevant. Most “is X better than Y” articles online ignore these because they are project-specific:
| Constraint | Source | What it eliminates |
|---|---|---|
Atomic FS + index transactions (Workspace::tx) | BR-6, ADR-003 §Consequences | Any backend without a transaction model that composes with the filesystem write |
| Append-only audit trail living next to the index | BR-12.3, ADR-013 | Any backend that requires a separate process or separate storage mount |
| FTS5 ranking already shipped in 121 tests | v0.4 codebase | Any backend that forces a re-implementation of full-text from zero |
| Single binary, no daemon | BR-1, BR-12, ADR-018’s “no second runtime” thread | Anything that requires localhost:<port> |
| Cross-platform: aarch64+x86_64 macOS, aarch64+x86_64 Linux, x86_64 Windows | v0.4 release matrix | Anything that ships only on a subset of OSes |
| Liberal OSS license (MIT or Apache 2.0) | Synapse is MIT | Anything that ships proprietary or AGPL |
| Workspace ceiling 10k entities (federation chunks beyond) | v0.5 brief §6.3 | Anything optimised exclusively for ≥ 1M vectors at the cost of complexity |
Anything that satisfies all seven is a candidate. The list of candidates that pass the gate is short.
2. The candidate matrix
The matrix below grades each option against the Synapse constraint set, not against synthetic benchmarks. Each row ends with the yes/no on whether a v0.5 migration to that option would pay back.
| Option | What it is | Hard-no for Synapse? | Soft-no for Synapse? | Worth migrating from sqlite-vec? |
|---|---|---|---|---|
sqlite-vec 0.1.9 | Alex Garcia’s loadable SQLite extension; flat brute-force scan; ~1.5 MB native code; rusqlite integration documented. Author roadmap: v1.0 within a year, then maintenance mode. ANN index (“eventually”) still in design. | - | Flat scan is the v0.5 ceiling; documented at 10k entities | baseline |
vectorlite 0.2.x (beta) | hnswlib-based HNSW index packaged as a SQLite loadable extension. 2×–40× faster search, 10× faster inserts vs sqlite-vss according to the author’s bench (2025). Still beta as of 2026. | - | Beta status + smaller maintainer; HNSW tuning adds knobs we don’t need at 10k entities | No for v0.5 (too early); yes if we ever exceed ~100k vectors per workspace |
| LanceDB embedded | Apache Arrow-based vector lakehouse. Rust core. In-process. Has Tantivy-backed FTS, hybrid search, rerankers, S3 backing. ~50 MB extra binary. 1.5M IOPS bench 2026. Multi-modal (vectors + tables + text + images). | - | Would force re-implementing Workspace::tx, the pending queue, the audit trail, the federation registry, and all FTS5 callers because LanceDB has no SQL transactions in the SQLite sense; it is Arrow-native, columnar. Atomic write-after-write semantics are different. | No: migration cost is v1.0-shaped, not v0.5. Right answer if we were greenfield in 2026. We are not. |
| SurrealDB embedded | Multi-model DB (graph + document + relational + vector + KV + time-series + geospatial). Rust-native. Embedded + server. Custom query language (SurrealQL). | - | Same as LanceDB plus: replaces SQL entirely. Loses 100% of our existing SQL tests + migrations + the queries 21 commits in v0.4 just wrote. Conceptually attractive (graph + vector + KV in one engine maps onto Synapse’s data model nicely) but the migration is a complete reskinning. | No: even more costly than LanceDB. Reconsider only on a v2.0 reset. |
| DuckDB + VSS extension | Columnar OLAP database with a vector extension. Embedded. Multi-platform. | - | Wrong workload shape: DuckDB is analytical (read-heavy aggregations) not transactional (one row, one write). Synapse is transactional. DuckDB also breaks Workspace::tx for the same reasons LanceDB does. | No: DuckDB is the answer for a different product. |
usearch | Single-file HNSW index library by Unum. ~1 MB. C++/Rust/multi-language. No storage layer: just the index. | - | Would have to wire its own storage and we’d lose SQLite’s transaction binding | No as a standalone replacement; could complement sqlite-vec if we ever wanted HNSW without leaving SQLite, but vectorlite already does that and ships as a SQLite extension |
| Qdrant embedded mode | Real vector DB that has an embedded crate. Rust-native. HNSW. | - | Same daemon-shaped split as Ollama: heavy binary growth, separate API surface, ~80 MB | No: same reason we rejected Ollama-as-runner for embeddings |
sqlite-vector by sqlite.ai | Commercial-ish (sqliteai.com) vector extension; HNSW. | License unclear (BSL? Commercial?) | - | No until license clarity |
| Tantivy + custom vector | Lucene-style FTS engine in Rust. Quickwit underpins it. Not a vector store on its own. | - | We’d add Tantivy alongside SQLite + a separate vector layer. Three storage engines, three transaction surfaces, three failure modes | No: we’d be inventing LanceDB’s stack ourselves |
| Hand-rolled flat scan + SIMD cosine | Pure Rust, no dep. | - | Reinvents sqlite-vec for no upside; lacks the ANN index path we’d want at scale | No |
The matrix collapses to three real options: stay on sqlite-vec, upgrade to vectorlite (HNSW within the SQLite shell), or migrate to LanceDB (different shell entirely).
3. Cross-check vs the architectural promises Synapse already made
Synapse’s data model is eight entity types + tags + links + FTS +
pending + audit + provenance + federation cache, all atomic per
Workspace::tx. The matrix below tabulates how much code each
backend would force us to re-write, taking the v0.4 codebase as the
baseline (Cargo.toml at synapse 0.4.0, 121 lib tests, 10k+ LOC).
| Subsystem | LOC today | Stays on sqlite-vec | Moves to vectorlite | Moves to LanceDB |
|---|---|---|---|---|
Workspace::tx (atomic FS + SQLite transaction) | ~150 | unchanged | unchanged | rewrite: different transaction surface |
| FTS5 ranking + snippet | ~120 | unchanged | unchanged | replace with Tantivy: different ranker, snippet format, tests |
Audit trail (.synapse/audit.ndjson lives outside the DB but the pending queue and the payload_sha256 integrity check are SQLite-backed) | ~450 | unchanged | unchanged | rewrite the queries: Arrow columnar reads, no SQL |
| Pending queue | ~530 | unchanged | unchanged | rewrite |
Federation registry + manifest cache (separate SQLite DB at ~/.config/synapse/workspaces.db) | ~560 | unchanged | unchanged | migrate or keep on SQLite alongside: two DBs, two query languages |
Schema migrations (0001..0004) | ~200 (incl. SQL) | unchanged | unchanged | rewrite as Arrow-native migrations |
FTS5 MATCH … ORDER BY rank callers | ~80 in core::search, cli/at, mcp | unchanged | unchanged | rewrite all of them |
core::reindex (4 migration tables, 6 entity types) | ~310 | unchanged | unchanged | rewrite |
| Net delta | ~0 lines | ~30 lines (FFI to vectorlite or migration script) | ~2,400 lines rewritten + ~100 tests rewritten |
Migrating to LanceDB is a v1.0-shaped commitment in a v0.5 cycle. Migrating to vectorlite is a ~30-line swap (the loadable-extension boundary is the same as sqlite-vec). Staying on sqlite-vec costs zero.
4. Where each option really beats sqlite-vec
The honest read on each alternative, not biased by what we already have:
LanceDB
- Multi-modal (vectors + images + tables + Parquet-importable) by
design. We do not need this today. If Synapse ever ships a
syn entity import <csv>for 10M-row enterprise CRM dumps, LanceDB becomes the right answer. - Tantivy-backed FTS is more flexible than SQLite FTS5 (custom analyzers, faceting, BM25 score tuning). FTS5 is enough for our workload size; Tantivy would matter at corpora 100× ours.
- 1.5M IOPS on cloud-backed storage; we are local-first, the IOPS number is meaningless for us.
- Native hybrid search with
query_type="hybrid", but we are building RRF ourselves on top of three signals (FTS + vector + graph), so LanceDB’s hybrid doesn’t subsume our SYN-86 ticket.
vectorlite
- HNSW index → sub-millisecond search on millions of vectors. The one real performance win over sqlite-vec for large corpora.
- Same SQLite shell, same
load_extensionshape, same FFI integration pattern we’re already taking with sqlite-vec in SYN-81. - Beta status as of 2026: author is one maintainer, less mature than sqlite-vec’s ecosystem.
SurrealDB
- The data model fits Synapse better than SQL does: graph edges +
documents + KV + vectors are exactly what entities + links + tags
- embeddings need. If we were starting from scratch in 2026 with Synapse’s spec in hand, SurrealDB is the architectural option to consider seriously.
- But we are not greenfield. We have 121 tests pinning SQL behaviour.
5. The conditional logic that would force a re-evaluation
Three triggers would re-open this decision. Recording them so the next reader does not have to re-do the survey:
| Trigger | What to do |
|---|---|
A real user workspace exceeds ~100k entities and reports flat-scan latency on syn search | Migrate to vectorlite (HNSW). ~30 lines of FFI changes. Same SQL queries. Same FTS5. No business logic change. Pre-staged ticket: SYN-203 (file in v0.7 milestone when created). |
| Synapse decides to support multimodal capture (images, audio embeddings, large attachments) | Evaluate LanceDB seriously. It owns multimodal natively; bolting it onto SQLite is unhealthy. This would be a v2.0 conversation. |
| sqlite-vec project goes inactive | Switch to vectorlite (same shell) immediately. Synapse already had the same risk play out with tower-lsp → tower-lsp-server and managed; the rerun is documented in ADR-018. |
| Synapse opens an enterprise CRM / SaaS-integration import path with 1M+ rows | Migrate to LanceDB: same conversation as the multimodal trigger above, just for a different scale axis. |
6. Risk of staying on sqlite-vec: the parts the ADR didn’t fully
The ADR-008 §Consequences lists three risks. The exhaustive read:
| Risk | Severity now | Mitigation already in place |
|---|---|---|
| Flat scan O(N) becomes visible at ≥ 50k vectors per workspace | Low | Brief §6.3 caps the v0.5 workspace at 10k entities; federation chunks beyond |
| sqlite-vec author single-maintainer (Alex Garcia) goes inactive | Medium | Switch to vectorlite (same shell); C extension is ABI-stable so the source can be vendored under src/index/vendor/ if upstream disappears |
| ANN index promised “soon” never materialises | Low | Doesn’t block v0.5; if it never lands, vectorlite is the upgrade path |
| sqlite-vec v1.0 introduces breaking changes during the maintenance handoff | Medium | We pin a specific version + take FFI direct path (per ADR-008 production wiring decision), insulating us from crate-level API churn |
rusqlite ^0.31 vs our 0.39 collision | Low | Resolved in ADR-008 by FFI-against-C-extension path; no Rust crate dependency |
None of these justify a v0.5 migration away from sqlite-vec.
7. Recommendation
Confirm ADR-008 as written. No change to v0.5. The decision matrix says sqlite-vec is the right call for our workload size, codebase shape and constraint set. The alternatives are either wrong-workload (DuckDB), too-early (vectorlite beta), or greenfield-only (LanceDB, SurrealDB).
Two follow-ups that this report recommends filing:
| ID | What | When |
|---|---|---|
| SYN-203 (placeholder) | Document vectorlite migration path as the v0.7+ swap; vendor sqlite-vec C source under src/index/vendor/ so we are insulated from upstream churn | Open ticket now, no milestone: moves into v0.7 when that milestone exists |
| ADR amendment | Append to ADR-008 §Consequences: “If a workspace ever exceeds 50k indexed entities, switch to vectorlite via the same load_extension FFI path: no business-logic change required.” | Inline edit to ADR-008: small enough to do now |
8. References
- Releases · asg017/sqlite-vec: v0.1.9 stable, v1.0 roadmap statements.
- Introducing sqlite-vec v0.1.0: Alex Garcia’s blog: design goals + flat scan limitations.
- vectorlite: Fast SQL-powered HNSW SQLite extension: 2×–40× faster searches vs sqlite-vss (predecessor benchmark).
- LanceDB GitHub: Rust core, in-process, embedded.
- LanceDB vs SQLite: slashdot.org comparison (2026): feature parity table.
- LanceDB Documentation: Hybrid Search:
query_type="hybrid"design. - SurrealDB embedded mode docs: multi-model in one engine.
- DuckDB vs SQLite: Motherduck: analytical vs transactional workload framing.
- usearch crate: HNSW-only index, no storage layer.
- Embedded databases (3): LanceDB and the modular data stack, The Data Quarry: independent embedded-DB landscape read for 2026.
- ADR-003:
rusqlite bundled(the constraint that binds the storage decision to SQLite). - ADR-008: embedding backend + vector storage + NER (the decision this brief stress-tests).
- v0.5 brief:
2026-06-02-v0.5-semantic-layer-and-second-brain.md§2.2.