Every significant, hard-to-reverse decision is captured here as a short, numbered record so future readers understand why the system is shaped the way it is.
Each ADR is NNNN-kebab-title.md with:
- Status — Proposed · Accepted · Superseded by ADR-XXXX · Deprecated
- Date and Deciders
- Context — the forces and constraints in play
- Decision — what we will do
- Consequences — the trade-offs we accept, good and bad
- Alternatives considered — what we rejected and why
ADRs are immutable once Accepted; we supersede rather than edit. Numbers are stable and never reused.
| # | Title | Status | Phase |
|---|---|---|---|
| 0001 | Language and workspace layout | Accepted | 0 |
| 0002 | Async runtime — Tokio | Accepted | 0 |
| 0003 | Serialization formats | Accepted | 0 |
| 0004 | On-disk format | Accepted | 0 |
| 0005 | Durability & crash recovery | Accepted | 0 |
| 0006 | Concurrency model | Accepted | 0 |
| 0007 | Index roadmap (HNSW → Vamana/IVF) | Accepted | 0 |
| 0008 | Quantization strategy | Accepted | 0 |
| 0009 | SIMD distance kernels | Accepted | 0 |
| 0010 | Crypto: envelope encryption & AEAD | Accepted | 0 |
| 0011 | AuthN/Z & tenant isolation | Accepted | 0 |
| 0012 | Client-side encryption & trust boundary | Accepted | 0 |
| 0013 | Configuration & secure defaults | Accepted | 0 |
| 0014 | Observability | Accepted | 0 |
| 0015 | CI policy — manual-only + local verify gate | Accepted | 0 |
| 0016 | License — AGPL-3.0 | Accepted | 0 |
| 0017 | Error handling | Accepted | 0 |
| 0018 | SDK & integration strategy | Accepted | 0 |
| 0019 | Disk-resident index format (DiskANN on encrypted pages) | Accepted | 2 |
| 0020 | Row-addressed segment storage (.vec/.pay/.dir, mmap) |
Accepted | 2 |
| 0021 | Tombstones (roaring .del) and compaction |
Accepted | 2 |
| 0022 | Secondary indexes (.sec, order-preserving keys) |
Accepted | 2 |
| 0023 | Incremental in-place index updates (SpFresh / LIRE) | Accepted | 4 |
| 0024 | Migration importers (Qdrant / Chroma / pgvector) | Accepted | 4 |
| 0025 | Durable on-disk incremental index (IVF) | Accepted | 4 |
| 0026 | HNSW incremental delete (soft-delete) | Accepted | 4 |
| 0027 | Live migration connectors (Qdrant over HTTP) | Accepted | 4 |
| 0028 | Multi-vector documents & late interaction (ColBERT / MaxSim) | Accepted | 4 |
| 0029 | Live Chroma & Postgres migration connectors | Accepted | 4 |
| 0030 | Leader-follower replication (async read replicas) | Accepted | 4 |
| 0031 | Experimental property-preserving vector encryption (DCPE) | Accepted | 4 |
| 0032 | Semantically secure client-side vector encryption (opaque vectors) | Accepted | 4 |
| 0033 | Graph-index incremental updates (FreshDiskANN StreamingMerge) | Accepted | 4 |
| 0034 | Multi-vector follow-ups (incremental maintenance, native rows, ColBERTv2/PLAID) | Accepted | 4 |
| 0035 | Documentation site (mdBook), DCPE hardening (shuffle + normalisation), native TS cipher | Accepted | 4 |
| 0036 | Retro cockpit design system (Bronze Quiver theme, logo, decoration vocabulary) | Accepted | 4 |
| 0037 | Scientific multi-DB benchmark suite | Accepted | 5 |
| 0038 | Batch WAL sync for upsert (build-time bottleneck fix) | Accepted | 5 |
| 0039 | One-command install and self-update (quiver update) | Proposed | 5 |
| 0040 | Query cost limits (caps on k, ef_search, dimension, payload, batch) | Accepted | 5 |
| 0041 | Deep, large-data benchmark dimensions (SIFT1M, concurrency, Pareto, quantization curve) | Accepted | 5 |
| 0042 | RAG/agentic ergonomics (async SDK, Haystack, MCP introspection) + usage docs | Proposed | 5 |
| 0043 | Hybrid (dense + sparse) search with RRF fusion | Proposed | 5 |
| 0044 | Automated, tag-triggered multi-platform release assets (Windows job added) | Accepted | 5 |
| 0045 | Hybrid everywhere + fast ingest (sparse inverted index, gRPC/MCP/TS parity, bulk upsert) | Accepted | 5 |
| 0046 | BM25 / full-text over the sparse path (tokenizer + BM25 scoring, text/query_text) | Accepted | 5 |
| 0047 | Server-side embedding & reranking hooks (provider-agnostic, opt-in per collection) | Accepted | 5 |
| 0048 | Snowball (Porter2) stemmer for BM25 tokenization | Accepted | 5 |
| 0049 | Per-key rate limiting (token bucket, RateLimit headers, 429) | Accepted | 5 |
| 0050 | Online snapshot & restore (consistent whole-dir copy, REST + MCP) | Accepted | 5 |
| 0051 | Distributed / sharded mode (hash sharding, scatter-gather, per-shard Raft) — design only | Proposed | 5 |
| 0052 | GPU-accelerated build & search (behind the index trait, feature-gated) — design only | Proposed | 5 |
| 0053 | Lock-free MVCC reads (versioned snapshots, epoch reclamation) — high-level design; implementation in ADR-0064 | Accepted | 5 |
| 0054 | Prometheus /metrics (real counters/histograms) + request tracing spans + Grafana dashboard | Accepted | 5 |
| 0055 | v0.20.0 multi-DB benchmark re-run with the bulk-ingest build path (honest time-until-queryable) | Accepted | 5 |
| 0056 | Packaging & distribution — publish pipeline (crates.io/PyPI/npm), Helm chart, CHANGELOG | Accepted | 5 |
| 0057 | Concurrent reads behind a reader–writer lock + &self snapshot reads (staged path to lock-free arc-swap) | Accepted | 4 |
| 0058 | MCP upsert_text/search_text tools + extract the embedding/rerank seam into the shared quiver-providers crate | Accepted | 4 |
| 0059 | OpenTelemetry traces exporter — opt-in otlp cargo feature + runtime endpoint gate (OTLP/gRPC, reuses tonic) | Accepted | 4 |
| 0060 | Interactive TUI cockpit — query runner, point inspector, recent searches, help overlay, theme toggle; pure table-tested key handler | Accepted | 4 |
| 0061 | v0.22.0 benchmark dimensions — recall@{1,10,100}, saturated-concurrency QPS (qdrant thread-local fix), quantization memory wedge, filtered-selectivity sweep | Accepted | 4 |
| 0062 | Move the index rebuild off the exclusive lock — measured the rebuild stall (8–77 s, scales with size), captures the lock-free win with Arc+RwLock, no unsafe/loom; refines ADR-0057 ph2 / ADR-0053 | Accepted | 4 |
| 0063 | Durable on-disk DiskVamana index — load the mmap base + WAL-tail replay on open instead of an O(N) full-RAM rebuild; atomic-rename base + tiny checkpoint blob, rebuild fallback keeps the kill -9 gate | Accepted | 4 |
| 0064 | Lock-free MVCC reads — implementation design: per-collection arc-swap snapshot + small copy-on-write overlay (resolves the in-place index-mutation tension ADR-0053 left open); staged, default-off QUIVER_MVCC_READS | Accepted | 4 |
| 0065 | Cluster mode — implementation design: takes ADR-0051 from design-only to built; opt-in, dynamic/elastic scaling first-class (HRW hashing + a refreshable versioned shard map → online rebalancing of only ~1/N keys, no downtime); sharding + scatter-gather first, online membership + a coordinator next, per-shard consensus via an audited Raft crate (not hand-rolled), autoscaling hooks last; single-node stays the zero-overhead default | Accepted | 5 |
| 0067 | Per-shard Raft for write HA (ADR-0065 increment 4) — adopt openraft (settled by a cargo-deny review: openraft's tree is clean, raft-rs fails on a protobuf 2.28.0 advisory + is unmaintained); one Raft group per shard with the WAL as the replicated state machine and the read replicas as voters, leader-aware routing + a "not the leader" redirect, snapshot-based log compaction (ADR-0050); acked only after quorum commit so failover loses no acked write and cannot split-brain; opt-in per shard, single-node untouched; multi-quarter, staged 4a–4d, pause-on-trade-off | Accepted | 5 |
| 0066 | Dynamic cluster membership, online rebalancing & the coordinator (ADR-0065 increment 3) — stable shard ids (immutable HRW key, gaps tolerated), a thin off-the-data-path coordinator owning a monotonically versioned shard map that routers refresh into their ArcSwap (no restart), and online slice migration (donor-serves-until-caught-up via the ADR-0030 stream → single version flip → grace drop) made self-correcting by a shard-side "not my range" redirect; no acknowledged write lost, moved slice queryable throughout; staged 3a ids / 3b coordinator+refresh / 3c migration | Accepted | 5 |
| 0069 | Automated OWASP ZAP DAST gate that blocks a release — a reusable dast workflow boots a production-configured live server and runs the ZAP baseline (passive) + API scan (active, over the committed OpenAPI spec, authenticated); a FAIL-level alert (.zap/rules.tsv promotes the injection/disclosure rule classes to FAIL, IGNOREs reviewed benign findings) fails the job, and release needs it → no release until fixed. Also runs on main/develop pushes for early signal; PRs skip it (kept fast by the just verify gate, ADR-0015) | Accepted | 5 |
| 0068 | Streaming, memory-bounded, per-checkpoint-bounded segment compaction — a BlockWriter streams the .vec/.pay columns page-by-page (byte-identical to write_blocks) so compact_collection holds one row at a time, not the whole live set (disk-resident collections no longer pull the dataset into RAM); auto_compact compacts at most one collection per checkpoint so compaction stays off the checkpoint's critical path; old segments stay valid until the atomic manifest swap (crash contract preserved, tested). Fully off-lock background compaction (the ADR-0062 plan→build→commit-or-abort shape) is specified and deferred | Accepted | 4 |
| 0070 | Streaming, memory-bounded index build — the batch IVF+PQ build no longer materialises the whole n·dim corpus in RAM (~51 GiB at 100M×128, the last single-box-100M ceiling). Ivf::build_streaming does two bounded passes (reservoir-sample train, stream-encode) over a re-iterable vector source, byte-identical to Ivf::build within the training sample; peak build memory drops to O(sample + nlist·dim + n·m_bytes). Shipped incrementally: A = the primitive (v0.32.0), B = the live wiring (ADR-0071), C = the on-disk primary index + 100M ref-HW run (sequenced). No on-disk format change; the crash gate is untouched by construction | Accepted | 4 |
| 0071 | Lock-free vector source for the streaming rebuild (ADR-0070 Increment B) — Store::capture_vector_source reopens the referenced segments' immutable .vec mmaps as owned, independent handles (not shared Arcs, not borrowed slices) so the source is Send across the off-lock spawn_blocking boundary and immune to a concurrent checkpoint's in-place segment mutation; threaded through RebuildScan and both rebuild entry points so the live IVF rebuild routes through build_streaming without ever materialising flat. Payload-only scan rebuilds the sparse index; vectors read once, off-lock. Reference-HW RSS validation deferred to the dedicated box, no number claimed | Accepted | 4 |
Phase-0 ADRs (0001–0018) are Accepted; Phase-2 decisions span 0019–0022; Phase-4 decisions begin at 0023. New decisions take the next free number; superseded ADRs are marked as such — never deleted or renumbered.