Hi everyone!
I’ve been working on MojoVec, an embedded vector search engine implemented from scratch in pure Mojo.
GitHub: GitHub - bewaffnete/MojoVec: Vector DB implementation in Mojo · GitHub .
What is implemented
-
HNSW with exact
Float32and quantized SQ8 storage -
IVF-Flat and IVF-PQ lower-level indexes
-
Squared L2, cosine, and inner-product distance metrics
-
Managed
add,upsert,update,delete, and batchedquery -
Typed metadata and Chroma-style
wherefilters -
Automatic sparse bitmap indexes for metadata fields
-
Native BM25 document search
-
Hybrid vector + BM25 search using reciprocal rank fusion
-
Atomic snapshots, memory-mapped loading, optional WAL recovery, and compaction
-
Native Mojo API and Python bindings
The public API is intentionally collection-oriented and familiar to users of tools such as Chroma, while the implementation underneath is written in Mojo.
Small Mojo example
from mojovec import Client, Metadata, Where
from std.collections import List
def main() raises:
var client = Client()
var collection = client.create_collection(
"articles",
dimension=128,
M=32,
ef_construction=96,
ef_search=96,
quantized=True,
metric="cosine",
)
var metadata = Metadata()
metadata.set("kind", "guide")
metadata.set("year", 2026)
metadata.set("published", True)
# Fill these with IDs and flattened Float32 embeddings.
var ids = List[Int]()
var embeddings = List[Float32]()
collection.add(ids, embeddings)
var results = collection.query(
embeddings,
where=Where.and_([
Where.eq("published", True),
Where.gte("year", 2024),
]),
n_results=10,
)
Metadata filters support typed equality, inequality, ordered comparisons, membership, and nested and, or, and not expressions. MojoVec automatically maintains the corresponding bitmap indexes; there is no separate index-management API.
Python API
The same native collection implementation is available from Python:
pip install mojovec
import mojovec
collection = mojovec.Collection(
dimension=3,
metric="cosine",
quantized=True,
)
collection.add(
ids=[1, 2, 3],
embeddings=[
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.8, 0.2, 0.0],
],
metadatas=[
{"kind": "guide", "year": 2024},
{"kind": "reference", "year": 2026},
{"kind": "guide", "year": 2027},
],
documents=[
"Mojo vector search guide",
"Python API reference",
"Hybrid search with RRF",
],
)
results = collection.query(
query_embeddings=[[1.0, 0.0, 0.0]],
n_results=2,
where={
"$and": [
{"kind": {"$in": ["guide", "reference"]}},
{"year": {"$gte": 2024}},
]
},
)
Current benchmark results
I have been testing MojoVec on SIFT1M with one million 128-dimensional base vectors.
Current Apple Silicon search-only results with M=32, efConstruction=200, efSearch=96, and k=10:
| Index | QPS | Recall@10 |
|---|---|---|
| MojoVec Flat HNSW | 23,783 | 99.160% |
| FAISS Flat HNSW | 17,330 | 99.201% |
| MojoVec SQ8 HNSW | 36,353 | 99.144% |
| FAISS SQ8 HNSW | 14,712 | 99.185% |
SQ8 results use exact reranking of 20 candidates.
These are my measurements rather than universal performance claims. The repository contains the benchmark methodology and commands, and I would especially appreciate independent reproductions on other Apple Silicon machines and x86-64 systems.
Why Mojo has been interesting here
This project exercises more than the distance kernel:
-
SIMD distance computation
-
aligned vector storage
-
graph traversal
-
multithreaded index construction and batched queries
-
quantization and exact reranking
-
binary persistence formats
-
memory mapping
-
Python interoperability
-
recovery and crash-safety mechanisms
The project is still young, and feedback is very welcome—especially around:
-
Mojo API ergonomics
-
SIMD and memory-layout improvements
-
benchmark methodology
-
behavior on different CPU architectures
-
filtered HNSW search
-
persistence and WAL design
-
real-world RAG or semantic-search workloads
Issues, benchmark results, code reviews, and contributions are all welcome.
GitHub: GitHub - bewaffnete/MojoVec: Vector DB implementation in Mojo · GitHub