HelixDB: one database for graphs, vectors, and everything your RAG pipeline touches

HelixDB: one database for graphs, vectors, and everything your RAG pipeline touches

HelixDB is a graph-vector database built entirely in Rust that stores nodes, edges, and high-dimensional vectors in a single LMDB-backed engine, and exposes them through compiled, type-safe HTTP endpoints you write in its own query language.

Why I starred it

The standard RAG stack in 2025 is a mess of plumbing: Postgres for relational data, Pinecone or Weaviate for vectors, maybe Neo4j for graph relationships, plus whatever glue code ties them together. HelixDB's argument is that all three live naturally in one place — a vector is a node in the graph, relationships encode context, and querying across them shouldn't require three separate round trips.

What caught me wasn't the pitch but the implementation choice: rather than a runtime query interpreter, HelixQL compiles down to registered HTTP handlers at deploy time. Your .hx schema and query files get parsed, type-checked, and turned into routes before any request arrives. That's a meaningful architectural bet.

How it works

The codebase is a Cargo workspace with five crates: helix-db (storage + compiler + gateway), helix-cli, helix-container, helix-macros, and hql-tests. The interesting work is in helix-db/src.

The query language is defined in helix-db/src/grammar.pest — a PEG grammar parsed by pest. The grammar covers schema definitions (N::, E::, V::), typed traversals, for-loops, migrations, and built-in macro annotations. The parser in helix-db/src/helixc/parser/ splits into a dozen focused files (traversal_parse_methods.rs, creation_step_parse_methods.rs, etc.) and produces an AST that feeds a code generator emitting Rust handler functions. Those handlers are registered with the axum router before the server starts.

Vector storage lives in helix-db/src/helix_engine/vector_core/vector_core.rs. The HNSW index is implemented from scratch — not a wrapper around faiss or hnswlib. The config in HNSWConfig::new() clamps m between 5 and 48, ef_construct between 40 and 512, and defaults ef to 768. Each vector gets a compound key [prefix | id_bytes | level_bytes] in LMDB, and HNSW edges are stored as a separate database keyed by [source_id | level | sink_id]. The entry-point node is persisted under a literal b"entry_point" key. Worth noting: they use bumpalo arena allocation throughout the search path to avoid per-query heap churn — the search signature carries a &'arena bumpalo::Bump that scopes all intermediate allocations.

Keyword search is a full BM25 implementation in helix-db/src/helix_engine/bm25/bm25.rs, backed by five separate LMDB databases: inverted index (term → posting list), reverse index (doc_id → terms), doc lengths, term frequencies, and metadata. The metadata tracks total_docs, avgdl, k1, and b as a serialized struct under a single b"metadata" key, updated on every insert and delete.

Reranking sits in helix-db/src/helix_engine/reranker/ with separate implementations for RRF (reciprocal rank fusion) and MMR (maximal marginal relevance). These show up as ::rerank_rrf and ::rerank_mmr steps in HelixQL traversals, meaning you can compose hybrid retrieval — HNSW + BM25, reranked — inside a single query without application-layer orchestration.

The gateway and worker model in helix-db/src/helix_gateway/ is deliberately shaped around LMDB's reader/writer model: WorkerPool creates N reader threads pinned to CPU cores via core_affinity and a single dedicated writer thread. Reads go through a bounded flume channel (bounded(1000)), writes through a separate channel to the single writer. The read workers use a select! pattern alternating between two receivers for fairness. Workers per core defaults to 8 and can be tuned with HELIX_CORES_OVERRIDE.

MCP support is a first-class citizen in helix-db/src/helix_gateway/mcp/. Agents can call graph traversals directly through the MCP tool protocol without hand-writing queries.

// From vector_core.rs — how HNSW vector keys are built
#[inline(always)]
pub fn vector_key(id: u128, level: usize) -> Vec<u8> {
    [VECTOR_PREFIX, &id.to_be_bytes(), &level.to_be_bytes()].concat()
}

// Level assignment during insert — probabilistic, per HNSW spec
fn get_new_level(&self) -> usize {
    let mut rng = rand::rng();
    let r: f64 = rng.random::<f64>();
    (-r.ln() * self.config.m_l).floor() as usize
}

The allocator choice is mimalloc, declared in Cargo.toml — a reasonable pick for a server with many short-lived allocations.

Using it

# Install CLI
curl -sSL "https://install.helix-db.com" | bash

# Bootstrap a project
mkdir my-app && cd my-app
helix init

A .hx file defining a user node with an indexed name field:

N::User {
    INDEX name: String,
    age: U32
}

QUERY getUser(user_name: String) =>
    user <- N<User>({name: user_name})
    RETURN user
helix check   # type-checks queries before deploying
helix push dev

Each QUERY becomes a POST endpoint. The TypeScript SDK calls them by name:

import HelixDB from "helix-ts";
const client = new HelixDB(); // default port 6969

const user = await client.query("getUser", { user_name: "Alice" });

Rough edges

The last commits in the public repo are from March 2026, mostly focused on an enterprise CLI path. The core engine itself hasn't seen visible changes in weeks, which makes it hard to know what's under active development versus what's drifting into the managed-service track.

The documentation at docs.helix-db.com is functional but thin on the internals — nothing that explains the HNSW tuning parameters or how BM25 interacts with vector search at the query planner level. You'll need to read grammar.pest and vector_core.rs to understand your options.

The HNSW implementation doesn't appear to support quantization (PQ or SQ). At large vector counts that becomes a memory constraint worth planning for. The hql-tests crate has integration tests but they're scenario-based — no property-based tests for the HNSW correctness paths beyond what proptest covers in helix-db/src.

The license is AGPL-3.0, which rules it out for many commercial embedding scenarios without negotiating a commercial license.

Bottom line

If you're building an AI application that needs graph traversals and vector search in the same query — think document graphs, knowledge bases, multi-hop RAG — HelixDB is a technically serious option. The single-writer/multi-reader architecture and arena allocation suggest the team thought carefully about performance, not just features. For pure vector search at scale or anything that needs the AGPL carve-out, there are safer bets.

HelixDB/helix-db on GitHub
HelixDB/helix-db