A factual comparison of TerminusDB and Neo4j for developers evaluating graph databases. Both are graph databases, but they serve different use cases with fundamentally different architectures.
Executive summary
Neo4j is a property graph database optimised for real-time graph traversal at scale — social networks, recommendation engines, fraud detection. It uses the Cypher query language and stores data as labeled nodes with typed relationships.
TerminusDB is a document graph database with built-in version control — it stores JSON documents in a schema-enforced graph, tracks every change as an immutable commit, and supports branch, diff, merge, and time-travel. It uses the WOQL datalog engine for queries.
The key architectural difference: Neo4j is a mutable database designed for high-throughput real-time queries. TerminusDB is an immutable database designed for collaborative data workflows with full audit history.
Comparison table
| Aspect | TerminusDB | Neo4j |
|---|---|---|
| Data model | JSON documents decomposed into RDF triples | Property graph (nodes + relationships + properties) |
| Schema | Enforced on every transaction (closed-world) | Optional constraints (open-world by default) |
| Query language | WOQL (Datalog with unification) | Cypher (declarative pattern matching) |
| Version control | Built-in: branch, merge, diff, time-travel | Not built-in (requires external tooling) |
| Immutability | Append-only delta layers, never mutates | Mutable in-place updates |
| ACID transactions | Full ACID with snapshot isolation | Full ACID |
| Collaboration | Clone, push, pull between instances | Clustering for HA, no data-level collaboration |
| Scalability model | Single-node with delta compression | Clustering (Enterprise), sharding (Aura) |
| Deployment | Docker container, ~120 MB | JVM-based, requires Java runtime |
| Licence | Apache 2.0 | GPL (Community) / Commercial (Enterprise) |
| Primary interface | HTTP REST API + client libraries | Bolt protocol + HTTP + client drivers |
| Graph traversal | WOQL path() expressions | Cypher variable-length patterns |
| Audit trail | Every commit has author, message, timestamp | Requires custom implementation |
| Schema migration | Schema weakening (backward-compatible only) | Manual migration scripts |
Data model
Neo4j: property graph
Neo4j stores data as nodes (entities) connected by relationships (edges). Both nodes and relationships carry properties (key-value pairs) and labels (type tags).
CREATE (p:Person {name: "Alice", age: 30})
CREATE (c:City {name: "London"})
CREATE (p)-[:LIVES_IN {since: 2020}]->(c)The property graph model is intuitive for developers coming from object-oriented backgrounds — entities feel like objects, relationships feel like pointers.
TerminusDB: document graph
TerminusDB stores data as JSON documents that are decomposed into a typed graph of triples. The schema defines document types and their relationships:
{"@type": "Person", "name": "Alice", "age": 30, "lives_in": "City/London"}Under the hood, this becomes RDF triples that can be traversed with WOQL. You interact with JSON documents; the graph is the engine:
WOQL.and(
WOQL.triple("v:Person", "rdf:type", "@schema:Person"),
WOQL.triple("v:Person", "name", "v:Name"),
WOQL.triple("v:Person", "lives_in", "v:City"),
WOQL.triple("v:City", "name", "v:CityName")
)Query language
Cypher (Neo4j)
Cypher uses ASCII-art patterns that visually resemble the graph structure:
MATCH (p:Person)-[:LIVES_IN]->(c:City)
WHERE c.name = "London"
RETURN p.name, p.ageCypher excels at expressing graph patterns intuitively. Variable-length path matching (*1..5) handles recursive traversal concisely.
WOQL (TerminusDB)
WOQL uses Datalog-style pattern matching with unification:
WOQL.and(
WOQL.triple("v:Person", "lives_in", "v:City"),
WOQL.triple("v:City", "name", WOQL.string("London")),
WOQL.triple("v:Person", "name", "v:Name"),
WOQL.triple("v:Person", "age", "v:Age")
)WOQL's strength is composability — queries are programs that can be nested, abstracted, and combined. The path() operator handles recursive traversal.
Version control
This is where the databases diverge most significantly.
TerminusDB: git for data
Every write in TerminusDB creates an immutable commit. You can:
- Branch — create isolated workspaces for changes
- Diff — compare any two states at the field level
- Merge — apply changes from one branch to another
- Time-travel — query the database at any historical commit
- Clone — replicate databases between instances
This enables collaborative data workflows: multiple teams work on branches, review changes via diff, and merge when ready — exactly like Git for code.
Neo4j: no built-in version control
Neo4j mutates data in place. To achieve version control, you would need to:
- Build a custom changelog system
- Use external tools (e.g., Liquigraph for schema changes)
- Implement your own branch/merge logic at the application layer
For use cases that need audit trails or collaborative editing, this is significant additional engineering work.
Schema enforcement
TerminusDB: closed-world assumption
TerminusDB enforces schema on every transaction. You cannot insert a document that violates its class definition. This provides strong guarantees:
- Every document conforms to its type
- Relationships are typed and validated
- Schema changes follow the weakening principle (backward-compatible only)
Neo4j: open-world by default
Neo4j is schema-optional. You can add constraints (uniqueness, existence, node key) but the graph is open-world by default — any node can have any property, any label combination.
Neo4j 5+ added type constraints and property type constraints, but enforcement is opt-in rather than default.
When to choose Neo4j
- Real-time recommendation engines — Neo4j's query planner is optimised for low-latency traversal at scale
- Social network analysis — finding shortest paths, community detection, influence scoring
- Fraud detection — pattern matching across transaction networks in real time
- Large-scale graph analytics — when you need graph algorithms (PageRank, betweenness centrality)
- Existing Cypher expertise — large ecosystem of tools, connectors, and community resources
- Clustering requirements — Neo4j Enterprise provides multi-node clusters for HA
When to choose TerminusDB
- Collaborative data workflows — teams editing shared datasets with branch/merge workflows
- Regulated industries — finance, healthcare, compliance where full audit trail is mandatory
- Schema-first development — when you want the database to enforce data integrity, not the application
- Content versioning — knowledge bases, documentation, reference data that evolve over time
- Data lineage and compliance — proving what changed, when, and by whom
- Lightweight deployment — single Docker container, no JVM, minimal infrastructure
- Distributed data collaboration — clone and sync between instances (edge computing, partner data sharing)
Worked example: tracking product changes
Suppose you need to track product catalogue changes with full history and review workflow.
In Neo4j
You would need to model versioning explicitly:
CREATE (p:Product {id: "widget-1", name: "Widget", price: 9.99, version: 1})
CREATE (p)-[:SUPERSEDED_BY]->(:Product {id: "widget-1", name: "Widget Pro", price: 14.99, version: 2})History, diff, and rollback become application-level concerns.
In TerminusDB
Version control is built in:
# Create a branch for the price change
curl -X POST http://localhost:6363/api/branch/admin/catalogue/local/branch/price-update \
-d '{"origin": "admin/catalogue/local/branch/main"}'
# Update the product on the branch
curl -X PUT "http://localhost:6363/api/document/admin/catalogue/local/branch/price-update?author=alice&message=Update+widget+price" \
-d '{"@id": "Product/widget-1", "@type": "Product", "name": "Widget Pro", "price": 14.99}'
# See exactly what changed
curl -X POST http://localhost:6363/api/diff/admin/catalogue \
-d '{"before_data_version": "main", "after_data_version": "price-update"}'
# Merge when approved
curl -X POST http://localhost:6363/api/apply/admin/catalogue/local/branch/main \
-d '{"before_commit": "main", "after_commit": "price-update", "commit_info": {"author": "alice", "message": "Merge price update"}}'The full history is preserved. You can time-travel to see the product at any point. Diff shows exactly what changed. No application-level versioning code required.
Summary
Neo4j and TerminusDB are both graph databases, but optimised for different problems:
- Neo4j excels at real-time graph traversal, analytics, and pattern matching at scale
- TerminusDB excels at collaborative, auditable data workflows with built-in version control
They are not direct substitutes — they serve different architectural needs. Choose based on whether your primary challenge is querying complex relationships in real time (Neo4j) or managing evolving data with history and collaboration (TerminusDB).