镜像分 arm64-metal、amd64-cpu、amd64-cuda、amd64-vulkan 等变体,选错架构无法获得对应加速;带 bge 的镜像体积更大,构建 Heimdall 变体需先 make download-models 下载约 750MB 模型;macOS 上 Docker 跑不了 Metal,GPU 加速要原生安装。
NornicDB
ornerydMIT活跃维护分布式低延迟图+向量数据库,兼容 Neo4j Bolt/Cypher 和 Qdrant gRPC,无需改代码即可切换,支持亚毫秒 HNSW 检索与图遍历。
Nornicdb is a distributed low-latency, Graph+Vector, Temporal MVCC with all sub-ms HNSW search, graph traversal, and writes. Using Neo4j Bolt/Cypher and qdrant's gRPC means you can switch with no changes while adding intelligent features like schemas, managed embeddings, reranking+llm, GPU accel, Auto-TLP, Policy-based Memory Decay, and MCP server.
docker run -d --name nornicdb -p 7474:7474 -p 7687:7687 -v nornicdb-data:/data timothyswt/nornicdb-amd64-cpu-bge:latest支持 CPU、CUDA、Metal、Vulkan 多架构;README 未给出具体显存或 GPU 型号要求。macOS 上 Docker 不暴露 Metal 加速,需从 releases 原生安装或本地构建才能用 GPU。
兼容 Neo4j 的图数据库,把图遍历、向量检索和历史版本读放进同一个引擎
分布式低延迟图+向量数据库,兼容 Neo4j Bolt/Cypher 和 Qdrant gRPC,无需改代码即可切换,支持亚毫秒 HNSW 检索与图遍历。
核心能力
- 通过 Bolt/Cypher 兼容 Neo4j 现有驱动与应用
- 内置 HNSW 向量索引与全文检索,支持混合检索
- 用 MVCC 快照隔离提供 as-of 历史读与事务冲突检测
- 同时暴露 REST、GraphQL、Bolt 和 Qdrant 兼容 gRPC
- 支持 Metal/CUDA/Vulkan 加速与内存衰减策略
容易踩的坑
- v1.4.3v1.4.3 - Cochise最新正式版2026-10-16 · 2026-10-16 02:22 UTC
v1.4.3 - Cochise - 10/15/26
Cochise is a bugfix release focused on reliable writes, accurate query results, and consistent behavior across clients.
Highlights
- Accurate counts during writes: fixes double-counted nodes and relationships while buffered writes become durable, including grouped product/category counts.
- More consistent Cypher: corrects subquery comments, variable scope, temporal values, numeric rounding, and ordering of local and remote graph values.
- Stronger constraint enforcement: fixes uniqueness checks for lists, composite keys, and mixed numeric values, including validation of existing data.
- Reliable transactions and recovery: preserves property types and metadata across recovery, improves snapshot/cache consistency, and stops canceled operations promptly.
- Consistent access controls: fixes database permissions, custom-procedure administration, and password-change credential caching. Property visibility is applied more consistently across query and search results.
- Smoother query performance: avoids repeated cold grouped-count work and quadratic scanning of large map-heavy queries.
Upgrade notes
- Keep a pre-upgrade backup for rollback. Older binaries cannot read the new snapshot format or fully restore the new WAL metadata. See recovery-format compatibility.
- Go integrations: remote query entities/paths now use
storage.RemoteEntityValue/storage.RemotePathValue; projected graph properties retain their numeric/list types. Review direct type assertions. See remote entity values. - Installing, replacing, or removing custom procedures requires administrator permissions.
id(n)continues to return NornicDB string IDs.
macOS installers, Homebrew tarballs, and checksums will appear under Assets as the release builds complete. Container images are published by the CD matrix.
Full Changelog: https://github.com/orneryd/NornicDB/compare/v1.4.2...v1.4.3
- v1.4.2v1.4.2 - Knock Knock2026-10-13 · 2026-10-13 20:40 UTC
查看更新说明
v1.4.2 - Knock Knock - 10/13/26
Knock Knock delivers a major expansion of Cypher 25 compatibility, graph retrieval capabilities, transaction correctness, durability controls, and write performance. This release adds relationship search, fused graph retrieval, search-match provenance, Change Data Capture (CDC), native
VECTORandUUIDsupport, and a new write-behind commit buffer.It also includes extensive compatibility fixes validated against Neo4j 5.26 and Neo4j 2026.09, along with significant improvements to constraint enforcement, concurrent writes, traversal planning, and storage efficiency.
As for "async" writes there was only one query that worked under the old asyncEngine. The entire concept was scrapped and moved to a badger storage write behind cache. This trades memory for raw update performance across the board.
Added
Cypher Language
- Cypher 25 query structure: Added
NEXTchains for query parts (RETURN 1 AS a NEXT RETURN a + 1 AS b),WHEN ... THEN ... ELSEbranching, braced query parts ({ q }) for groupingUNIONoperations, and explicit grouping withRETURN/WITH ... GROUP BY keys. Implicit-grouping errors now match Neo4j. Results match Neo4j 2026.09. (#1028) - Cypher 25 expressions: Added
RETURN ALL,WITH ALL, interpolated strings (s"{p.name} is {p.age}"), map comprehensions ({k: v IN m WHERE v > 1 | k: v}),n IS [NOT] LABELED <label expression>, dynamic label and type tests (WHERE n:$(e),n IS $any(l)),allReduce(...), andPROPERTY_EXISTS(n, key). (#1028) SHOW ... YIELDcomposition: Any clause, includingWITH,MATCH,UNWIND,CALL {},FILTER, writes, andUNION, can follow aSHOWcommand'sYIELD. Subsequent clauses see only the yielded columns, soRETURN categoryafterYIELD namecorrectly fails withVariable not defined. (#1028)- GQL path selectors and path modes: Added
ANY SHORTEST,ALL SHORTEST,SHORTEST k [GROUPS],ANY [k], andALL [WALK | TRAIL | ACYCLIC]. Pattern predicates select candidate paths, while the clause'sWHEREfilters the selected paths. Invalid combinations produce Neo4j-compatible syntax errors. (#907) - Quantified path patterns: Added patterns such as
(a)((x)-[r:T]->(y) WHERE r.w > 1){1,3}(b)and parenthesized path patterns such asMATCH p = ((a)-->(b) WHERE ...). Variables inside groups bind lists, group predicates apply to each iteration, and parameters and functions work in group predicates, including underSHORTEST k. (#907) - Match modes: Added
MATCH REPEATABLE ELEMENTSandMATCH DIFFERENT RELATIONSHIPS. Reusing a relationship variable within a singleMATCHproduces no matches underDIFFERENT RELATIONSHIPSand joins underREPEATABLE ELEMENTS. Without an explicit mode, the openCypher TCK's syntax error is preserved. (#907) - Dynamic labels, relationship types, and property keys: Added
$(expr),$all(expr), and$any(expr)inMATCH,CREATE, andMERGEpatterns;SET/REMOVE n:$(expr); andSET n[key] = v/REMOVE n[key]. Supported acrossMERGEactions andFOREACH, matching Neo4j 5.26 behavior. (#907) - Cypher 25
VECTORandUUIDvalues: Addedvector(value, dimension, type),vector_dimension_count,vector_distance,vector_norm,uuid()(v7),uuid(text), anduuid(msb, lsb). Supports float32 vector operations with bit-for-bit Neo4j compatibility, UUID bit properties, equality, ordering, type predicates (IS :: VECTOR(n)/IS :: UUID), property storage, Bolt and HTTP encodings, and Neo4j-compatible compile-time type errors. (#907) - Property type constraints: Added all Neo4j property types, including unions (
IS :: INTEGER | STRING),LOCAL TIME,ZONED TIME,DURATION,POINT, and synonyms such asTIMESTAMP WITH TIME ZONEandVARCHAR.SHOW CONSTRAINTSreports normalized types. (#907) LIST<T>property type constraints: Added scalar
- Cypher 25 query structure: Added
- v1.4.1v1.4.1 - Black Sheep2026-10-09 · 2026-10-09 06:01 UTC
查看更新说明
v1.4.1 - Black Sheep - 10/08/26
Highlights
- Cypher 25 shared grammar (foundation slice).
LET,FILTER, andFORreading clauses execute in the existing shared pipeline, with an optionalCYPHER 5/CYPHER 25header. No separate executor, router, or text-rewrite fallback. - Correctly rounded math.
^/power()(andexp/log/log2/exp2/ hyperbolic functions) now return Neo4j's correctly rounded results, fixing the 1-ulp^divergence (#981). - A large Neo4j 5.26.30 compatibility sweep (#907) across operators, literals, functions, UNION, DELETE, temporal values, and MERGE.
- Lazy Bolt auto-commit reads stream rows as the driver
PULLs them (#939). - Storage and concurrency correctness for label scans, record errors, and concurrent unique-key MERGE (#961).
1. Cypher 25 — Shared Grammar Foundation
NornicDB previously rejected
CYPHER 25. This release adds the first implemented slice of the Cypher 25 conformance plan.What is included
LET— bindings with retained scope, including chainedLETclauses. Aggregate expressions are rejected.FILTER— a standalone reading clause filtering rows, with optionalWHERE.FOR x IN expr— iteration over a list, equivalent toUNWIND expr AS x(including scalar coercion:FOR x IN 1returns one row).- Optional language header —
CYPHER 5/CYPHER 25are accepted and discarded by both parsers; callers pass statements as written.
FOR x IN [1, 2, 3] LET scaled = x * 10 FILTER scaled > 10 RETURN x, scaled ORDER BY xOne pipeline, two front ends
- The SRD parser (default) accepts
LET/FILTER/FORand correlated unscopedCALLwithout a header — a permissive, deterministic extension. - The ANTLR parser keeps the strict Cypher 5.26 contract: those additive clauses require
CYPHER 25, and implicit unscopedCALLimports remain rejected. The ANTLR grammar now also parses theCYPHER 5/CYPHER 25preamble directly.
Both front ends feed the same pipeline clause kinds and operators; ANTLR is a syntax front end, not a second execution path.
Rule enforcement
LET/FORredeclaration is rejected (VariableAlreadyBound), non-booleanFILTERpredicates fail as in Neo4j (including the list-to-boolean coercion error), aggregates are rejected inFILTER, and conflictingCYPHER 5 CYPHER 25is anArgumentError.This is the foundation slice of the Cypher 25 conformance plan — not full 2026.09 conformance. The remaining inventory (SEARCH, graph types, typed VECTOR/UUID values, standalone ORDER BY after LET, and more) is tracked in the plan and stays open.
2. Correctly Rounded Math (#981)
Go's
mathpackage (fdlibm) is up to 1 ulp away from Java'sMathfor some inputs, so3 ^ 2.5returned15.588457268119894instead of Neo4j's15.588457268119896.- Ported musl's double-precision
exp,exp2,log,log2, andpow(Arm optimized-routines, MIT) and the six hyperbolic functions intopkg/math/libm. - The package mirrors the standard library
mathAPI, so everymathimport became an import alias tolibmwith no call-site changes. Sin/Cos/Tan/inverse-trig/Log10/Log1p/Expm1are fdlibm-derived identically in musl and Go, so they are re-exported unchanged.
3 ^ 2.5and9007199254740993 ^ 2.5now match Neo4j exactly.
3. Neo4j 5.26.30 Compatibility Sweep (#907)
Dozens of correctness fixes from a differential sweep against
neo4j:5.26.30-community. Notable groups:- Operators —
AND/OR/XOR/NOTfollow Neo4j's rules through one implementation; unary plus;^static types. - Literals —
true,false,null,NaN, andInfinityare literals even where a variable has that name; numeric literals group digits with underscores;0X/0Oprefixes kept as a NornicDB extension;
- Cypher 25 shared grammar (foundation slice).
- v1.4.0v1.4.0 - Lewps2026-10-06 · 2026-10-06 18:11 UTC
查看更新说明
v1.4.0 - Lewps
We are really proud of this release as it improves performance across the board nearly 40-50% in certain cases. The parser architecture is now complete. It is a scannerless recursive descent parser. (no token stream, lightweight lexing, etc...) and results in ~28% faster latency e2e vs ANTLR. Cartesian aggregation is now multi-threaded and automatically scales based off cores and workload (in testing the multiplicative increase is similar to the number of cores you have. Such as 12 cores producing a 9-10x speedup on large aggregations). Also, embedding workers no longer consume a version when embedding a node using managed embeddings. Property updates such as custom embedding properties will still create a new version.
Also, I am considering forking badger to create some additive APIs for property map projections reading from disk be more real than having to filter what was already scanned from the physical disk. TBD
Everything since v1.3.3. The release is about two things: reads and writes that do less work, and a Cypher engine that behaves like Neo4j in more places. The openCypher TCK passes in full on the pinned corpus, and a large batch of fixes closes differences found by running the same statements against Neo4j 5.26.30 over Bolt and HTTP.
openCypher and Neo4j compatibility
- TCK: all 3,897 scenarios of the pinned openCypher corpus (revision
370fe27f) pass in both transaction modes, 7,794 of 7,794 outcomes, with no expected gaps (make cypher-tck-ratchet). - Differential testing: pinned Neo4j 5.26.30 regressions over Bolt and HTTP, in auto-commit and explicit transactions, cover the fixes below.
- New language support:
- label expressions (
n:A|B,n:A&B,n:!A,n:%,n IS A) in every position, which previously matched nothing (#860); - quantified relationships (
-[:R]->{1,3},-->+) (#864); WHEREinside node and relationship patterns (#878);- type predicates (
x IS :: TYPE,IS [NOT] TYPED, unions,LIST<T>,NOT NULL) (#838); - the
FINISHclause,CYPHER version/optionpreambles,point()values with Neo4j's rules, storage, indexing and Bolt/HTTP encoding (#817), andWITH *, items/RETURN DISTINCT *(#883); - keyword-named variables (
where,optional,distinct, …) (#894), and the decay functionsdecayScore(),decay()andpolicy()(#871, #866).
- label expressions (
- Semantics now matching Neo4j:
- label and relationship-type names are case-sensitive (#862);
- integers and floats compare by exact value (#893);
- cross-type ordering for points, temporals, lists, strings and numbers (#837);
- Cypher equality in node-pattern properties, so
(n {n: 1.0})matches a stored1, andMERGEno longer creates duplicates (#846, #844); - the array-property rule, null-valued pattern predicates (#810), Unicode code-point string semantics,
toString()of times, and non-booleanWHEREraisingTypeError; shortestPath/allShortestPathsas a pipeline step, includingOPTIONAL MATCHand value position (#863);- an index and a uniqueness constraint on the same label and property are mutually exclusive (#884).
- Stricter validation: the forms Neo4j rejects are now rejected, including
NOT IN, trailing list commas, adjacent string literals andEXPLAIN PROFILE, with compile-time checks for subscripts, function arity and undefined variables (#657). The strict ANTLR grammar covers subqueries, scopedCALL/UNION, map projections, dynamic labels, type predicates and administration commands (#739). - Procedures and schema:
- canonical
SHOW PROCEDURES/SHOW FUNCTIONSanddb.*/dbms.*signatures, with real data behinddb.stats,dbms.listConnections,dbms.listConfigand persisted database/server UUIDs (#530); - EXPLAIN/PROFILE plans reach Bolt and HTTP clients (#744);
- composite uniqueness constraints, TEXT and POINT indexes, transactiona
- canonical
- TCK: all 3,897 scenarios of the pinned openCypher corpus (revision
- v1.4.0-preview-1v1.4.0-preview-1 - WIPpre-release2026-09-28 · 2026-09-28 08:01 UTC
查看更新说明
1.4.0-preview-1 - working title - (Preview)
[!WARNING] Warning: This requires a storage upgrade so back up your data and only test this on data you don't care about.
[!IMPORTANT] Full openCypher TCK Compliance. That includes all the builtins, math functions, datetime conversions, everything. It's now part of CI and runs over 2000 scenarios in various modes each. more Neo4J - coming soon.
[!NOTE] Performance highlights. Across the board -
- per-query latency dropped roughly 35–45% —
- mean query latency fell from 0.23 ms to 0.14 ms,
- wall time improved from ~1.40 s to ~1.15 s (−18%)
- energy from ~11.8 J to ~10.2 J (−14%),
- peak memory dropped from 32.5 GiB to 20.0 GiB (−38%).
- Ingestion rate climbed from ~8.8k to ~12.7k nodes/sec (+44%)
performance benchmark breakdowns:
https://github.com/orneryd/NornicDB/blob/main/docs/performance/1.1.0-northwind-results/comparison.md
preview-1
- Hotfix - version 2-3 storage upgrade not executing (no data loss)
Added
- Log classified Cypher syntax rejections at INFO with a bounded redacted statement shape, allowlisted statement class and stable grouping hash. JSON logs can be grouped into an optimization backlog without retaining rejected queries in memory.
Fixed
- Deliver EXPLAIN/PROFILE query plans to clients (#744): Bolt PULL SUCCESS
metadata now carries
plan(EXPLAIN) andprofilewith runtime counters (PROFILE), and HTTP transaction results carryplan/profilein the Neo4j JSON shape (operatorType,identifiers,argswithEstimatedRows,children; profile addsrows/dbHits). The Go driver reads both viasummary.Plan()andsummary.Profile(). - Stop PROFILE's inner execution from serving and populating the result cache: a cached result object was mutated with plan metadata and leaked it into ordinary cached reads of the same query.
- Fix
OPTIONAL MATCH p = shortestPath(...)returning a fabricated{result: null}row with the wrong columns instead of projecting the path. Clause-only and anchored forms (MATCH (a) OPTIONAL MATCH p = shortestPath((a)-...->(c))) now run the shared shortestPath BFS with left-outer-join semantics: one row per seed, real values when a path exists, nulls when none, and errors propagate instead of being swallowed. - Allow
shortestPath(...)/allShortestPaths(...)in value position (RETURN length(shortestPath((a)-[:R*]->(b)))) instead of rejecting the statement as an illegal projected pattern expression. Value forms reuse the same BFS machinery as clause forms and project per row. - Return null (not a fabricated
0) forlength(null)/length()of an unbound path in a non-matching OPTIONAL MATCH. - Isolate one-statement transaction scripts (
BEGIN … COMMIT/ROLLBACK) on a private executor instead of the shared per-database executor. A client statement could previously open the script's transaction on the executor other clients' auto-commit statements run on, letting a low-privilege caller crash the process mid-run and cause unrelated clients' acknowledged writes to fail or be silently lost. - Reject bare
BEGIN/COMMIT/ROLLBACKstatements on cached per-database executors (the embeddedDB.Cypher/DB.ExecuteCypherbase executor and the HTTP and Bolt autocommit executor caches) with the sameNeo.ClientError.Statement.SyntaxErrora client statement gets. A bareBEGINon an unmarked context previously opened a transaction on the shared executor, after which every concurrent auto-commit statement and one-statement script ran inside that caller's transaction. Embedded callers that want explicit transactions create their own session executor (cypher.NewStorageExecutor(db.GetStorage())); HTTP/Bolt protocol transaction owners keep their per-session executors. - Treat pattern comprehensions (
[(n)-->(m) | …])
- per-query latency dropped roughly 35–45% —
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
Quick Start
# Homebrew
brew tap orneryd/nornicdb && brew install nornicdb && brew services start nornicdb
# arm64 / Apple Silicon
docker run -d --name nornicdb -p 7474:7474 -p 7687:7687 -v nornicdb-data:/data timothyswt/nornicdb-arm64-metal-bge:latest
# amd64 / CPU only
docker run -d --name nornicdb -p 7474:7474 -p 7687:7687 -v nornicdb-data:/data timothyswt/nornicdb-amd64-cpu-bge:latest
Open http://localhost:7474 for the admin UI. For NVIDIA CUDA hosts, use timothyswt/nornicdb-amd64-cuda-bge:latest. For Vulkan hosts, use timothyswt/nornicdb-amd64-vulkan-bge:latest.
Note: Docker on macOS does not expose Metal acceleration. The Apple Silicon image still runs, but GPU acceleration on macOS requires a native install from the releases page or a local build.
Writing queries? Start with the Hot-Path Cypher Cookbook — proven query shapes that route through the executor's specialized fast paths.
🤖 Building with Claude / agents? The
docs/skills/directory contains agent-ready skill files for every Cypher surface: query shapes, decay/promotion policies, managed embeddings, vector & hybrid search, and RAG procedures. Drop them into.claude/skills/to make agents fluent in NornicDB.
What NornicDB Is
NornicDB is a graph database for workloads that need graph traversal, vector retrieval, and historical truth in the same system. It speaks Neo4j's language through Bolt and Cypher, exposes REST, GraphQL, and gRPC interfaces, and can preserve Qdrant-style client workflows where that helps migration.
The architecture draws from research in Temporal GraphRAG, agent memory systems, event-sourced decision memory, and persistence semantics for AI agents. These ideas appear in NornicDB as graph-native support for temporal facts, canonical knowledge versioning, replayable history, policy-driven memory retention, and audit-friendly retrieval.
It is built for knowledge systems, agent memory, Graph-RAG, and canonical truth stores where semantic search is only part of the query. The design goal is not to bolt a vector store onto a graph database. The design goal is one execution path for graph, vector, temporal, and audit-oriented workloads.
Why NornicDB Is Different
- Neo4j-compatible by default: Bolt + Cypher support for existing drivers and applications.
- Built for AI-native workloads: vector search, memory decay, and auto-relationships are first-class features.
- Graph, vector, and ledger semantics in one engine: hybrid retrieval, graph traversal, canonical graph ledger modeling, tritemporal facts, as-of reads, txlog queries, and receipts do not require a second database.
- Protocol flexibility without splitting the system: REST, GraphQL, Bolt/Cypher, Qdrant-compatible gRPC, and additive Nornic gRPC live on the same platform.
- Hardware-accelerated execution: Metal/CUDA/Vulkan pathways for high-throughput graph + semantic workloads.
- Operational flexibility: full images (models included), BYOM images, and headless API-only deployments.
Deployment Patterns
NornicDB is being used in internal production deployments for stack-consolidation workloads where graph traversal, vector retrieval, and auditability need to live in the same system.
- Agent and Graph-RAG systems: replacing a Neo4j + Qdrant + embeddings stack with a single deployment for task tracking, dependency graphs, and retrieval pipelines.
- Translation and evaluation workflows: replacing a document store plus embeddings pipeline with a single deployment for graph-native retrieval and faster aggregation paths.
Transactional Guarantees & Isolation
NornicDB implements Snapshot Isolation at the storage layer. Each transaction is anchored to a specific MVCC version, so point reads, label scans, and snapshot-visible graph traversals resolve against the same committed view of the graph.
- Repeatable reads within a transaction: transactions see their own buffered writes, but not commits that land after their read snapshot.
- Conflict detection at commit: concurrent graph mutations against the same logical state fail with a normalized
ErrConflictinstead of silently overwriting newer data. - Explicit historical reads: MVCC pruning preserves the current head and a retained floor per logical key; requests below that retained floor fail safely with
ErrNotFound. - Search remains current-state focused: current search paths are intentionally separate from historical MVCC state.
See transaction implementation details, historical reads and MVCC retention, and the canonical graph ledger guide.
Performance Snapshot
Northwind benchmark (48,000 products and 48,000 orders; 30 measured iterations per query after 5 warmups):
| Metric | NornicDB | Neo4j | Difference |
|---|---|---|---|
| Overall mean query latency | 0.13 ms | 54.69 ms | -99.8% (413.40x ratio) |
| Query-latency-only aggregate throughput | 7,559.12 ops/s | 18.29 ops/s | +41240.3% (413.40x) |
| End-to-end query-loop throughput | 16.58 ops/s | 15.14 ops/s | +9.6% (1.10x) |
| Query-loop duration | 25.327 s | 27.746 s | -8.7% (1.10x) |
| Benchmark wall-clock | 35.12 s | 55.06 s | -36.2% (1.57x ratio) |
| Energy during benchmark | 325.30 J | 383.86 J | -15.3% (1.18x ratio) |
| Peak memory used | 17.4 GiB | 17.7 GiB | -1.6% (1.02x ratio) |
All seed counts and per-query result fingerprints matched between NornicDB and Neo4j. See the full Northwind benchmark report for per-query latency, correctness, power, memory, and storage results.
BEIR Retrieval Quality
The reproducible BEIR SciFact evaluation uses the official 300-query test qrels. With exact hybrid RRF retrieval and the native BGE-M3 reranker, NornicDB recorded:
| Recall@10 | Recall@100 | nDCG@10 | MRR@10 | MAP@100 |
|---|---|---|---|---|
| 0.82510 | 0.93563 | 0.72292 | 0.69447 | 0.69215 |
These scores are configuration-specific rather than an official leaderboard placement. See the BEIR retrieval benchmark for the protocol, baselines, confidence intervals, and published-reference context.
Hybrid Retrieval Benchmarks
Hybrid retrieval is where NornicDB is materially different from vector-only stacks: the query shape is vector search followed by graph expansion in the same engine.
Local benchmark (67,280 nodes, 40,921 edges, 67,298 embeddings, HNSW CPU-only index):
| Workload | Transport | Throughput | Mean | P50 | P95 | P99 | Max |
|---|---|---|---|---|---|---|---|
| Vector only | HTTP | 19,342 req/s | 511 us | 470 us | 750 us | 869 us | 1.02 ms |
| Vector only | Bolt | 22,309 req/s | 444 us | 428 us | 629 us | 814 us | 968 us |
| Vector + 1 hop | HTTP | 11,523 req/s | 859 us | 699 us | 1.54 ms | 3.46 ms | 4.71 ms |
| Vector + 1 hop | Bolt | 13,291 req/s | 747 us | 637 us | 1.29 ms | 3.24 ms | 4.47 ms |
Remote benchmark (GCP, 8 vCPU, 32 GB RAM):
- Vector only: ~110.7 ms P50
- Vector + 1 hop: ~112.9 ms P50
- The delta between local and remote matched network RTT closely enough that end-to-end latency was network-bound rather than compute-bound.
This point is: once vector search plus one-hop traversal stays in low single-digit milliseconds locally, the bottleneck shifts from retrieval logic to deployment topology.
See the hybrid retrieval benchmark write-up for methodology, caveats, and reproduction queries, and see Graph-RAG: NornicDB vs Typical for the architectural implications.
🔬 Academic Validation: UCLouvain Case Study
NornicDB is currently being utilized by researchers at UCLouvain to map large-scale Cyber-Physical Systems (CPS).
In benchmarks performing Automata Learning (L*)—a high-iteration logic process where an LLM acts as a "Deterministic Teacher" or Oracle—NornicDB outperformed industry-standard graph databases by a significant margin:
- Efficiency: 2.2x Faster than Neo4j in total execution time for formal logic mapping.
- Throughput: Successfully handled 1,443 state-transition queries in ~32 seconds (Avg 22.69ms per full reasoning loop).
| DATABASE | CALLS | AVG TIME (ms) | TOTAL (s) |
|---|---|---|---|
| NornicDB | 1443 | 22.69 | 32.74 |
| Neo4j | 1443 | 50.20 | 72.43 |
What Recent Deep-Dives Show
- Hybrid execution model (streaming fast paths + general engine): NornicDB uses shape-specialized streaming executors for common traversal/aggregation patterns while retaining a general Cypher path for coverage and correctness.
- Scannerless recursive-descent (SRD) parser by default: the
nornicparser scans the raw query text with no lexer and no parse tree — clause boundaries and precedence are found by scanning for top-level keywords and operators — so hot-path routing is allocation-free. Theantlrparser remains for strict parsing and diagnostics. - Shared Cypher 5 / 25 grammar:
LET,FILTER, andFORreading clauses execute in the existing pipeline with an optionalCYPHER 5/CYPHER 25header. The SRD parser accepts them without a header; the ANTLR parser requiresCYPHER 25for them and parses the header itself. - HNSW build acceleration from insertion-order optimization: BM25-seeded insertion order reduced a 1M embedding build from ~27 minutes to ~10 minutes (~2.7x) in published tests by reducing traversal waste during construction, without changing core quality knobs.
- Shared seed strategy across indexing stages: the same lexical seed extraction supports HNSW insertion ordering and improves k-means centroid initialization spread for vector pipeline efficiency.
Read more:
More Setup Options
Docker (Recommended)
# Apple Silicon (includes bge-m3 embedding model)
docker run -d --name nornicdb \
-p 7474:7474 -p 7687:7687 \
-v nornicdb-data:/data \
timothyswt/nornicdb-arm64-metal-bge:latest # Apple Silicon
# timothyswt/nornicdb-amd64-cuda-bge:latest # NVIDIA GPU
Open http://localhost:7474 for the admin UI.
Need a different image/profile (Heimdall, BYOM, CPU-only, Vulkan, headless)?
From Source
git clone https://github.com/orneryd/NornicDB.git
cd NornicDB
go build -o nornicdb ./cmd/nornicdb
./nornicdb serve
Connect
Use any Neo4j driver — Python, JavaScript, Go, Java, .NET:
from neo4j import GraphDatabase
driver = GraphDatabase.driver("bolt://localhost:7687")
with driver.session() as session:
session.run("CREATE (n:Memory {content: 'Hello NornicDB'})")
Why Switch from Neo4j?
- 99.8% lower overall mean query latency on the current 48k-product / 48k-order Northwind comparison (413.40x ratio), with matching result fingerprints.
- Measured retrieval quality on the official 300-query BEIR SciFact test set, including 0.72292 nDCG@10 with native BGE-M3 reranking.
- Native graph + vector in one engine (no separate vector sidecar required).
- GPU acceleration paths (Metal/CUDA/Vulkan) for semantic + graph workloads.
- Drop-in compatibility via Bolt + Cypher for existing applications.
- Canonical graph ledger model for temporal validity, tritemporal fact modeling, as-of reads, and audit-oriented mutation tracking.
🚚 Migrating? Neo4j → NornicDB skill · runnable Python/Go/Node scripts in
scripts/migration/neo4j/.
Why Switch from Qdrant?
- Graph + vector in one engine: combine semantic retrieval with native graph traversal and Cypher queries.
- Qdrant gRPC compatibility preserved: keep Qdrant-style gRPC workflows while adding graph-native capabilities.
- Hybrid retrieval built in: vector + BM25 fusion and optional reranking in the same query pipeline.
- Canonical truth modeling: versioned facts, temporal validity windows, tritemporal facts, and as-of reads for governance-heavy use cases.
- Protocol flexibility: use REST, GraphQL, Bolt/Cypher, Qdrant-compatible gRPC, and additive Nornic gRPC on one platform.
🚚 Migrating? Qdrant → NornicDB skill · gRPC surface skill · runnable Python/Go/Node scripts in
scripts/migration/qdrant/.
Features
Retention Policies
Retention policy enforcement is available, but it is disabled by default and must be explicitly enabled. When retention is off, NornicDB does not create the retention manager and does not start the retention sweep background worker. When enabled, retention supports label-aware policy evaluation, legal holds, GDPR erasure tracking, and admin APIs.
See Retention Policies and Configuration.
🔌 Neo4j Compatible
Designed to work with existing Neo4j drivers and Bolt/Cypher workflows, with minimal or no application changes for supported query shapes.
- Bolt Protocol — Use official Neo4j drivers
- Cypher Queries — Full query language support
- Cypher 25 —
LET,FILTERandFORreading clauses with the optionalCYPHER 5/CYPHER 25header - Schema Management — Constraints, indexes (single- and multi-property), vector indexes
- Qdrant gRPC API Compatible — Works with Qdrant-style gRPC vector workflows
🤖 Agent skill: Bolt Client — connection defaults, retry classification, MERGE under concurrent writers, batch sizing.
🧠 Knowledge-Layer Scoring
Profile-driven decay and promotion scoring with the Ebbinghaus-Roynard four-layer decomposition. The engine does not hardcode cognitive tiers. Operators model their own labels and lifecycle rules using Cypher DDL.
Typical deployments map the four-layer decomposition onto labels such as:
- Knowledge: durable fact labels using
NO DECAYor neutral profiles - Memory: episodic/session labels using bounded half-life decay
- Wisdom: stable directive labels using conservative decay plus promotion rules
- Evidence/links: edge types with their own decay and suppression behavior
Those categories are conventions, not built-in engine classes. NornicDB provides the authoring and diagnostics surface:
CREATE/ALTER/DROP/SHOW DECAY PROFILECREATE/ALTER/DROP/SHOW PROMOTION PROFILECREATE/ALTER/DROP/SHOW PROMOTION POLICYdecayScore(entity),decay(entity),policy(entity),reveal(entity)CALL kp.info|profiles|policies|resolve|deindexStatus()
CREATE DECAY PROFILE working_memory OPTIONS {
halfLifeSeconds: 604800,
function: 'exponential',
visibilityThreshold: 0.10
}
CREATE DECAY PROFILE session_retention
FOR (n:SessionRecord)
APPLY {
DECAY PROFILE 'working_memory'
n.tenantId NO DECAY
}
MATCH (n:SessionRecord) WHERE decayScore(n) > 0.5
RETURN n ORDER BY decayScore(n) DESC
📖 Deep dive: Knowledge-Layer Policies, Decay Profiles, Promotion Policies, and Ebbinghaus-Roynard Bootstrap.
🤖 Agent skills: Knowledge Policies · Decay Tuning · Promotion Policies
🔗 Auto-Relationships
NornicDB weaves connections automatically:
- Embedding Similarity — Related concepts link together
- Co-access Patterns — Frequently queried pairs connect
- Temporal Proximity — Same-session nodes associate
- Transitive Inference — A→B + B→C suggests A→C
🎯 Vector Search
Native semantic search with GPU acceleration and hybrid retrieval support.
📖 Deep dive: Vector Search Guide and Qdrant gRPC Endpoint.
🤖 Agent skills: Vector & Full-Text Search · Managed Embeddings · RAG Procedures
Cypher (Neo4j-compatible):
CALL db.index.vector.queryNodes('embeddings', 10, 'machine learning guide')
YIELD node, score
RETURN node.content, score
Hybrid search (REST):
curl -X POST http://localhost:7474/nornicdb/search \
-H "Content-Type: application/json" \
-d '{"query": "machine learning", "limit": 10}'
More API entry points:
- GraphQL hybrid search:
POST /graphqlwithsearch(query, options) - gRPC (Qdrant-compatible):
Points.Search/Points.Query(Document.text) - Nornic native gRPC:
NornicSearch/SearchText(additive client) - See
docs/user-guides/nornic-search-grpc.mdfor additive proto setup without forking Qdrant drivers.
🤖 Heimdall AI Assistant
Built-in AI that understands your database.
# Enable Heimdall
NORNICDB_HEIMDALL_ENABLED=true ./nornicdb serve
Natural Language Queries:
- "Get the database status"
- "Show me system metrics"
- "Run health check"
Plugin System:
- Create custom actions the AI can execute
- Lifecycle hooks (PrePrompt, PreExecute, PostExecute)
- Database event monitoring for autonomous actions
- Inline notifications with proper ordering
See Heimdall AI Assistant Guide and Plugin Development.
🧩 APOC Functions
950+ built-in functions for text, math, collections, and more. Plus a plugin system for custom extensions.
// Text processing
RETURN apoc.text.camelCase('hello world') // "helloWorld"
RETURN apoc.text.slugify('Hello World!') // "hello-world"
// Machine learning
RETURN apoc.ml.sigmoid(0) // 0.5
RETURN apoc.ml.cosineSimilarity([1,0], [0,1]) // 0.0
// Collections
RETURN apoc.coll.sum([1, 2, 3, 4, 5]) // 15
Drop custom .so plugins into /app/plugins/ for automatic loading. See the APOC Plugin Guide.
Docker Images
All images available at Docker Hub.
ARM64 (Apple Silicon)
| Image | Size | Description |
|---|---|---|
timothyswt/nornicdb-arm64-metal-bge-heimdall | 1.1 GB | Full - Embeddings + AI Assistant |
timothyswt/nornicdb-arm64-metal-bge | 586 MB | Standard - With BGE-M3 embeddings |
timothyswt/nornicdb-arm64-metal | 148 MB | Minimal - Core database, BYOM |
timothyswt/nornicdb-arm64-metal-headless | 148 MB | Headless - API only, no UI |
AMD64 (Linux/Intel)
| Image | Size | Description |
|---|---|---|
timothyswt/nornicdb-amd64-cuda-bge | ~4.5 GB | GPU + Embeddings - CUDA + BGE-M3 |
timothyswt/nornicdb-amd64-cuda | ~3 GB | GPU - CUDA acceleration, BYOM |
timothyswt/nornicdb-amd64-cuda-headless | ~2.9 GB | GPU Headless - API only |
timothyswt/nornicdb-amd64-cpu | ~500 MB | CPU - No GPU required |
timothyswt/nornicdb-amd64-cpu-headless | ~500 MB | CPU Headless - API only |
BYOM = Bring Your Own Model (mount at /app/models)
# With your own model
docker run -d -p 7474:7474 -p 7687:7687 \
-v /path/to/models:/app/models \
timothyswt/nornicdb-arm64-metal:latest
# Headless mode (API only, no web UI)
docker run -d -p 7474:7474 -p 7687:7687 \
-v nornicdb-data:/data \
timothyswt/nornicdb-arm64-metal-headless:latest
Headless Mode
For embedded deployments, microservices, or server-only use cases, NornicDB supports headless mode, which disables embedded UI assets, SPA/bootstrap routes, and browser IDEs while keeping core APIs available.
Runtime flag:
nornicdb serve --headless
Environment variable:
NORNICDB_HEADLESS=true nornicdb serve
Build without UI (smaller binary):
# Native build
make build-headless
# Docker build
docker build --build-arg HEADLESS=true -f docker/Dockerfile.arm64-metal .
Configuration
# nornicdb.yaml
server:
bolt_port: 7687
http_port: 7474
host: localhost
database:
data_dir: ./data
async_writes_enabled: true
async_flush_interval: 50ms
async_max_node_cache_size: 50000
async_max_edge_cache_size: 100000
embedding:
enabled: true
provider: local # or ollama, openai
model: bge-m3.gguf
url: ""
dimensions: 1024
embedding_worker:
chunk_size: 8192
chunk_overlap: 50
memory:
decay_enabled: true
decay_interval: 3600
auto_links_enabled: true
auto_links_similarity_threshold: 0.82
Use Cases
- AI Agent Memory — Persistent, queryable memory for LLM agents
- Knowledge Graphs — Auto-organizing knowledge bases
- RAG Systems — Vector + graph retrieval in one database
- Graph-RAG for LLM Inference — Simplify retrieval pipelines by combining graph traversal, hybrid search, and provenance in one engine
- Session Context — Decaying conversation history
- Research Tools — Connect papers, notes, and insights
- Canonical Truth Stores — Versioned facts, temporal validity, and append-only mutation history in a graph model
- Financial Systems — Loan/risk state reconstruction with as-of reads and audit receipts
- Compliance & RegTech — KYC/AML state changes, policy/rule versioning, and non-overlapping validity enforcement
- Audit Platforms — Correlate graph mutations to WAL sequence ranges and receipt hashes
- AI Governance & Lineage — Track model assertions, overrides, and fact provenance over time
Documentation
Start with the docs hub for role/task navigation, then use the issue index for symptom-first troubleshooting:
- Public documentation site: https://orneryd.github.io/NornicDB/
- Documentation Hub
- Issue Index
| Guide | Description |
|---|---|
| Getting Started | Installation & quick start |
| Docker Image Quick Reference | Full runtime image matrix |
| Hot-Path Cypher Cookbook | Proven query shapes for fast latency |
| Agent Skills | Claude/agent skill files for the Cypher surface |
| API Reference | Cypher functions & procedures |
| User Guides | Complete examples & patterns |
| Performance | Benchmarks vs Neo4j |
| Neo4j Migration | Compatibility & feature parity |
| Migration Scripts | Runnable Neo4j and Qdrant → NornicDB migrations (Python, Go, Node) |
| Architecture | System design & internals |
| Docker Guide | Build & deployment |
| Development | Contributing & development |
Additional deep dives referenced above:
- Hybrid query benchmarks
- Canonical graph ledger
- Historical reads and MVCC retention
- Cypher parser modes
Comparison
| Platform | Category | Query Language Support (and protocol) | Native Vector Search | Canonical Graph + Temporal Ledger Pattern | Queryable Mutation Log + Receipts | Embedded/Self-Hosted Focus |
|---|---|---|---|---|---|---|
| NornicDB | Graph + Vector + Canonical Ledger | Cypher via Bolt; also HTTP/GraphQL and gRPC (Qdrant-compatible + NornicSearch) | Yes | Yes | Yes | Yes |
| Neo4j | Graph DB | Cypher via Bolt/HTTP | Yes | Partial (manual modeling) | Partial (logs exist, not first-class receipts model) | Server-first |
| Memgraph | Graph DB | openCypher via Bolt/HTTP | Partial/varies by setup | Partial (manual) | Partial (manual/integration) | Server-first |
| TigerGraph | Graph analytics DB | GSQL via REST++/native endpoints | Partial/extension-driven | Partial (manual) | Partial (manual/integration) | Server-first |
| Qdrant | Vector DB | Qdrant query/filter API via gRPC/REST | Yes | No (not graph-native) | No | Server-first |
| Weaviate | Vector DB | GraphQL + REST APIs | Yes | Partial (knowledge graph features, not Cypher property graph) | No | Server-first |
| Amazon QLDB | Ledger DB | PartiQL via AWS API/SDK | No | Partial (ledger + temporal history, not graph-native) | Yes (ledger-native) | Managed service |
Snapshot is capability-oriented and high-level; exact behavior depends on edition/configuration and workload design.
Building
Native Binary
# Basic build
make build
# Headless (no UI)
make build-headless
# With local LLM support
make build-localllm
Docker Images
# Download models for Heimdall builds (automatic if missing)
make download-models # BGE-M3 + qwen3-0.6b (~750MB)
make check-models # Verify models present
# ARM64 (Apple Silicon)
make build-arm64-metal # Base (BYOM)
make build-arm64-metal-bge # With BGE embeddings
make build-arm64-metal-bge-heimdall # With BGE + Heimdall AI
make build-arm64-metal-headless # Headless (no UI)
# AMD64 CUDA (NVIDIA GPU)
make build-amd64-cuda # Base (BYOM)
make build-amd64-cuda-bge # With BGE embeddings
make build-amd64-cuda-bge-heimdall # With BGE + Heimdall AI
make build-amd64-cuda-headless # Headless (no UI)
# AMD64 CPU-only
make build-amd64-cpu # Minimal
make build-amd64-cpu-headless # Minimal headless
# Build all variants for your architecture
make build-all
# Deploy to registry
make deploy-all # Build + push all variants
Cross-Compilation
# Build for other platforms from macOS
make cross-linux-amd64 # Linux x86_64
make cross-linux-arm64 # Linux ARM64
make cross-rpi # Raspberry Pi 4/5
make cross-windows # Windows (CPU-only)
make cross-all # All platforms
Roadmap
Completed
- Neo4j Bolt protocol
- Configurable RBAC and oAuth support
- Cypher query engine (52 functions)
- Cypher 25 shared grammar foundation —
LET,FILTER,FORreading clauses and theCYPHER 5/CYPHER 25header - Correctly-rounded math — musl
libmports forexp/log/powand trigonometry - MCP database pinning —
/mcp/{database}targets one database for every tool call - Memory decay system
- GPU acceleration (Metal, CUDA)
- Vector & full-text search
- Auto-relationship engine
- HNSW vector index
- Metadata/Property Indexing (single- and multi-property)
- SIMD Implementation
- Clustering support
- Sharding (Composite DB + Remote Constituents)
- Data Explorer UI (Browser query editor, semantic search, node details)
- GDPR Compliance
- per-DB Search Index Overrides for BM2 and HNSW as independently levers for deferred or skipped construction (
docs/plans/okf-admin-import-export-plan.md) - Bulk Import Tool
- Cross-platform GPU-assisted HNSW construction with CPU-serving persistence parity (
docs/plans/archive/gpu-hnsw-construction-plan.md) - Production message localization (message catalog, all core phases complete) (
docs/plans/archive/localization-consolidation-plan.md)
Planned (from docs/plans)
- Neo4j-compatible end-to-end streaming execution + wrapper driver/ORM (
docs/plans/neo4j-compatible-streaming-driver-and-server-plan.md) - UI enhancement backlog (search/config/admin UX improvements) (
docs/plans/ui-enhancements.md) - Fine-grained RBAC: security administration commands and graph privileges, including property-based rules (#935)
- User impersonation:
IMPERSONATEprivilege and Boltimp_user(#936) - Change Data Capture:
txLogEnrichment,db.cdc.*procedures and change events (#937) - Query API v2 (typed JSON transactions, bookmarks, impersonated user)
- Full Cypher 25 conformance beyond the shared grammar foundation (
docs/plans/cypher-convergence-plan.md)
Contributors
Special thanks to everyone who helps make NornicDB better. See CONTRIBUTORS.md for a list of community contributors.
License
MIT License — See LICENSE.md for details.
Patent rights are handled via a defensive non-assertion grant in PATENTS.md. This keeps the project open for broad use (including commercial use) while adding patent retaliation protection.
See NOTICES.md for third-party license information, including bundled AI models (BGE-M3, Qwen2.5) and dependencies.