Skip to main content

Fast, embeddable C++ vector database with Python bindings

Project description

RixDB

Fast, embeddable vector database for Python — written in C++.

⚠️ Pre-implementation. RixDB is in active design — no C++ source exists yet. The code samples and API below reflect the planned design, not a working package. Follow the repo or watch releases to be notified when the first alpha is available.

RixDB is intended to be a zero-dependency, SIMD-accelerated vector index with memory-mapped persistence and a clean Python API. It is designed to be embedded directly inside your application — no server, no daemon, no configuration overhead.

# Planned API — not yet functional
import rix
 
db = rix.Index.open_or_create(dim=768, metric="cosine", path="./index")
db.upsert(ids, vectors, metadata)
results = db.search(query_vector, top_k=8)

RixDB is a ground-up implementation of HNSW-based vector search, built to understand the internals rather than wrap an existing library. It prioritizes correctness, clean API design, and the specific feature set needed for local embedding retrieval — not raw benchmark numbers.


Why RixDB

Most local vector search options make you choose between simplicity and performance. ChromaDB is simple but slow on large corpora. FAISS is fast but has no metadata, no incremental updates, and a difficult API. hnswlib is close but general-purpose and lacks a metadata store.

RixDB is built for the specific case of embedding-based retrieval inside a single Python process:

  • Zero runtime dependencies. Will ship as a single compiled .so / .pyd. Nothing to install beyond pip install rix once released.
  • Fast cold load (design target). The index is planned to be memory-mapped so the OS page cache handles most I/O, with load time largely independent of index size.
  • SIMD-accelerated queries (planned). Support for AVX-512, AVX2, SSE4.2, and NEON is intended, with code paths selected automatically at runtime based on CPU features.
  • Incremental updates (planned). The index is intended to support inserts and deletes without full rebuilds, optimized for indices that change frequently.
  • Metadata-native (design goal). The design calls for every vector to carry structured metadata stored in a flat binary layout alongside the index, avoiding a separate lookup table.

Installation

Package name vs import name: The PyPI distribution name is rixdb (what you type in pip install). The Python module name is rix (what you type in import rix). This follows the same convention as other libraries — pip install Pillow / import PIL, pip install scikit-learn / import sklearn.

Planned install (Phase E — production release)

pip install rixdb

Pre-built wheels are planned for:

Platform Architecture
Linux x86_64, aarch64
macOS x86_64, arm64
Windows x86_64

To build from source (once C++ implementation exists), a C++17 compiler and CMake 3.21+ will be required.


Quick Start

Not yet functional. The following shows the planned API once Phase A is complete. The code samples reflect the final design, not the current state of the repository.

Create and populate an index

import rix
import numpy as np

# Open or create a persistent index
db = rix.Index.open_or_create(
    dim=768,
    metric="cosine",
    path="./my_index"
)

# Generate some example vectors (replace with real embeddings)
ids = ["doc_0", "doc_1", "doc_2"]
vectors = np.random.rand(3, 768).astype(np.float32)
metadata = [
    {"source": "readme.md", "section": "intro"},
    {"source": "api.md",    "section": "usage"},
    {"source": "guide.md",  "section": "install"},
]

db.upsert(ids, vectors, metadata)

Search

query = np.random.rand(768).astype(np.float32)
results = db.search(query, top_k=3)

for r in results:
    print(r.id, r.score, r.metadata)

Update and delete

# Upsert replaces existing IDs automatically
db.upsert(["doc_0"], new_vector, new_metadata)

# Delete by ID
db.delete(["doc_1"])

Use as a context manager

with rix.Index.open("./my_index") as db:
    results = db.search(query_vector, top_k=5)

API Overview

rix.Index

Method Description
Index.create(dim, metric, path, params) Create a new empty index
Index.open(path) Open an existing index
Index.open_or_create(dim, metric, path, params) Open if exists, create if not
upsert(ids, vectors, metadata) Insert or replace vectors by ID
search(vector, top_k, ef_search, filters) Approximate nearest neighbor search
search_batch(vectors, top_k, ef_search) Parallel batch search, one result list per query
delete(ids) Remove vectors by ID
get(ids) Fetch metadata without ANN search
contains(id) Check if an ID exists
list_ids(prefix) List all stored IDs
compact() Force compaction of deleted entries
stats() Index statistics and file sizes
close() Flush and close (called automatically)

rix.SearchResult

Field Type Description
id str External ID provided at insert time
score float Similarity score (higher = more similar)
metadata dict All metadata fields stored at insert time

Metrics

Value Distance Function Use Case
"cosine" Cosine similarity Text and code embeddings (default)
"l2" Euclidean distance Image embeddings, some ML models
"ip" Inner product Recommendation systems

Tuning

RixDB works well at default settings for most use cases. The key parameters are:

Parameter Default Effect
M 16 Connections per node. Higher = better recall, more memory
ef_construction 200 Build quality. Higher = better recall, slower build
ef_search 50 Query candidate pool. Higher = better recall, slower query

Pass custom parameters at creation time:

db = rix.Index.create(
    dim=768,
    metric="cosine",
    path="./index",
    params={"M": 32, "ef_construction": 400}
)

Built-in profiles

# High recall — best accuracy, higher memory
params = rix.profiles.high_recall

# Low memory — reduced RAM, slightly lower recall
params = rix.profiles.low_memory

