jeffhajewski/latticedb

Embedded single-file knowledge graph database with vector search and full-text search for AI/RAG apps

LatticeDB – an embedded graph‑plus‑vector‑search database

What it is – LatticeDB is a single‑file, embedded property‑graph database that also indexes high‑dimensional vectors (via HNSW) and full‑text (BM25). It lets a local program query the same data by relationships, semantic similarity, or keyword search using one Cypher‑style query language.

Key selling points

  • One file, zero config – the whole database (graph, vectors, FTS, WAL) lives in a portable file; no server process is required.
  • Unified query layer – MATCH … WHERE node.embedding <=> $vec < 0.3 AND node.text @@ "keyword" works in a single statement.
  • Embedded, single‑writer model – ideal for desktop apps, tools, or agents that run on a single machine.
  • Fast – sub‑microsecond node look‑ups, ~0.8 ms 10‑NN search on 1 M vectors with 100 % recall, and 19 µs BM25 text search.
  • Bindings – native C API plus first‑class libraries for Python, TypeScript/Node, Go, and Java.

Installation

Language Command
CLI curl -fsSL https://raw.githubusercontent.com/jeffhajewski/latticedb/main/dist/install.sh | bash
Python pip install latticedb
TypeScript / Node npm install @hajewski/latticedb
Java Build the JNI bridge (JDK 21+) via the bindings/java README.
Go Follow bindings/go/README.md (cgo workflow).

The packages bundle the native liblattice library on supported platforms; you can also stage a custom build with the LATTICE_BUNDLE_LIB_DIR env var.


Quick example (Python)

from latticedb import Database
from latticedb.embedding import hash_embed

with Database("knowledge.db", create=True, enable_vectors=True, vector_dimensions=128) as db:
    db.create_node_fts_index("Chunk", "text")
    with db.write() as txn:
        alice = txn.create_node(labels=["Person"], properties={"name": "Alice"})
        doc   = txn.create_node(labels=["Document"], properties={"title": "Attention Is All You Need"})
        chunk = txn.create_node(labels=["Chunk"], properties={"text": "The transformer architecture uses self‑attention..."})
        txn.set_vector(chunk.id, "embedding", hash_embed("transformer self‑attention", 128))
        txn.create_edge(chunk.id, doc.id, "PART_OF")
        txn.create_edge(doc.id, alice.id, "AUTHORED_BY")
        txn.commit()

    results = db.query(
        """
        MATCH (c:Chunk)-[:PART_OF]->(d:Document)-[:AUTHORED_BY]->(a:Person)
        WHERE c.embedding <=> $q < 0.5
        RETURN d.title, c.text, a.name
        ORDER BY c.embedding <=> $q
        LIMIT 5
        """,
        parameters={"q": hash_embed("attention mechanism", 128)}
    )
    for r in results:
        print(r["d.title"], "by", r["a.name"])

The same pattern works in TypeScript, Go, and Java (see the README for full snippets).


Performance highlights (from the repo’s benchmarks)

Operation Latency Throughput
Node lookup (cached) 0.13 µs 7.9 M ops/s
10‑NN HNSW (1 M vectors) 0.83 ms (mean, 100 % recall) 1.2 K queries/s
Full‑text BM25 (100 docs) 19 µs 53 K queries/s
2‑hop graph traversal (100 K nodes) 39 µs –

Compared to popular alternatives, LatticeDB’s node look‑ups match in‑memory RocksDB, its vector search beats FAISS single‑threaded HNSW and is on par with server‑based Weaviate/Qdrant, while its BM25 search is ~300× faster than SQLite FTS5.


Core features

  • Graph – labeled nodes/edges, property indexes, ACID transactions, MERGE/UNWIND, aggregations.
  • Vector search – HNSW ANN, configurable M/ef, bulk ingestion, built‑in hash embed helper or HTTP client for real models.
  • Full‑text – BM25 inverted index, tokenization, stemming, fuzzy Levenshtein search.
  • Cypher dialect – MATCH, WHERE, RETURN, CREATE, DELETE, ORDER BY, LIMIT, plus custom operators <=> (vector distance) and @@ (text match).
  • Durability – write‑ahead log, point‑in‑time backup, hot backup, compacting freelist.
  • Event streams – named changefeeds share the same WAL, useful for reactive agents.
  • In‑memory mode – :memory: opens a transient DB with no file I/O.

Typical use cases

  • Local knowledge bases, note‑taking apps, or personal search tools that need both graph relationships and semantic search.
  • Agent memory / RAG pipelines where a single process stores chunks, embeddings, and metadata and queries them together.
  • Prototyping graph‑centric applications without running a separate server (lightweight alternative to Neo4j or Weaviate).

When to look elsewhere

  • Multi‑process or networked workloads – LatticeDB only allows one writer at a time.
  • Purely tabular data – a relational DB (SQLite, PostgreSQL) may be simpler.
  • Massive concurrent writes or distributed scaling – a client‑server system (e.g., Neo4j, Qdrant) is more appropriate.

Where to go next

  • Getting started – docs/getting_started.md walks through CLI, Python, TS, Go, and Java setups.
  • Examples – see examples/cli, examples/go, and the language‑specific READMEs for runnable demos.
  • Benchmarks – run zig build benchmark or the specific vector/graph/FTS benchmarks to reproduce the numbers.

LatticeDB is a purpose‑built engine for anyone who wants a fast, local, single‑file store that can handle graph traversals, vector similarity, and full‑text search all together.

Related

  • Dispatch
  • Project
  • Project
  • Project
  • Project