edgevec 0.4.0

High-performance embedded vector database for Browser, Node, and Edge
Documentation

πŸš€ EdgeVec

CI Performance Crates.io License

High-performance vector search for Browser, Node, and Edge

βœ… STATUS: Alpha Release Ready β€” All performance targets exceeded.


What's New in v0.4.0

Documentation & Quality Sprint

  • docs/TUTORIAL.md β€” Complete getting started guide
  • docs/PERFORMANCE_TUNING.md β€” HNSW parameter optimization
  • docs/TROUBLESHOOTING.md β€” Top 10 errors and solutions
  • docs/INTEGRATION_GUIDE.md β€” Third-party embedding integrations
  • docs/MIGRATION.md β€” Migration from hnswlib, FAISS, Pinecone

Benchmark Dashboard

  • Interactive visualization at /wasm/examples/benchmark-dashboard.html
  • EdgeVec vs hnswlib-node vs voy comparison
  • Real-time performance charts with Chart.js

Quality Infrastructure

  • Chaos Testing β€” 15 edge case tests (empty index, max dimensions, etc.)
  • Load Testing β€” 100k vector stress tests, sustained search load
  • P99 Latency Tracking β€” P50/P99/P999 percentile benchmarks
  • CI Regression Detection β€” 10% threshold enforcement

Previous (v0.3.0)

  • Soft delete API with O(1) tombstone-based deletion
  • Compaction API for reclaiming space
  • Full WASM bindings for soft delete operations
  • Persistence format v0.3 with automatic migration

What is EdgeVec?

EdgeVec is an embedded vector database built in Rust with first-class WASM support. It's designed to run anywhere: browsers, Node.js, mobile apps, and edge devices.

Key Features

  • Sub-millisecond search β€” 0.23ms at 100k vectors (768d, quantized)
  • HNSW Indexing β€” O(log n) approximate nearest neighbor search
  • Scalar Quantization (SQ8) β€” 3.6x memory compression
  • WASM-First β€” Native browser support via WebAssembly
  • Persistent Storage β€” IndexedDB in browser, file system elsewhere
  • Minimal Dependencies β€” No C compiler required, WASM-ready
  • Tiny Bundle β€” 227 KB gzipped (55% under 500KB target)

Quick Start

Installation

npm install edgevec

For Rust users: To achieve optimal performance, ensure your .cargo/config.toml includes:

[build]
rustflags = ["-C", "target-cpu=native"]

Without this configuration, performance will be 60-78% slower due to missing SIMD optimizations.

Browser/Node.js Usage

import init, { EdgeVec, EdgeVecConfig } from 'edgevec';

async function main() {
    // 1. Initialize WASM (required once)
    await init();

    // 2. Create Config and Index
    const config = new EdgeVecConfig(128);  // 128 dimensions
    config.metric = 'cosine';  // Optional: 'l2', 'cosine', or 'dot'
    const index = new EdgeVec(config);

    // 3. Insert Vectors
    const vector = new Float32Array(128).fill(0.1);
    const id = index.insert(vector);
    console.log(`Inserted vector with ID: ${id}`);

    // 4. Search
    const query = new Float32Array(128).fill(0.1);
    const results = index.search(query, 10);
    console.log("Results:", results);
    // Results: [{ id: 0, score: 0.0 }, ...]

    // 5. Save to IndexedDB (browser) or file system
    await index.save("my-vector-db");
}

main().catch(console.error);

Load Existing Index

import init, { EdgeVec } from 'edgevec';

await init();
const index = await EdgeVec.load("my-vector-db");
const results = index.search(queryVector, 10);

Rust Usage

use edgevec::{HnswConfig, HnswIndex, VectorStorage};
use edgevec::persistence::{write_snapshot, MemoryBackend};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Create Config & Storage
    let config = HnswConfig::new(128);
    let mut storage = VectorStorage::new(&config, None);

    // 2. Create Index
    let mut index = HnswIndex::new(config, &storage)?;

    // 3. Insert Vectors
    let vec1 = vec![1.0; 128];
    let _id1 = index.insert(&vec1, &mut storage)?;

    // 4. Search
    let query = vec![1.0; 128];
    let results = index.search(&query, 10, &storage)?;
    println!("Found {} results", results.len());

    // 5. Save Snapshot
    let mut backend = MemoryBackend::new();
    write_snapshot(&index, &storage, &mut backend)?;

    Ok(())
}

Batch Insert (Rust)

For inserting many vectors efficiently, use the batch insert API:

use edgevec::{HnswConfig, HnswIndex, VectorStorage};
use edgevec::batch::BatchInsertable;
use edgevec::error::BatchError;

