Home / Blog / Databases

FalkorDB, explained: the graph database that's secretly linear algebra

FalkorDB is an ultra-fast graph database with one unusual idea at its core: it stores your graph as sparse matrices and answers queries with matrix multiplication. The payoff is a single engine that does graphs, graph algorithms, and vector search together — which is exactly the shape modern AI, RAG and agent memory need. Here's the whole thing, jargon kept to a minimum.

A glowing node graph on the left flows into a sparse matrix grid in the middle and then into a strip of embedding vectors with a magnifying glass on the right
The whole story in one picture: a graph becomes a matrix, and the same store also holds the vectors you search over

TL;DR

A graph is really a matrix, and walking the graph is really multiplying by that matrix. FalkorDB leans all the way into that: every relationship type is a sparse adjacency matrix, patterns compile to chains of matrix multiplications, and the heavy lifting runs on GraphBLAS — a battle-tested library for sparse linear algebra. That's where the speed comes from.

It ships as a Redis module, so you start it with one Docker command, query it in openCypher, and get a visual browser for free. And because it also has a built-in vector index, your embeddings live right next to your graph — search by meaning, then hop across relationships for context. One engine instead of three.

Why a graph database?

Think about the data you actually work with. People know people. Customers buy products. Accounts send money to accounts. The connections are the interesting part. In a relational database those connections live in JOIN tables, and every extra hop — friends, then friends-of-friends, then friends-of-friends-of-friends — means another expensive JOIN. Ask a deep question and the query balloons.

A graph database flips that around. It stores the connections directly, so following a relationship is cheap no matter how deep you go. FalkorDB uses the standard property graph model, which has just two building blocks:

Two labelled node circles carrying property tags, connected by one directed relationship arrow that also carries a property tag
The whole data model: nodes (entities with labels + properties) joined by directed, typed relationships that can carry properties too
  • Nodes are entities. Each can have labels (like User or Book) and properties (like a name or an email).
  • Relationships are directed, typed edges between nodes (like FRIENDS_WITH or LOVES) — and they can carry their own properties too.

There's no rigid schema to define up front: you invent new labels and relationship types the moment you use them. That flexibility is why graphs are the natural fit for today's hottest workloads — knowledge graphs for GenAI and RAG, agent memory, fraud detection (fraud rings are literally loops in the graph), and classic recommendations.

The big idea: a graph is a matrix

Here's the insight that makes FalkorDB different. Take any graph and number its nodes 0, 1, 2, … Now draw a grid with one row and one column per node, and put a 1 in row i, column j whenever there's an edge from node i to node j. That grid is the adjacency matrix. In FalkorDB, every relationship type gets its own.

A small five-node directed graph above, and below it the matching square adjacency matrix with the corresponding cells filled in orange
Number the nodes, and the graph becomes a grid: a filled cell means "there's an edge here"

Why bother? Because once your graph is a matrix, graph operations turn into matrix operations — and those have decades of fast, optimized math behind them. The classic example is a single hop. Make a vector with a 1 for every node you're standing on (your "frontier"). Multiply it by the adjacency matrix, and you land on every neighbour at once — for all starting points simultaneously, in one operation.

A four-node graph with its adjacency matrix, showing v prime equals A transpose times v for one hop, and A squared for two-hop reachability
One hop is one multiplication (v′ = Aᵀv). Want friends-of-friends? Square the matrix — A² even counts how many 2-step paths exist

Want to go two hops? Square the matrix. "Friends of friends" is literally A × A, and the result even tells you how many different 2-step paths connect each pair. This is how FalkorDB thinks about every traversal you write — not as pointer-chasing one edge at a time, but as algebra over the whole frontier.

Why sparse matrices make it fast

"One row and column per node" sounds alarming — a million users would be a matrix with a trillion cells. The saving grace: real graphs are almost entirely empty. Each user knows a few hundred people, not a million, so nearly every cell is a zero.

A large mostly-empty grid where only a sparse scattering of cells is filled, those filled cells collected into a small compact list
A sparse matrix stores only the non-zero cells — so memory grows with the number of edges, not with the square of the node count

Sparse matrix formats store only the cells that aren't zero. Memory grows with the number of edges, not with n². FalkorDB builds on GraphBLAS, the standard library for exactly this kind of sparse linear algebra, and it's the first property-graph database to represent its whole graph this way.

What about fast writes? Editing a tightly-packed matrix is expensive, so FalkorDB keeps each one as three parts: the big main matrix plus a small plus and minus for recent additions and deletions. Writes only touch the tiny deltas, and a background process folds them in later. You get matrix speed and quick inserts.

