Rewriting FalkorDB in Rust: Make It Work, Make It Stable, Then Make It Fast - FalkorDB
Discord
3.4k
Log in
Start Free
Open menu
Menu
Close menu
Start Free
Discord
3.4k
Back to all posts
Rewriting FalkorDB in Rust: Make It Work, Make It Stable, Then Make It Fast
Dvir Dukhan
Avi Avni
Date Published:<br>August 3, 2026
Date Updated: August 3, 2026
80,000 lines of Rust, 357 merged pull requests, 1,585 TCK scenarios and 1,322 flow tests green. FalkorDB’s new engine is here, and this is the story of building it. The C engine is fast and mature, but it’s manually managed memory, and the crashes that slip through are the kind that can take customer data with them. Rust removes those bug classes at compile time without giving up the low-level control a database needs. We used coding agents throughout, and we were careful about how: humans made every design decision and reviewed every change, agents got the bounded work, and correctness was measured against the C engine’s own test suite before performance was allowed to matter. Make it work, make it stable, then make it fast. This post is about how we did it.
Why?
As FalkorDB evolved, we made the strategic decision to rewrite our core database engine in Rust to build the next generation of the product on a safer and more maintainable foundation. While C has served the industry well for decades, modern distributed database systems demand stronger guarantees around memory safety, concurrency, and long-term maintainability. Rust eliminates entire classes of memory related bugs at compile time without sacrificing low-level control or performance. Those bug classes are also considered security bugs: memory corruption is what most exploitable database vulnerabilities are made of, so removing it at compile time shrinks the attack surface, not just the crash count. We went through the C engine’s issue tracker and found more than 100 open bugs that this migration closes, mostly crashes and memory corruption that Rust doesn’t allow. For our customers, the migration is completely transparent and no application changes are required. Existing Cypher queries, APIs, and integrations continue to work as before, enabling a seamless migration while benefiting from a more robust underlying engine.<br>Performance remained a non-negotiable requirement throughout the rewrite. Our internal benchmarking shows that the Rust implementation delivers performance on par with the original C codebase, and in some cases even exceeds. Beyond performance, the greatest advantage is engineering velocity. Rust’s strong type system and safety guarantees allow our team to develop, test, and ship new functionality with greater confidence, reducing debugging time and accelerating time-to-market for new capabilities. The result is a database that not only preserves FalkorDB’s performance leadership but also provides a stronger foundation for rapid innovation and long-term reliability.
If any of this was useful, a star is the fastest way to help other engineers find FalkorDB.
Star on GitHub
Not a redesign, a re-expression
From day one, the project had one rule: keep everything that makes FalkorDB what it is (graphs as sparse matrices, traversal as matrix multiplication, Redis as the host), and use Rust’s compile-time enforcement for the invariants that the C code left to developer discipline.<br>That rule wasn’t just a slogan. The RDB serialization format is byte-compatible with the C engine’s v19, so a Rust server can load a dump written by the C server. The C engine’s whole integration test suite was pulled in as a compatibility oracle. Some optimizer passes even cite, comment by comment, the exact C code they mirror.<br>The rule covered behavior, not structure, and starting fresh let us apply lessons from the C implementation that legacy code made impractical there. The biggest one: the graph engine is now fully independent of the host database it runs on. It lives in a separate crate, and storage, matrix layer, planner, and executor compile and link without any host-side dependencies. The dependency direction only runs one way, the host calls engine, never the reverse. That boundary is also a containment line: the engine can’t reach into host state it was never meant to touch, and what crosses between them is a defined API rather than shared memory. That’s better security than the C layout, where those layers share headers and global state. In C those layers share headers and global state, so the boundary had to be defined rather than extracted.<br>We’re in the process of building an index library, built to fit the engine’s MVCC model, and once that’s done the separation is complete.
The engine’s behavior is unchanged; what changed is that its entry points are now a public API surface, so it can be linked into another binary, run behind its own server process, or driven directly from unit tests with no host running. More on what that unlocks in a follow-up post.
Spring 2025
A walking skeleton....