TypeDB vs Postgres
When your data stops looking like tables
Postgres stores your data and leaves its meaning to the joins and code around it. TypeDB stores the meaning too, which matters most for connected, graph-shaped domains.
- 1
- 2
- 3
- 4
- 5
- 6
match
$b isa company, has name "Acme Ltd";
$l isa loan, links (borrower: $b,
guarantor: $g), has amount $a;
fetch { "guarantor": $g.name, "amount": $a };- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
SELECT g.name, l.amount
FROM loan l
JOIN loan_party b ON b.loan_id = l.id AND b.role = 'borrower'
JOIN company bc ON bc.id = b.company_id
JOIN loan_party gp ON gp.loan_id = l.id AND gp.role = 'guarantor'
JOIN company g ON g.id = gp.company_id
WHERE bc.name = 'Acme Ltd';Overview
Main differences from Postgres
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.
Relations, not join tables
A loan with a lender, borrower and guarantor is one relation in TypeDB, not a join table with a role column.
Modelling relationships
Many values, declared
Things that come in varying numbers are part of the model, with no extra tables and no rows multiplying in joins.
Cardinality
Queries checked for meaning
Postgres checks names and types. TypeDB also checks roles and relationships, so a wrong query fails.
Where errors show up
Relationships
Join tables, or relations with roles
Postgres can model a loan with three parties. It takes a join table, a role column and a join for every participant.
The loan is one relation with three named roles. Queries name the roles directly, and the schema says which types can play them.
A loan_party table with a role column. Every query rebuilds the relationship with one join per participant, and the roles are just strings.
Cardinality
When one thing has many answers
A person has several email addresses. A deal has any number of advisors. Real domains are full of values that come in varying numbers.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
entity person,
owns email @card(1..);
relation deal,
relates buyer @card(1),
relates advisor @card(0..);How many values are allowed is declared in the schema and checked on every write, so a deal without a buyer never gets stored.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
SELECT d.id, SUM(f.amount)
FROM deal d
JOIN deal_advisor a ON ...
JOIN deal_fee f ON ...
GROUP BY d.id;
-- each fee counted once per advisorEach multi-valued field becomes its own table. Join two of them and rows multiply, so sums inflate unless every query guards against it.
Catching mistakes
Valid SQL can still mean the wrong thing
Postgres is strict about tables, columns and types, and enforces foreign keys. What it can't check is whether a query means what you intended.
| TypeDB | Postgres | |
|---|---|---|
| Misspelt column or table | Error | Error |
| Misspelt role, such as 'guarenter' | Error: the role isn't defined | Runs, returns no rows: it's just a string |
| Join on the wrong key of the same type | No join keys to get wrong; roles are checked | Runs, returns plausible wrong rows |
First-attempt queries by Claude Sonnet 5, same dataset, counting only the incorrect ones. SQL was more often right first time, 82.1% against 75.2%; with retries TypeQL finished ahead with both models tested. See the benchmark →
Hierarchies
Categories within categories
Parties that can be companies or people. Companies that can be banks or funds. Relational models can handle it, at a cost.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
entity party;
entity company sub party;
entity bank sub company;
# One query returns every kind of party
match $p isa party;Subtypes inherit attributes and roles. One query returns every kind of party, including ones you add later, without a migration.
- One wide table with a type column and many nullable fields
- A table per subtype, with UNIONs to query them together
- Table inheritance, where indexes and foreign keys don't carry over
Adding a subtype usually means a migration and finding every query that joins through it.
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 schema is mostly join tables and role columns
- your data has values that come in varying numbers
- your domain has deep hierarchies that keep growing
- agents or analysts write queries and wrong ones need to fail loudly
Choose Postgres when
- your data is mostly tabular and relationships are simple
- you need a transactional system of record with a vast ecosystem
- your team lives in SQL and the joins aren't getting in the way
Or use both
Plenty of teams keep Postgres as the system of record and load the connected, graph-shaped part of their domain into TypeDB for the queries that need it.
Reference
The full comparison
| TypeDB | Postgres | |
|---|---|---|
| What it stores | Data and its meaning: types, roles and what's allowed | Data; meaning lives in joins and application code |
| Data model | Entities, relations and attributes, organised into types | Tables, rows and columns |
| Many-sided relationships | One relation, each participant in a named role | A join table with a role column |
| Multiple values | Native, with cardinality declared and enforced | A table per multi-valued field; joins multiply rows |
| Hierarchies | Native inheritance, with polymorphic queries | Wide tables, table-per-subtype or table inheritance |
| Schema | Required, and enforced on every write | Required, and enforced on every write |
| Bad queries | Checked against the domain model, including roles | Checked for names and types |
| Best for | Connected, complex domains | General-purpose transactional and analytical work |