How a query actually runs

You never see the matrices — you write openCypher, the most widely used graph query language. FalkorDB takes it from there:

A six-stage pipeline: Cypher query, parser to AST, execution plan, algebraic expression, GraphBLAS multiply, and a result set table
From text to algebra to answers: your Cypher pattern is compiled into a chain of matrix multiplications and run on GraphBLAS

Your query is parsed and planned, then — this is the twist — each graph pattern is compiled into an algebraic expression: a chain of matrix multiplications. GraphBLAS multiplies those sparse matrices together, and the results stream back. Text in, algebra in the middle, rows out.

Getting started in one command

None of this shows up in day-to-day use, which is the point. FalkorDB ships as a Redis module, so you start the engine and a visual browser with a single Docker command:

# graph engine on :6379, visual browser on :3000
docker run -p 6379:6379 -p 3000:3000 --rm falkordb/falkordb:latest
A container ship carrying boxes with a graph blooming out of a terminal window, illustrating a one-command launch
One command starts the database and a browser at http://localhost:3000

Connect from your language of choice (Python, JavaScript, Rust, Java) — the pattern is always connect, select a graph, query:

# pip install falkordb
from falkordb import FalkorDB
db = FalkorDB(host="localhost", port=6379)
g = db.select_graph("social")

Then it's just openCypher. You draw the shape you want with ASCII-art arrows; the engine finds every match. Creating data:

CREATE (a:User {name:'Alice'})-[:FRIENDS_WITH {since:2020}]->(b:User {name:'Bob'})

And asking a question — "who are Alice's friends?" — is just describing the pattern:

MATCH (a:User {name:'Alice'})-[:FRIENDS_WITH]->(friend)
RETURN friend.name

No JOINs, no foreign keys — just the shape of the relationship you care about. Once you've internalized node → arrow → node, you can read most Cypher you'll ever meet.

Vectors live in the same graph

Here's where it gets genuinely useful for AI. FalkorDB has a native vector index, so an embedding is just another property on a node. That means semantic search and graph structure live in one store — no separate vector database to sync.

// 1) store an embedding on a node
CREATE (:Chunk {text:"...", v: vecf32($embedding)})
// 2) index it (768-d, cosine)
CREATE VECTOR INDEX FOR (c:Chunk) ON (c.v)
  OPTIONS {dimension:768, similarityFunction:'cosine'}
// 3) k-nearest-neighbour search
CALL db.idx.vector.queryNodes('Chunk','v', 5, vecf32($q)) YIELD node, score

To see it in action I built a small demo: three public-domain novels — Wuthering Heights, The Merchant of Venice and A Tale of Two Cities — split into nearly 2,000 passages, each embedded and stored as a graph node with a vector index. The screenshot below is a live search:

A search UI: a query maps to a red star in an embedding scatter plot, with nearest passages highlighted and ranked by similarity on the right
Real semantic search over the novels: the query becomes a point in embedding space, and FalkorDB's vector index returns the nearest passages — ranked by meaning, not keywords

Ask for "a merciful judge weighing a pound of flesh" and every top hit lands in Portia's courtroom in The Merchant of Venice — with no keywords in common. But the real superpower is the combination: each result is a node, so you can immediately hop across relationships to its book, its author, or its neighbouring passages. Vectors find meaning; the graph provides context. That is precisely the recipe behind GraphRAG.

🕸️

Graph

Property graph + openCypher, so relationships are first-class and cheap to traverse.

Linear algebra

Sparse GraphBLAS matrices under the hood — traversal as multiplication, batched and fast.

🔎

Vectors

Native KNN index in the same store, so embeddings and structure never drift apart.

Why it matters

Most "AI databases" are really three systems taped together: a graph store, a vector store, and glue code keeping them in sync. FalkorDB collapses that into one engine — and does it on an unusually elegant foundation. The theory (a graph is a sparse matrix) buys the performance; the packaging (a Redis module, one Docker command, openCypher, a built-in browser) buys the ease.

The one-sentence version. If your problem has both relationships and meaning in it — knowledge graphs, RAG, recommendations, agent memory, fraud — FalkorDB lets you keep them together and query them fast, because underneath, it's all just linear algebra.

The best way to get the intuition is to run it: one Docker command, then paste in a few CREATE and MATCH lines and watch the browser draw your graph. From there, adding a vector index is three more lines — and you've got a graph-plus-vector store on your own machine.

References