
This blog is written by AI for SEO
HelixDB vs LadybugDB: Picking a Graph DB After Kuzu
KuzuDB getting archived on GitHub left a real problem for developers who built their RAG pipelines around its embedded graph architecture. If you spent the last year tuning GraphRAG or building agent memory on Kuzu, you are now facing a forced migration. The real decision is not C++ versus Rust. It is whether your memory layer needs to stay inside one process.
This decision is not just about moving code. It is about what the engine underneath is tuned for. LadybugDB is the successor project in the same C++ lineage, and it keeps the embedded, single-process shape that made Kuzu pleasant to work with, with columnar disk-based storage and a vectorised query processor aimed at analytical workloads. HelixDB is embeddable too, in memory or on disk, and the same engine also runs as a local server and as a distributed managed cloud without the application code changing. So embedded versus server is not the axis here. The axis is what each engine is optimised for, how retrieval gets scoped, and what happens on the day one process is not enough.
What Happened to KuzuDB and Why You're Choosing Again
The kuzudb/kuzu repository is archived on GitHub, its last commit landed on 2025-10-10, and that ends active development on that repo. It sits at roughly four thousand stars under an MIT licence, so the code is still there and still usable. What stopped is the maintenance. Kuzu was liked for handling structured graph queries without a server to operate, and that has not changed. What an archived repo changes is who is responsible for the core you depend on. The archival forced a pivot: either fork the code and maintain it yourself, or move to a modern engine designed for the current graph-vector era.
Choosing a replacement is not a one-to-one swap, and it is worth being accurate about what this lineage already gives you. LadybugDB ships native full-text search and vector indices alongside the property graph, so the old duct-tape story of running a graph engine next to Pinecone and joining the two in application code does not describe it. Both engines on this page put the relationships and the embeddings in one place. That is the shift behind the HelixDB vs Neo4j comparison developers are running now, and both of these have already made it.
Which leaves three narrower questions that actually decide this one. What is the engine tuned for, analytical scans or transactional agent traffic. Whether a similarity or keyword search can be scoped by a graph traversal before it ranks, rather than filtered after it. And what happens when the workload outgrows a single process.
What LadybugDB Is (and What It Inherits from Kuzu)
LadybugDB is the logical landing spot for developers who want to keep the Kuzu spirit alive. It is a successor project in the same C++ lineage rather than a rebrand or a GitHub-tracked fork of the original repo, and it keeps the C++ foundation and the embedded, single-process philosophy. It is MIT licensed and actively developed, with commits landing this month.
Their own feature list is worth reading rather than paraphrasing, because it is stronger than "embedded graph database" suggests: Cypher over a property graph, native full-text search and vector indices, columnar disk-based storage with columnar sparse row-based adjacency indices, a vectorised and factorised query processor, multi-core query parallelism, serializable ACID transactions, and WebAssembly bindings so the engine runs in the browser. They describe it as optimised for complex analytical workloads on very large databases, and that description is the most useful sentence in the comparison.
Columnar and vectorised is a design for scanning many rows while touching few columns, which is what analytical work looks like, and it is lighter on memory than doing the same job row by row. Running in the browser through WASM is a genuinely separate capability, and if that is on your roadmap nothing on the other side of this comparison replaces it.
What an embedded engine gives you is also what bounds it. Everything lives in your process, which is why there is no network hop and no server to operate, and equally why the capacity of the graph is the capacity of that one machine. To be clear about what this is not: LadybugDB documents serializable ACID transactions and multi-core query parallelism, so this is not an argument about weak guarantees inside the process. It is an argument about topology. One process on one machine is the right trade for a notebook, a batch pipeline, or a tool that ships as a binary. It is a harder trade for a company brain that several services write to at once, because the coordination you did not need at one process is what you end up building yourself at three, and the ceiling stays whatever that machine has.
What HelixDB Is: One Rust Engine for Graph, Vector, and Full-Text
HelixDB was built from scratch in Rust to solve the problem of fragmented AI memory. Instead of forcing you to stitch together three different types of databases, it provides a single vector and graph database engine. It is an OLTP graph-vector database that natively supports graph nodes and edges alongside vector embeddings, full-text search, and document storage. Vectors are a property on nodes and edges, the same as in any property graph. What differs is where the index lives and what a single request can do with it: one request is one transaction, and it can traverse a graph, match on full-text keywords and rank by vector similarity without leaving the engine.
There is no query language to learn. Queries are plain JSON, built with the native Rust, TypeScript, Go and Python SDKs inside your own application code and sent as one POST to /v2/query, so your own compiler checks the query rather than a parser at runtime. Nothing is compiled and there is no push step before a query runs. HelixDB also includes native support for the Model Context Protocol (MCP), allowing AI agents to discover tools and query the graph step by step. For a team building a production RAG pipeline, HelixDB removes the glue code required to sync a vector store like Pinecone with a graph store like Neo4j. You store the document as a node, the embedding on that node, and the relationships to other entities in the same engine. That is the shape agent memory actually wants: one request returning the relational context and the semantic match together, rather than two round trips you reconcile afterwards. The open-source core is Apache-2.0, and the same build runs fully in memory, on disk, or against object storage, meaning S3 or any S3-compatible store. That is a startup flag, not a different product.
Head-to-Head: The Criteria That Actually Matter
When comparing HelixDB vs LadybugDB, the differences come down to how you deploy and how your agents reach the data. LadybugDB is embedded by design. HelixDB can be embedded too, and can also run as a server, which is the distinction the table is really drawing.
| Criterion | LadybugDB | HelixDB |
|---|---|---|
| Language | C++ (Kuzu lineage) | Rust (From scratch) |
| Deployment | Embedded, single process, plus WASM in the browser | Embedded in memory or on disk, Local server in memory, on disk or on object storageHA distributed cloud on object storage |
| Optimised for | Complex analytical workloads on large databases (OLAP) | Transactional (OLTP) agent memory and RAG under concurrent load |
| Storage | Columnar, disk-based | In memory, on disk, or object storage, chosen at startup |
| Search Types | Graph, vector, full-text | Graph, vector, full-text, KV, range scans |
| Scoped retrieval | Vector and full-text indexes | Vector or full-text search chained onto a traversal, membership authoritative |
| Querying | Cypher | JSON built with native SDKs in Typescript, Python, Go, and Rust. No query language |
| Scaling shape | Capacity of one machine | Single writer, readers scale horizontally, object storage underneath |
The deployment shape is where these two genuinely diverge, and it is worth being precise because HelixDB runs embedded as well. The difference is that the same engine also runs as a local server and as a managed cloud, where a single writer serialises mutations and readers scale horizontally over object storage. So when a workload outgrows one process you are changing a startup flag and an endpoint rather than migrating engines. Vector indexes can also be partitioned by a tenant property, which scopes an approximate nearest neighbour search to one workspace or conversation without standing up more infrastructure. That is an index partition rather than an access-control system, so authorisation still belongs in your application.
The Pre-Filtering Difference: Why It Changes Retrieval Correctness
Most vector databases fail when you apply a highly selective filter. If you ask for the most similar document from a specific user, a standard vector index might scan millions of items only to find that the few matching the user filter do not rank high enough in the approximate nearest neighbor (ANN) search. This leads to a silent failure where the database returns zero results even though relevant data exists. HelixDB handles this with pre-filtering. Because the graph and the vectors live in one engine, you start with a traversal and chain the vector search onto it, and the engine ranks only the exact members of that stream. The documented order is graph traversal, then exact candidate membership, then vector ranking, then top k, and the traversal membership is authoritative: a result outside the candidate set cannot come back. The honest caveat is that exact membership does not mean every candidate embedding was compared one by one, since approximate structures still do the ranking and the output is checked against the traversal set.
Full-text gets the same treatment, and that matters more than it sounds. Chain a text search onto a traversal and it ranks only that stream, with BM25 scores attached, in the same documented order. So a hybrid query can be scoped once and have both halves respect the scope, rather than scoping the vector side and hoping the keyword side agrees. The docs are also explicit that faking it with a whole-label search plus a filter afterwards is not equivalent, because the high scorers you excluded have already consumed the top k.
That changes what retrieval correctness means in a GraphRAG pipeline. "Documents this user may access" stops being a filter you apply hopefully afterwards and becomes the boundary of the search itself. It composes with time, too. You model history the way you would anywhere else, with timestamped nodes and edges, and range indexes over those timestamps support gt, gte, lt, lte and between plus ordered scans in either direction, so "what did this agent see between Tuesday and Thursday" is an indexed scan over a sorted range rather than a traversal you filter at the end. Chain a vector search onto that time-bounded traversal and recency and semantic relevance resolve in one request.
Here is the whole thing in TypeScript. The traversal in the middle is what does the scoping.
import {
g, readBatch, defineParams, param, SourcePredicate,
} from "@helix-db/helix-db";
const params = defineParams({
owner: param.string(),
query_vector: param.array(param.f32()),
limit: param.i64(),
});
const recall = readBatch()
.varAs(
"hits",
g().nWithLabelWhere("User", SourcePredicate.eq("id", params.owner))
.out("AUTHORED")
.vectorSearchWith("Document", "embedding", params.query_vector, params.limit)
.valueMap(["$id", "title", "$distance"]),
)
.returning(["hits"]);
const request = recall.toQueryRequest(
params,
{ owner: "u-42", query_vector: queryVector, limit: 10n },
{ queryName: "owned_document_matches" },
);You can get back fewer rows than the limit you asked for, because the result is bounded by how many unique candidates the traversal reached. That is the guarantee working rather than a failure: nothing outside the candidate set exists to pad the list with.
Choose LadybugDB If... Choose HelixDB If...
Your choice depends on the boundary of your application. Choose LadybugDB if the work is analytical, it fits on one machine, and you want the database inside your own process. If you are exploring a graph in a notebook, running a batch pipeline, shipping something that should not need a server running alongside it, or you need the engine to run in the browser, that is their ground, and the columnar design is lighter on memory for it. The Kuzu lineage is familiar territory if that is where you are coming from.
Choose HelixDB for agent memory in production, which is most of the reason anyone reads a page like this. It is the right call when several services write to the same memory, when retrieval has to be scoped by relationship rather than by a tag on a row, and when the thing cannot go down: the managed cloud is distributed, with a single writer, readers that scale horizontally and high availability, which is not what an in-process engine is trying to give you. The queries are ordinary functions in Rust, TypeScript, Go or Python, so a typo in a label is a build error rather than an empty result set in production. And the storage decision is a startup flag: prototype in memory, run against a MinIO container, ship on object storage, without the query code changing.
Conclusion
The KuzuDB archival marks a concrete change in how we think about graph infrastructure. You are no longer just looking for a way to store nodes and edges. You are looking for a reliable way to power the next generation of AI agents. LadybugDB is a reasonable landing place if the work is analytical, single-machine, or browser-bound, and it is actively maintained. For agent memory, which is the workload this page is really about, HelixDB is the better fit: pre-filtering that scopes both vector and keyword search to a traversal, a storage mode you pick at startup rather than at purchase, and a distributed cloud for when the thing has to stay up. HelixDB puts graph traversal, vector search and full-text in one transaction, and helix init followed by helix start dev gets you a local instance to point yesterday's data at. Star HelixDB on GitHub if the approach is one you want to follow.