TypeDB vs Neo4j
Graph modelling for domains that have to be right
Neo4j is a fast, flexible property graph. TypeDB is a typed graph database that models complex domains and catches mistakes as they happen. Here's how to tell which one your project needs.
- 1
- 2
- 3
- 4
match
$b isa company, has name "Acme Ltd";
$l isa loan, links (borrower: $b, guaranter: $g);
fetch { "guarantor": $g.name };- 1
- 2
- 3
MATCH (b:Company {name: "Acme Ltd"})
<-[:BORROWER]-(l:Loan)-[:GUARANTER]->(g)
RETURN g.name;Overview
Main differences from Neo4j
We typically see businesses choose TypeDB when they have large, messy domains, when they are dealing with critical systems that require accuracy, or when they want their data architecture to give them an unfair AI advantage.
Relationships with more than two sides
Neo4j edges join two nodes. TypeDB relations take any number of participants, each in a named role.
How relations work
Mistakes you can see
Neo4j accepts most writes and runs most queries by default. TypeDB checks both against your schema.
Where errors show up
A model that grows with you
TypeDB subtypes inherit from their parents, and queries pick them up. Reshaping a Neo4j relationship means migrating data.
Extending the model
Relationships
Two sides, or as many as it takes
Real relationships often involve more than two things. A purchase has a buyer, a seller, a product and a broker.
Modelling those participants directly, instead of routing them through intermediate nodes, reduces bloat in the data itself: one enterprise project reported 3x fewer facts stored for the same data in TypeDB vs. in Neo4j!
One relation connects all four, each in a named role. Relations can own attributes and play roles in other relations, so an ownership can itself be disputed.
Each edge joins two nodes, so the purchase becomes an intermediate node. What each participant's role means is a convention your queries have to follow.
Types
Labels, or a type hierarchy
Most enterprise domains have categories within categories. Two things matter: subtyping, where a query on a parent returns its children, and inheritance, where what you add to a parent applies to its children.
- 1
- 2
- 3
- 4
- 5
- 6
entity company, owns location;
entity public-company, sub company;
entity private-company, sub company;
match $c isa company;Subtyping: ask for every company and get both subtypes, plus any added later.
Inheritance: add location to company and every subtype owns it. Both work for relations and attributes too.
- 1
- 2
- 3
- 4
- 5
MATCH (c)
WHERE c:Company OR c:PublicCompany
OR c:PrivateCompany
RETURN c;Subtyping: emulated by giving nodes several labels, so every write has to add both. Enterprise Edition can require one label to imply another. Each relationship has exactly one type, so relationships have no subtypes.
Inheritance: none. Properties aren't declared on types; a constraint on a shared label is the closest equivalent.
Functions
Logic in the schema, or in a plugin
Both let you define your own functions. Where they live, and who can change them, is very different.
- 1
- 2
- 3
- 4
- 5
fun exposure($c: company) -> decimal:
match $l isa loan,
links (guarantor: $c), has amount $a;
return sum($a);Functions are written in TypeQL, stored in the schema and called from any query. They're type-checked against the model, and can be recursive.
User-defined functions are written in Java, packaged as a JAR and deployed to the server's plugins folder, then the server is restarted. They sit outside the schema, and custom code can't be deployed on AuraDB.
Catching mistakes
Where errors show up
TypeDB checks at three points: when you change the schema, when you commit data, and when you write a query. Neo4j is permissive by default.
| TypeDB | Neo4j | |
|---|---|---|
| Write with a misspelt label | Rejected: the type isn't defined | Accepted, and a new label is created |
| Relationship between the wrong kinds of thing | Rejected: that type can't play that role | Accepted, unless a constraint or graph type covers it |
| Query with a misspelt relationship type | Fails with an error naming the problem | Runs, returns no rows, raises a warning |
| Query for something impossible, like a person's engine size | Fails: a person can't have an engine size | Runs and returns nothing |
Neo4j constraints and graph types are opt-in, and graph types are open, so data they don't describe can still be written. A broken query that returns nothing looks exactly like a correct one.
First-attempt queries written by Claude Sonnet 5 over the same dataset, counting only the incorrect queries. See the full benchmark →
Extending the model
When the model needs to change
Say you've stored employment as an edge between a person and a company, and now you need to record the department too.
Add a department role to the employment relation. Existing data and queries keep working. Renaming types or restructuring a hierarchy still needs a migration.
Adding labels and properties is instant. A third participant means turning the EMPLOYED_BY edge into a node, migrating the data and rewriting the queries that used it.
Performance
Faster small, steadier large
We ran TPC-C on both, growing the dataset until it no longer fitted in memory.
TPC-C, TypeDB CE 3.4.1 vs Neo4j CE 5.26.5, single-threaded, 8 cores, 16 GB RAM. Read the write-up →
Use Cases
What teams build on TypeDB
01 · Agent grounding
Give agents a model of your domain they can check their work against.
- Agents query the same typed model your application uses
- Wrong queries come back as errors the agent can fix
- Connect through MCP and a TypeDB skill
match
$c isa customer, has name "Acme";
$p isa policy, links (holder: $c);
fetch { "policy": $p.ref };02 · Knowledge graphs
One connected model of your organisation, built to keep growing.
- Bring data from several systems into one typed model
- Extend the schema as you learn, without rewriting queries
- Ask questions that cross teams, systems and sources
entity employee, sub person,
plays membership:member;
relation membership,
relates member, relates team;03 · Financial relationships
Deals, ownership and exposure, modelled as they really are.
- A deal with a buyer, a target and advisors is one relation
- Ownership chains and guarantees stay queryable end to end
- One definition of exposure, shared by every team
relation deal,
relates buyer, relates target,
relates advisor @card(0..);04 · Manufacturing
Parts, suppliers and assemblies, with every dependency traceable.
- Bills of materials as nested assemblies, at any depth
- Supply relations linking part, supplier, site and contract
- Ask for every component and get every part type back
entity component;
entity fastener, sub component;
relation supply,
relates part, relates supplier, relates site;05 · Threat intelligence
Model actors, campaigns and indicators in one connected graph.
- Map standards like STIX directly onto types and roles
- Ask for every threat actor and get every subtype back
- Keep analyst and agent queries on the same model
entity threat-actor, sub stix-object;
entity intrusion-set, sub threat-actor;
match $a isa threat-actor;06 · Enterprise interoperability
Share data across systems and teams without losing what it means.
- A common model that several systems can write to
- Data that doesn't fit the model is rejected at the door
- Self-host with TypeDB Enterprise
entity person, owns id, plays case:subject;
relation case, relates subject,
relates department, owns status;07 · Digital twins
Assets, sensors and sites, connected in one live model.
- Model plants, systems and components as nested hierarchies
- Link each reading to the asset, sensor and location it belongs to
- Add new equipment types without rewriting queries
entity asset;
entity pump, sub asset;
relation reading,
relates asset, relates sensor, relates site,
owns value;08 · Legal and regulated
Obligations, parties and jurisdictions, modelled precisely.
- An obligation links a party, a rule, a jurisdiction and a deadline in one fact
- Data that breaks the model is rejected before it is stored
- Every answer traces back to typed, explicit relations
relation obligation,
relates party, relates regulation,
relates jurisdiction, owns due-date;09 · Scientific knowledge
Research domains with deep hierarchies and many-sided relationships.
- Inheritance for taxonomies that keep growing
- Reactions, pathways and samples with as many participants as they need
- Used in research in geoscience, biology and robotics
relation reaction,
relates input, relates output,
relates catalyst;Which to choose
Pick the one that fits the problem
Choose TypeDB when
- your domain has many interdependent types and will keep growing
- relationships involve more than two parties, or need nesting
- you work in a regulated domain where the data's shape mustn't drift
- you want the database to reject invalid data and queries
- agents will be writing queries against your data
Choose Neo4j when
- your workload is traversal, pathfinding or graph analytics
- your model is simple and unlikely to grow much more complex
- you need to load data before the schema is agreed
- your team knows Cypher, or wants the established ecosystem and tooling
Reference
The full comparison
| TypeDB | Neo4j | |
|---|---|---|
| Data model | Entities, relations and attributes, all typed | Nodes, relationships and properties |
| Schema | Required and enforced; can start small and grow | Optional; constraints and graph types as needed |
| Relationships | Any number of participants in named roles; can nest | Directed edges between two nodes |
| Subtyping | Native for entities, relations and attributes | Emulated with multiple labels; none for relationships |
| Inheritance | Attributes and roles inherited from parent types | None; constraints on a shared label are the closest equivalent |
| Bad writes | Rejected if they don't fit the model | Accepted unless a constraint or graph type covers them |
| Bad queries | Type-checked first; mistakes return errors | Run; unknown names return no rows and a warning |
| Path queries | Recursive functions; more code for open-ended paths | Concise variable-length paths |
| Functions | Written in TypeQL, stored in the schema | Written in Java, deployed as server plugins |
| Graph analytics | Through external tools | Built in |
| Larger-than-memory data | Throughput holds up better as data grows | Fastest while data fits in memory |
| Ecosystem | Smaller and growing | Large and established |