fn main() -> Result<(), BatchError> {
    let config = HnswConfig::new(128);
    let mut storage = VectorStorage::new(&config, None);
    let mut index = HnswIndex::new(config, &storage).unwrap();

    // Prepare vectors as (id, data) tuples
    let vectors: Vec<(u64, Vec<f32>)> = (1..=1000)
        .map(|i| (i as u64, vec![i as f32; 128]))
        .collect();

    // Batch insert with progress tracking
    let ids = index.batch_insert(vectors, &mut storage, Some(|inserted, total| {
        println!("Progress: {}/{}", inserted, total);
    }))?;

    println!("Inserted {} vectors", ids.len());
    Ok(())
}

Features: Progress tracking, best-effort semantics, and unified error handling.

Soft Delete (Rust)

Delete vectors without rebuilding the index (v0.3.0+):

use edgevec::{HnswConfig, HnswIndex, VectorStorage};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = HnswConfig::new(128);
    let mut storage = VectorStorage::new(&config, None);
    let mut index = HnswIndex::new(config, &storage)?;

    // Insert a vector
    let vector = vec![1.0; 128];
    let id = index.insert(&vector, &mut storage)?;

    // Soft delete (O(1) operation)
    let was_deleted = index.soft_delete(id)?;
    println!("Deleted: {}", was_deleted);

    // Check deletion status
    println!("Is deleted: {}", index.is_deleted(id)?);

    // Get statistics
    println!("Live: {}, Deleted: {}", index.live_count(), index.deleted_count());
    println!("Tombstone ratio: {:.1}%", index.tombstone_ratio() * 100.0);

    // Compact when tombstones accumulate (rebuilds index)
    if index.needs_compaction() {
        let (new_index, new_storage, result) = index.compact(&mut storage)?;
        println!("Removed {} tombstones", result.tombstones_removed);
        // Use new_index and new_storage for future operations
    }

    Ok(())
}

Soft Delete (JavaScript)

import init, { EdgeVec, EdgeVecConfig } from 'edgevec';

await init();
const config = new EdgeVecConfig(128);
const index = new EdgeVec(config);

// Insert vectors
const vector = new Float32Array(128).fill(0.5);
const id = index.insert(vector);

// Soft delete
const wasDeleted = index.softDelete(id);
console.log('Deleted:', wasDeleted);

// Statistics
console.log('Live:', index.liveCount());
console.log('Deleted:', index.deletedCount());
console.log('Tombstone ratio:', index.tombstoneRatio());

// Compact when needed
if (index.needsCompaction()) {
    const result = index.compact();
    console.log(`Removed ${result.tombstones_removed} tombstones`);
}
Operation Time Complexity Notes
soft_delete() O(1) Set tombstone byte
is_deleted() O(1) Read tombstone byte
search() O(log n) Automatically excludes tombstones
compact() O(n log n) Full index rebuild

Interactive Examples

Try EdgeVec directly in your browser with our NVIDIA-grade cyberpunk demo suite:

Demo Gallery

Running Locally

# Clone the repository
git clone https://github.com/matte1782/edgevec.git
cd edgevec

# IMPORTANT: Start server from project root!
python -m http.server 8080

# Open in browser (include full path)
# http://localhost:8080/wasm/examples/index.html

⚠️ Note: Do NOT start server from wasm/examples/ β€” WASM module requires /pkg/ access from root.


Development Status

EdgeVec follows a military-grade development protocol. No code is written without an approved plan.

βœ… Alpha Release Ready (v0.1.0)

All Performance Targets Exceeded:

  • βœ… Search Mean: 0.23ms (4.3x under 1ms target)
  • βœ… Search P99 (estimated): <600Β΅s (based on Mean + 2Οƒ)
  • βœ… Memory: 832 MB for 1M vectors (17% under 1GB target)
  • βœ… Bundle Size: 227 KB (55% under 500KB target)

What Works Now:

  • βœ… HNSW Indexing β€” Sub-millisecond search at 100k scale
  • βœ… Scalar Quantization (SQ8) β€” 3.6x memory reduction
  • βœ… SIMD Optimization β€” AVX2/FMA for 60-78% speedup
  • βœ… Crash Recovery (WAL) β€” Log-based replay
  • βœ… Atomic Snapshots β€” Safe background saving
  • βœ… Browser Integration β€” WASM Bindings + IndexedDB
  • βœ… npm Package β€” edgevec@0.4.0 published

Development Progress:

  • Phase 0: Environment Setup β€” βœ… COMPLETE
  • Phase 1: Architecture β€” βœ… COMPLETE
  • Phase 2: Planning β€” βœ… COMPLETE
  • Phase 3: Implementation β€” βœ… COMPLETE
  • Phase 4: WASM Integration β€” βœ… COMPLETE
  • Phase 5: Alpha Release β€” βœ… READY

Future Roadmap (v0.5.0+)

  1. ARM/NEON Optimization β€” Cross-platform SIMD verification
  2. Mobile Support β€” iOS Safari and Android Chrome formalized
  3. CLI Tools β€” Optional developer command-line interface
  4. Enhanced Metadata Storage β€” Native metadata support

Path to v1.0

EdgeVec will reach v1.0 after:

  • Production usage feedback from v0.4.0/v0.5.0
  • Security audit
  • API stability guarantee commitment