# Fast build — quicker indexing, default query performance
params = rix.profiles.fast_build

Benchmarks

Note — RixDB is not yet implemented. The numbers below are conservative design targets, not measured results. RixDB is an initial, first-principles implementation — these targets reflect what a correct, well-optimized implementation of HNSW with AVX2 SIMD and mmap persistence should be able to achieve, not what has been verified. Benchmarks will be measured and published after Phase B is complete. Until then, treat all numbers here as aspirational.

Design targets on a mid-range developer laptop (Intel Core i7, AVX2, no GPU). Index dimension: 768. Metric: cosine. Default parameters (M=16, ef_search=50).

Corpus Size Query P95 (target) Build Time (target) Cold Load (target) Recall@10 (target)
10K vectors < 5ms < 30s < 100ms ≥ 0.95
100K vectors < 20ms < 5min < 100ms ≥ 0.95
500K vectors < 50ms < 30min < 100ms ≥ 0.95

Feature comparison with alternatives (competitor numbers are from their published benchmarks — RixDB column is targets only):

Library Query P95 Cold Load Incremental Updates Metadata
RixDB (target) < 20ms < 100ms
ChromaDB ~25ms ~400ms
hnswlib ~4ms ~180ms
FAISS (IVF) ~3ms ~200ms

RixDB's query latency target is intentionally conservative. hnswlib is written by the authors of the HNSW paper and is extensively optimized. Matching it on the first implementation attempt is not a realistic expectation. The value RixDB adds over hnswlib is incremental updates and a built-in metadata store — not raw query speed.


Architecture

RixDB is built on three core components:

HNSW index — Hierarchical Navigable Small World graph for O(log n) approximate nearest neighbor search. Parameters M, ef_construction, and ef_search control the recall/speed/memory tradeoff.

SIMD distance kernel — Runtime CPU detection selects the best available path: AVX-512, AVX2, SSE4.2, NEON, or scalar fallback. Cosine similarity reduces to a dot product after L2 normalization at insert time.

mmap persistence — The index and metadata live in memory-mapped binary files. The OS page cache manages physical memory. Cold load time is independent of index size.

Full architecture documentation is in docs/architecture.md.


Building From Source

Not yet possible. No C++ source exists yet. The following describes the planned build process for when Phase A implementation begins.

Requirements (planned): C++17 compiler (GCC 10+, Clang 12+, MSVC 2019+), CMake 3.21+, Python 3.11+.

git clone https://github.com/Pranav1173/RixDB
cd RixDB
pip install -e ".[dev]"

To run the C++ unit tests:

cmake -B build -DRIX_BUILD_TESTS=ON
cmake --build build
./build/rix_test

To run the Python tests:

pytest tests/python/

Contributing

Contributions are welcome. Please read CONTRIBUTING.md before opening a pull request.

For significant changes — new features, API changes, algorithm modifications — open an issue first to discuss the design. The architecture document is the reference for all design decisions.

Areas where contributions are especially welcome:

  • Additional SIMD kernels (AVX-512 path, improved NEON)
  • Scalar quantization (int8 vector support)
  • Windows ARM64 support
  • Language bindings beyond Python

License

Apache 2.0 — see LICENSE.


Status

RixDB is currently in pre-implementation planning. The architecture is fully documented and the repository is set up, but no C++ code has been written yet. Development begins at Phase A — a correct scalar HNSW implementation with Python bindings.

Planned release milestones:

Phase A  →  0.1.0-alpha   Correct scalar HNSW + Python bindings
Phase B  →  0.2.0-alpha   SIMD + mmap + verified benchmarks
Phase C  →  0.3.0-alpha   Incremental updates + compaction
Phase D  →  0.4.0-beta    Parallel batch insert + thread safety
Phase E  →  1.0.0         PyPI publication + pre-built wheels

Follow the repository or watch releases to be notified when the first alpha is available.

Current version: 0.1.0.dev0 (name reservation only)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rixdb-0.1.1.dev0.tar.gz (6.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rixdb-0.1.1.dev0-py3-none-any.whl (5.9 kB view details)

Uploaded Python 3

File details

Details for the file rixdb-0.1.1.dev0.tar.gz.

File metadata

  • Download URL: rixdb-0.1.1.dev0.tar.gz
  • Upload date:
  • Size: 6.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.3

File hashes

Hashes for rixdb-0.1.1.dev0.tar.gz
Algorithm Hash digest
SHA256 2907ff9d91ec2767a552166e2db9176035453027180d0f92ad83f6b80edbe21d
MD5 ecb9bd27a70f25cc168c3cc174c5bb0f
BLAKE2b-256 7312f2e002bba4ea2cd140aade7d039497c7e9b3ad2922a7de9892bdd374f903

See more details on using hashes here.

File details

Details for the file rixdb-0.1.1.dev0-py3-none-any.whl.

File metadata

  • Download URL: rixdb-0.1.1.dev0-py3-none-any.whl
  • Upload date:
  • Size: 5.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.3

File hashes

Hashes for rixdb-0.1.1.dev0-py3-none-any.whl
Algorithm Hash digest
SHA256 bdb071adf7527eedbd7e60ff2dafd05c699865e3b5fb84d3f13972adc2a1a807
MD5 71980dbd45f17bd687ccfe3130bba017
BLAKE2b-256 b395dd9723a76117d86a976df58ddb858844999eb240c64053c2727d32dc5e20

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page