Neo4j vs NornicDB Feature Audit
Historical compatibility audit
Last Updated: December 2025 (historical snapshot)
This audit is a December 2025 snapshot of the v0.1.x surface. The current function, procedure, and plugin capability boundaries are maintained in APOC Functions, the APOC procedure capability audit, and SHOW FUNCTIONS / SHOW PROCEDURES; remaining gaps are tracked in #1318.
Scope: Production workloads excluding plugins and multi-database orchestration.
Executive Summary
The December 2025 audit recorded the following estimates. These percentages are historical measurements, not current compatibility guarantees:
| Category | Status | Notes |
|---|---|---|
| Core Data Model | 100% | Nodes, relationships, properties, arrays, maps |
| Cypher Language | 100% | Implemented clauses, pattern matching, and subqueries; consult the compatibility guide for limits |
| Functions | 109% | Dec 2025 measurement: 147 functions vs Neo4j's 135. Current built-in surface: SHOW FUNCTIONS; APOC surface: APOC Functions |
| Indexes | 100% | B-tree, full-text, vector, composite, range |
| Constraints | 100% | UNIQUE, EXISTS, NODE KEY, RELATIONSHIP KEY, property type (nodes + relationships) + temporal no-overlap, domain/enum, cardinality, endpoint policy extensions |
| Transactions | 100% | Transactions with BEGIN/COMMIT/ROLLBACK; durability depends on configured sync policy |
| Built-in Procedures | 100% | Dec 2025 measurement: 41 procedures (34 db._ + 7 dbms._). Current surface: SHOW PROCEDURES |
| APOC | Partial | Dec 2025 measurement: 960+. Current: APOC Functions and the procedure capability audit; remaining gaps tracked in #1318 |
| Protocol/Drivers | 95% | Bolt v4.x, all major drivers |
New in 0.1.4:
- String query auto-embedding in
db.index.vector.queryNodes - Multi-line SET with arrays support
- Server-side query embedding
Feature Parity Scorecard
| Category | Weight | Score | Weighted |
|---|---|---|---|
| Core Data Model | 20% | 100% | 20.0 |
| Cypher Language | 20% | 100% | 20.0 |
| Functions | 10% | 109% | 10.9 |
| Indexes | 10% | 100% | 10.0 |
| Constraints | 10% | 100% | 10.0 |
| Transactions | 15% | 100% | 15.0 |
| Procedures | 10% | 60% | 6.0 |
| Protocol/Drivers | 5% | 95% | 4.75 |
| TOTAL | 100% | 96.65% | 96.65% |
Completed Features
1. Core Data Model - 100%
All 12 features fully implemented: node/relationship creation, multiple labels, all property types (string, int, float, bool, arrays, maps), ID persistence, directed relationships, self-relationships, parallel edges.
2. Cypher Query Language - 100%
Core Clauses (16/16): MATCH, OPTIONAL MATCH, WHERE, RETURN, WITH, CREATE, MERGE, DELETE, DETACH DELETE, SET, REMOVE, ORDER BY, LIMIT, SKIP, UNWIND, UNION/UNION ALL
Pattern Matching (8/8): Fixed-length paths, variable-length paths (bounded/unbounded), shortestPath, allShortestPaths, relationship type filtering, bidirectional matching, named paths
Advanced Features (7/7): List comprehension, pattern comprehension, CASE expressions, map projection, EXISTS subqueries, COUNT subqueries with comparisons
3. Functions - 109% (Dec 2025: 147 vs 135)
| Category | Count | Status |
|---|---|---|
| String | 23 | 100% |
| List | 17 | 100% |
| Mathematical | 24 | 126% (exceeds Neo4j's 19) |
| Trigonometric | 11 | 100% |
| Aggregation | 12 | 133% (exceeds Neo4j's 9) |
| Temporal | 25 | 100% |
| Spatial | 19 | 127% |
| Type Conversion | 12 | 100% |
| Node/Relationship | 12 | 100% |
| Vector/Similarity | 3 | 100% |
4. Indexes - 100%
All index types supported: B-tree, full-text (Lucene-compatible), vector (HNSW), composite (multi-property), token lookup, range indexes. Full CRUD operations including CREATE INDEX, DROP INDEX, SHOW INDEXES, index hints.
5. Constraints & Schema - 100%
Full Neo4j constraint parity on both nodes and relationships:
Node constraints: UNIQUE (single and composite), EXISTS (IS NOT NULL), NODE KEY (composite uniqueness + existence), property type (IS :: TYPE).
Relationship constraints: UNIQUE (single and composite), EXISTS (IS NOT NULL), RELATIONSHIP KEY (composite uniqueness + existence), property type (IS :: TYPE). Uniqueness and key constraints on relationships automatically create owned backing indexes.
NornicDB extensions: Temporal no-overlap (IS TEMPORAL NO OVERLAP) prevents overlapping time intervals on nodes or relationships grouped by a composite key. Domain/enum (IN ['val1', 'val2']) restricts a property to a fixed set of allowed values on nodes or relationships. Cardinality (REQUIRE MAX COUNT N) limits outgoing or incoming edge count per node for a given relationship type, with direction encoded in the FOR clause arrows (FOR ()-[r:TYPE]->() for outgoing, FOR ()<-[r:TYPE]-() for incoming). Endpoint policies (REQUIRE ALLOWED / REQUIRE DISALLOWED) restrict which label pairs may be connected by a relationship type; ALLOWED policies form a union whitelist and DISALLOWED policies are a blacklist with precedence.
All constraint DDL supports IF NOT EXISTS for idempotent creation. Constraints are validated against existing data at creation time and enforced on all write paths (CREATE, MERGE, SET, REMOVE) including transactions and bulk operations. Label mutations (SET n:Label, REMOVE n:Label) are also validated against endpoint policy constraints. SHOW CONSTRAINTS reports entity type (NODE or RELATIONSHIP), constraint type, owned backing indexes, and additional columns for cardinality (direction, maxCount) and policy (sourceLabel, targetLabel, policyMode) constraints. Block-style constraint contracts are exposed separately via SHOW CONSTRAINT CONTRACTS.
6. Transactions - 100%
Transaction behavior through native storage; see durability boundaries:
- Atomicity: All operations commit together or none
- Consistency: Constraint validation before commit
- Isolation: Snapshot isolation via MVCC at the storage transaction layer, including read-your-writes and write-write conflict detection at commit
- Durability: WAL-based recovery with configurable sync/acknowledgement boundaries
Supports: BEGIN/COMMIT/ROLLBACK, implicit transactions, automatic rollback on error, transaction metadata.
7. Protocol & Drivers - 95%
| Driver | Status |
|---|---|
| Python (neo4j-driver) | Full |
| JavaScript/TypeScript | Full |
| Go (neo4j-go-driver) | Full |
| Java (neo4j-java-driver) | Full |
| .NET, Ruby | Untested (should work) |
Bolt v4.x fully supported. v5.x backward compatible.
Built-in Procedures (18+ Implemented)
db.* Procedures
db.labels, db.propertyKeys, db.relationshipTypes, db.info, db.ping
db.index.vector.queryNodes, db.index.vector.createNodeIndex
db.index.vector.queryRelationships
db.index.fulltext.queryNodes, db.index.fulltext.queryRelationships
db.index.fulltext.listAvailableAnalyzers
db.awaitIndex, db.awaitIndexes, db.resampleIndex
db.stats.clear/collect/retrieve/status/stop
db.clearQueryCaches
db.create.setNodeVectorProperty, db.create.setRelationshipVectorPropertydbms.* Procedures
dbms.info, dbms.listConfig, dbms.clientConfig
tx.setMetaDataNEW: Vector Search Enhancements
-- String query (auto-embedded by NornicDB)
CALL db.index.vector.queryNodes('idx', 10, 'machine learning tutorial')
YIELD node, score
-- Direct vector (Neo4j compatible)
CALL db.index.vector.queryNodes('idx', 10, [0.1, 0.2, 0.3])
YIELD node, score
-- Multi-line SET with arrays (optional user metadata)
MATCH (n:Node {id: 'abc'})
SET n.embedding = [0.7, 0.2, 0.05, 0.05],
n.embedding_model = 'mxbai-embed-large',
n.has_embedding = trueNote: NornicDB-managed embedding metadata is stored internally (not in
Properties) to avoid property namespace pollution.
APOC Procedures (52 Implemented)
Core Utilities
| Category | Functions |
|---|---|
| Path/Graph | apoc.path.subgraphNodes, apoc.path.expand, apoc.path.spanningTree |
| Map | merge, setKey, removeKey, removeKeys, fromPairs, fromLists, clean |
| Collection | flatten, toSet, sum, avg, min, max, sort, reverse, union, unionAll, intersection, subtract, contains, containsAll |
| Text | apoc.text.join |
| Conversion | toJson, fromJsonMap, fromJsonList |
| Meta | apoc.meta.type, apoc.meta.isType |
| UUID | apoc.create.uuid |
Dynamic Cypher
CALL apoc.cypher.run('MATCH (n) RETURN count(n)', {})
CALL apoc.cypher.runMany('CREATE (n); MATCH (n) RETURN n', {})Batch Processing
CALL apoc.periodic.iterate(
'MATCH (n:Node) RETURN n',
'SET n.processed = true',
{batchSize: 1000}
)Graph Algorithms
| Algorithm | Procedure | Status |
|---|---|---|
| Dijkstra | apoc.algo.dijkstra | APOC name |
| A* | apoc.algo.aStar | APOC name |
| All Simple Paths | apoc.algo.allSimplePaths | APOC name |
| PageRank | apoc.algo.pageRank | NornicDB extension (GDS: gds.pageRank.stream) |
| Betweenness | apoc.algo.betweenness | NornicDB extension (GDS: gds.betweenness.stream) |
| Closeness | apoc.algo.closeness | NornicDB extension (GDS: gds.closeness.stream) |
| Neighbors | apoc.neighbors.tohop, apoc.neighbors.byhop | APOC names |
Community Detection
| Algorithm | Procedure | Status |
|---|---|---|
| Louvain | apoc.algo.louvain | NornicDB extension (GDS: gds.louvain.stream) |
| Label Propagation | apoc.algo.labelPropagation | NornicDB extension (GDS: gds.labelPropagation.stream) |
| Connected Components | apoc.algo.wcc | NornicDB extension (GDS: gds.wcc.stream) |
A NornicDB extension isn't in APOC or GDS: a query that uses it runs only on NornicDB (see NornicDB extensions).
Graph Data Science (GDS)
These GDS names work as in GDS 2.13 (Neo4j 5.26), with its parameters, columns, values and error messages:
| Area | Names |
|---|---|
| Graph catalog | gds.graph.project (label / type projections, with orientation, properties, aggregation and the configuration map), gds.graph.list, gds.graph.drop, gds.graph.exists (procedure and function); one catalog per database |
| FastRP | gds.fastRP.stream, gds.fastRP.stats |
| Link prediction | gds.alpha.linkprediction.adamicAdar, commonNeighbors, preferentialAttachment, resourceAllocation, totalNeighbors, sameCommunity |
| Utilities | gds.util.asNode, asNodes, nodeProperty, NaN, infinity, isFinite, isInfinite, gds.version |
NornicDB's differences: nodeId is the node's id (a STRING, #1165); FastRP's randomSeed defaults to 42, so the same call gives the same embeddings, and embeddingDimension is at most 8,192; memoryUsage and sizeInBytes are reported as unmeasured ("", -1); the catalog isn't per user; concurrency and readConcurrency are accepted and change nothing (NornicDB runs these single-threaded).
Not implemented (a query using them fails with an unknown procedure or function):
- every other GDS algorithm, in any mode: centrality (
gds.pageRank,gds.betweenness,gds.closeness,gds.degree,gds.articleRank, …), community detection (gds.louvain,gds.leiden,gds.labelPropagation,gds.wcc,gds.scc,gds.triangleCount,gds.localClusteringCoefficient,gds.kmeans, …), similarity (gds.nodeSimilarity,gds.knn, …), path finding (gds.shortestPath.*,gds.allShortestPaths.*,gds.bfs,gds.dfs,gds.spanningTree, …), embeddings other than FastRP (gds.node2vec,gds.beta.graphSage,gds.hashgnn); - the
mutate,writeandestimatemodes, including FastRP's; - Cypher projections (
gds.graph.projectas an aggregation,gds.graph.project.cypher) and other catalog operations (gds.graph.filter,gds.graph.nodeProperties.*,gds.graph.relationships.*,gds.graph.sample.*, graph export); - ML pipelines and models (
gds.beta.pipeline.*,gds.model.*).
Some of these algorithms exist as NornicDB extensions under apoc.algo.* (tables above); NornicDB's own gds.linkPrediction.*.stream procedures are extensions too.
Data Import/Export
| Operation | Procedure | Status |
|---|---|---|
| Load JSON | apoc.load.json, apoc.load.jsonArray | Yes |
| Load CSV | apoc.load.csv | Yes |
| Export JSON | apoc.export.json.all, apoc.export.json.query | Yes |
| Export CSV | apoc.export.csv.all, apoc.export.csv.query | Yes |
| Import JSON | apoc.import.json | Yes |
NornicDB-Exclusive Features
Features NornicDB has that Neo4j doesn't:
| Feature | Description |
|---|---|
| Automatic Vector Index | All node embeddings indexed automatically, no setup required (with managed embeddings enabled) |
| String Query Embedding | db.index.vector.queryNodes accepts strings, auto-embeds server-side |
| Hybrid Search REST API | /nornicdb/search with RRF fusion of vector + BM25 |
| Knowledge-Layer Scoring | Declarative decay profiles and retention bindings via Cypher DDL |
| Auto-Relationships | Automatic edge creation via embedding similarity |
| GPU Acceleration | Metal/CUDA/OpenCL/Vulkan for vector ops |
| Embedded Mode | Use as library without server |
| Link Prediction | ML-based relationship prediction (TLP algorithms) |
| MCP Server | Native Model Context Protocol for LLM tools |
| Temporal No-Overlap | Prevents overlapping time intervals on nodes or relationships |
| Domain/Enum Constraints | Restricts property values to a declared set of allowed values |
| Cardinality Constraints | Limits outgoing or incoming edge count per node for a given relationship type |
| Endpoint Policies | Restricts which (source, target) label pairs may be connected by a relationship type |
Measured Performance and Resource Comparison
The current same-hardware Northwind benchmark records the following results for its 48,000-product / 48,000-order workload:
| Metric | Neo4j | NornicDB | Difference |
|---|---|---|---|
| Overall mean query latency | 98.64 ms | 0.23 ms | -99.8% (432.38x ratio) |
| Overall throughput | 7.76 ops/s | 17.70 ops/s | +128.1% (2.28x) |
| Peak system memory used | 33.4 GiB | 32.5 GiB | -2.7% |
| Total benchmark data directory | 204 MiB | 134 MiB | -34.3% |
See the full Northwind comparison for workload, hardware, correctness fingerprints, power, and storage details. Treat these as workload-specific measurements rather than universal deployment requirements.
Recently Completed
| Feature | Implementation |
|---|---|
| Bookmarks (causal consistency) | Returns nornicdb:bookmark:* on commit, accepts in BEGIN |
| String query auto-embedding | db.index.vector.queryNodes accepts text strings |
| Multi-line SET with arrays | Full support for embedding storage workflow |
| db.index.fulltext.createNodeIndex | Create fulltext indexes on node labels |
| db.index.fulltext.createRelationshipIndex | Create fulltext indexes on relationship types |
| db.index.vector.createRelationshipIndex | Create vector indexes on relationships |
| db.index.fulltext.drop | Drop fulltext indexes |
| db.index.vector.drop | Drop vector indexes |
| Prometheus /metrics endpoint | Full metrics export (requests, nodes, edges, embeddings, slow queries) |
| Slow query logging | Configurable threshold (default 100ms), file or stderr output |
Not Applicable
| Feature | Reason |
|---|---|
| Cluster management (dbms.*) | Single-node design |
| Enterprise security | Use external auth |
| Multi-database | Use separate instances |
Use Case Compatibility
Recommended (95-100% Compatible)
- LLM/AI Agent Memory (primary design target)
- Knowledge Graphs
- Semantic Search (GPU-accelerated, MMR diversification)
- Graph Analysis (shortestPath, traversals, subgraphs)
- Recommendation Engines
- Financial/Transactional (full ACID)
- Multi-tenant Systems (constraint enforcement)
- Development/Testing (fast, lightweight)
- Enterprise Monitoring (Prometheus
/metricsendpoint)
Roadmap
Recently Completed (v0.1.4)
- String query auto-embedding in vector search
- Multi-line SET with arrays
- Server-side query embedding via Cypher executor
- Prometheus /metrics endpoint
- Slow query logging (configurable threshold)
- MMR diversification for search results
- Eval harness for search quality validation
- Cross-encoder reranking for Stage 2 retrieval (local GGUF or external API: Cohere, TEI, Ollama)
Next Priority
| Task | Effort | Status |
|---|---|---|
| Prometheus metrics | 2 days | Done |
| Slow query logging | 1 day | Done |
| MMR diversification | 1 day | Done |
| Cross-encoder rerank | 3 days | Done |
| Plugin system for APOC | 3 days | Done |
| Eval harness | 2 days | Done |
Conclusion
NornicDB v0.1.4 provides production-grade Neo4j replacement capability:
- 96% overall feature parity
- 100% core data model compatibility
- 109% function parity at the December 2025 audit (147 vs Neo4j's 135); see APOC Functions for the current catalog
- Full ACID transactions
- All constraint types enforced
- Neo4j driver compatibility (Bolt v4.x)
- LLM-native features (memory decay, vector search, auto-embedding)
For LLM/AI workloads: Recommended (99% effective parity) For general Neo4j replacement: Suitable (96% feature parity)
Last Updated: December 1, 2025Previous Audit: November 27, 2025