πŸ“Š Performance (Alpha Release)

Search Latency (768-dimensional vectors, k=10)

Scale Float32 Quantized (SQ8) Target Status
10k vectors 203 Β΅s 88 Β΅s <1 ms βœ… 11x under
50k vectors 480 Β΅s 167 Β΅s <1 ms βœ… 6x under
100k vectors 572 Β΅s 329 Β΅s <1 ms βœ… 3x under

Note: Mean latencies from Criterion benchmarks (10 samples). Max observed: 622Β΅s (100k Float32). Outliers: 0-20% (mostly high mild/severe). P99 estimates are all <650Β΅s. See docs/benchmarks/ for full analysis.

Memory Efficiency (768-dimensional vectors)

Mode Memory per Vector 1M Vectors Compression
Float32 3,176 bytes 3.03 GB Baseline
Quantized (SQ8) 872 bytes 832 MB 3.6x smaller

Memory per vector includes: vector storage + HNSW graph overhead (node metadata + neighbor pool). Measured using index.memory_usage() + storage.memory_usage() after building 100k index.

Bundle Size

Package Size (Gzipped) Target Status
edgevec@0.4.0 227 KB <500 KB βœ… 55% under

Competitive Comparison (10k vectors, 128 dimensions)

Library Search P50 Insert P50 Type Notes
EdgeVec 0.20ms 0.83ms WASM Fastest WASM solution
hnswlib-node 0.05ms 1.56ms Native C++ Requires compilation
voy 4.78ms 0.03ms WASM KD-tree, batch-only

EdgeVec is 24x faster than voy for search while both are pure WASM. Native bindings (hnswlib-node) are faster but require C++ compilation and don't work in browsers.

Full competitive analysis β†’

Key Advantages

  • βœ… Sub-millisecond search at 100k scale
  • βœ… Fastest pure-WASM solution β€” 24x faster than voy
  • βœ… Zero network latency β€” runs 100% locally (browser, Node, edge)
  • βœ… Privacy-preserving β€” no data leaves the device
  • βœ… Tiny bundle β€” 227 KB gzipped
  • βœ… No compilation required β€” unlike native bindings

Test Environment

  • Hardware: AMD Ryzen 7 5700U, 16GB RAM
  • OS: Windows 11
  • Rust: 1.94.0-nightly (2025-12-05)
  • Criterion: 0.5.x
  • Compiler flags: -C target-cpu=native (AVX2 SIMD enabled)

Full benchmarks β†’


Development Protocol

The Agents

Agent Role
META_ARCHITECT System design, data layouts
PLANNER Roadmaps, weekly task plans
RUST_ENGINEER Core Rust implementation
WASM_SPECIALIST WASM bindings, browser integration
BENCHMARK_SCIENTIST Performance testing
HOSTILE_REVIEWER Quality gate (has veto power)
DOCWRITER Documentation, README

Development Environment

Local CI Simulation

Before pushing changes, run the local CI simulation to catch issues:

# Run full CI check with timing validation
cargo xtask ci-check

# Run pre-release validation (CI + docs + publish dry-run)
cargo xtask pre-release

The ci-check command:

  • Sets CI environment variables (RUSTFLAGS, PROPTEST_CASES, NUM_VECTORS)
  • Runs formatting, clippy, tests, and WASM checks
  • Validates each step completes within CI timeout limits

Timing Budgets (xtask / CI timeout):

Step Local Limit CI Timeout Typical
Formatting 30s 5min <1s
Clippy 180s 10min ~20s
Tests 600s 30min ~50s
WASM Check 120s 10min <1s

If a step exceeds its local limit, the build fails to catch performance regressions before CI.

Environment Variables

Variable Local Default CI Value Purpose
RUSTFLAGS (native) -C target-cpu=x86-64-v2 Prevent SIGILL on CI runners
PROPTEST_CASES 256 32 Reduce proptest runtime
NUM_VECTORS 10000 1000 Reduce integration test runtime

Building

# Standard build
cargo build --release

# WASM build
wasm-pack build --release

# Run tests
cargo test --all

# Run benchmarks
cargo bench

Release Process

See CONTRIBUTING.md for the full release process, including:


Origins

EdgeVec builds upon lessons learned from binary_semantic_cache, a high-performance semantic caching library. Specifically:

Salvaged (MIT Licensed):

  • Hamming distance implementation (~10 lines)
  • Binary quantization math (~100 lines)

Built Fresh:

  • HNSW graph indexing
  • WASM-native architecture
  • IndexedDB persistence
  • Everything else

Acknowledgments

  • Thanks to the Reddit community for identifying a potential alignment issue in the persistence layer, which led to improved safety via bytemuck in v0.2.1.
  • Thanks to the Hacker News community for feedback on competitive positioning and benchmarking.

License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.


Built with πŸ¦€ Rust + πŸ•ΈοΈ WebAssembly

Correctness by Construction