Skip to content

research(nightly): fresh-diskann — streaming online index maintenance#426

Draft
ruvnet wants to merge 5 commits intomainfrom
research/nightly/2026-05-06-fresh-diskann
Draft

research(nightly): fresh-diskann — streaming online index maintenance#426
ruvnet wants to merge 5 commits intomainfrom
research/nightly/2026-05-06-fresh-diskann

Conversation

@ruvnet
Copy link
Copy Markdown
Owner

@ruvnet ruvnet commented May 6, 2026

Summary

  • Adds crates/ruvector-fresh-diskann — a new standalone Rust crate implementing FreshDiskANN (Singh et al., VLDB 2022, arXiv:2105.09613) for streaming online Vamana graph index maintenance without full rebuilds.
  • Adds docs/adr/ADR-183-fresh-diskann.md — architecture decision record documenting the design, alternatives considered, and consequences.
  • Adds docs/research/nightly/2026-05-06-fresh-diskann/README.md — full research document with SOTA survey, algorithm design, benchmark methodology, and improvement roadmap.

Note: gh CLI is not authenticated in this environment. Gist content is embedded below. To publish: gh gist create --public --desc "ruvector 2026: FreshDiskANN — Streaming Online Vamana Graph Index Maintenance in Rust" <gist-file.md>


Research: FreshDiskANN Streaming Index Maintenance

ADR: ADR-183 | Crate: ruvector-fresh-diskann


ruvector 2026: FreshDiskANN — High-Performance Streaming Vector Index in Rust

150-char SEO summary: ruvector FreshDiskANN enables live vector inserts into Vamana graph indices without full rebuilds — 3200 QPS, recall@10=0.751, 2ms per-vector consolidation in Rust.

Introduction

Every production vector database faces the same trap: graph-based ANN indices (HNSW, DiskANN, NSG) deliver outstanding recall and query throughput but require a full rebuild when new vectors arrive. On a 10,000-vector corpus at 128 dimensions, a static Vamana build takes 28.8 seconds on a 4-core Xeon. At 10M vectors that's hours.

ruvector-fresh-diskann implements the FreshDiskANN algorithm — a streaming maintenance layer that lets you insert, delete, and query simultaneously without rebuilding. New vectors land in an in-memory buffer (immediately searchable via brute-force), then are consolidated into the Vamana graph via per-vector beam-insert with α-robust pruning. No segment merging. No recall cliff. No rebuild.

Features

  • Streaming insertinsert(id, embedding) returns immediately; vector is searchable at once
  • Three consolidation policiesManual, Eager (per-insert), Lazy(T) (batch at threshold T)
  • Hybrid search — graph beam search ∪ buffer brute-force scan, merged by distance
  • Soft delete — tombstone-based; no graph surgery required
  • Self-contained — no Python, no ONNX runtime, pure Rust std
  • 8 passing tests, cargo test -p ruvector-fresh-diskann is green

Benefits

Benefit Detail
No rebuild latency Wire a new vector in ~2ms vs 28.8s full rebuild
Recall preserved Streaming recall@10 = 0.751 ≈ static 0.744 (within noise)
Throughput ~3,100–3,200 QPS at k=10 regardless of policy
Burst absorption Buffer absorbs insert spikes; consolidation runs on schedule
Delete support Tombstone filter; no graph invalidation

Benchmarks (Real Numbers — 4-core Intel Xeon @ 2.80 GHz)

Dataset: 10,000 vectors × 128 dimensions, f32, synthetic uniform
Config: R=32, L_build=64, L_search=64, α=1.2, k=10
Ground truth: brute-force k-NN over full corpus

Variant Recall@10 QPS Build (ms) Consol (ms)
A — Static (full batch) 0.744 3,178 28,819 0
B — Eager (per-insert) 0.751 3,213 25,062 2,017
C — Lazy T=100 0.751 3,133 24,932 2,749
D — Buffer-only (no graph) 0.751 3,235 25,163 2,869

Key result: streaming inserts preserve or improve recall vs static build (0.751 vs 0.744) while enabling live ingestion at ~2ms per-vector consolidation cost.

Comparisons vs Competitors

System Streaming Approach Recall guarantee
ruvector FreshDiskANN Vamana beam-insert + α-prune α-robust (same as build)
Qdrant HNSW in-place patch No α-robust bound
Weaviate Segment merge + HNSW rebuild Dips during merge
Milvus Growing segment + compaction Per-segment quality
LanceDB Lance LSM + per-fragment HNSW Fragment-level
FAISS ⚠️ add() without pruning Degrades without pruning
ruvector-diskann (pre-ADR-183) Full rebuild only N/A

Optimizations (Roadmap)

  1. Parallel consolidation via rayon (per-node Mutex + two-phase insert/repair)
  2. Generation-counter visited bitset (O(1) clear, eliminates per-search Vec<bool> alloc)
  3. Background consolidation thread with Arc<RwLock<ConsolidatedState>>
  4. WAL-backed buffer for crash recovery
  5. Periodic medoid recompute heuristic
  6. SSD spill for large buffers (memmap2)
  7. Vacuum pass to compact tombstoned edges

Get Started

# Clone
git clone https://github.com/ruvnet/ruvector
cd ruvector
git checkout research/nightly/2026-05-06-fresh-diskann

# Build
cargo build --release -p ruvector-fresh-diskann

# Test
cargo test -p ruvector-fresh-diskann

# Benchmark
cargo run --release -p ruvector-fresh-diskann --bin fresh-diskann-bench
use ruvector_fresh_diskann::{FreshDiskAnn, FreshConfig, ConsolidationPolicy};

let mut idx = FreshDiskAnn::new(FreshConfig {
    dim: 128,
    max_degree: 32,
    build_beam: 64,
    search_beam: 64,
    alpha: 1.2,
    policy: ConsolidationPolicy::Lazy(1000),
});

// Bulk load + build
for (id, vec) in base_corpus { idx.preload(id, vec)?; }
idx.build()?;

// Live streaming
idx.insert("new-doc".to_string(), embedding)?;

// Search (graph + buffer, merged)
let hits = idx.search(&query, 10)?;

References

  • FreshDiskANN: arXiv:2105.09613 (Singh et al., VLDB 2022)
  • DiskANN: arXiv:1908.10396 (Subramanya et al., NeurIPS 2019)
  • Research doc: docs/research/nightly/2026-05-06-fresh-diskann/README.md
  • ADR: docs/adr/ADR-183-fresh-diskann.md
  • Repo: https://github.com/ruvnet/ruvector

Test plan

  • cargo build --release -p ruvector-fresh-diskann — passes
  • cargo test -p ruvector-fresh-diskann — 8/8 tests pass
  • cargo run --release --bin fresh-diskann-bench — real numbers captured
  • Review recall@10 numbers against ruvector-diskann static baseline
  • Consider merging into workspace after parallel-consolidation roadmap item lands

https://claude.ai/code/session_01FuyD9huQGmZLdct1bUEm5q


Generated by Claude Code

claude added 5 commits May 6, 2026 07:20
…ine index maintenance

Implements FreshDiskANN (Singh et al., VLDB 2022, arXiv:2105.09613) as a new
standalone Rust crate providing streaming insert and soft-delete capabilities
for Vamana proximity graphs without requiring a full index rebuild.

Key features:
- In-memory insert buffer searchable immediately via brute-force scan
- Lazy consolidation: beam-insert each buffered vector via α-robust Vamana
  pruning + backlink repair (O(R·L·dim) per vector vs O(N·R·L·dim) rebuild)
- Three consolidation policies: Manual, Eager, Lazy(T)
- Tombstone-based soft deletes filtered at query time
- 8 passing tests; cargo build --release succeeds

Benchmark (4-core Xeon @ 2.80 GHz, 10k × 128-dim, k=10):
  Static baseline : recall@10=0.744, QPS=3178
  Eager streaming : recall@10=0.751, QPS=3213, consol=2017ms
  Lazy T=100      : recall@10=0.751, QPS=3133, consol=2749ms
  Buffer-only     : recall@10=0.751, QPS=3235

https://claude.ai/code/session_01FuyD9huQGmZLdct1bUEm5q
Records the decision to add ruvector-fresh-diskann crate for streaming
online index maintenance via lazy consolidation. Includes context (static
DiskANN rebuild cost), decision rationale, consequences, and alternatives
considered (Qdrant HNSW patching, LanceDB segment merging, FAISS add).

https://claude.ai/code/session_01FuyD9huQGmZLdct1bUEm5q
…ntenance

Research document covering:
- SOTA survey: FreshDiskANN vs Qdrant/Weaviate/Milvus/LanceDB/FAISS streaming approaches
- Proposed design with complexity table and architecture diagram
- Real benchmark numbers on 4-core Xeon @ 2.80 GHz (recall@10, QPS, consol latency)
- Blog-readable walkthrough of beam-insert algorithm
- Practical failure modes and mitigations
- Production crate layout proposal and 7-item improvement roadmap
- Full reference list (arXiv:2105.09613, 1908.10396, 2111.08566, SIGMOD 2024)

https://claude.ai/code/session_01FuyD9huQGmZLdct1bUEm5q
Adds rand, thiserror and transitive dependencies (rand_chacha, getrandom,
rand_core, zerocopy, ppv-lite86) required by the new crate.

https://claude.ai/code/session_01FuyD9huQGmZLdct1bUEm5q
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants