Why TypeDB is the Rust of the database world

Rust, the programming language, exists solely because of a broken elevator.
In 2006 Graydon Hoare came home to his Vancouver apartment to find his elevator broken because of a software issue. He was so fed up with unreliable software that he designed a new language that would make the entire category of bugs impossible to ship in the first place, as MIT Technology Review later told it.
The specific bug behind that elevator traced back to a program that incorrectly managed memory: a pointer was used after what it pointed to no longer existed, two parts of a program racing to touch the same data at once. Hoare’s solution to this integrity problem wasn’t better testing or a runtime safety net. It was to make the mistake statically checkable: if the borrow checker can’t prove your memory access is safe, the program doesn’t compile.
TypeDB was built around a parallel complaint about databases, although we only occasionally get stuck in elevators.
Same issue, different domain
Existing databases give you many ways to end up with data that doesn’t match your intended data model. That could be due to fundamentally lacking such constructs (eg. document and property graph databases not having a real schema), or allowing you to accidentally constraints (eg. missing foreign keys in relational databases).
As systems become increasingly complex and evolve over time, these errors can creep in and quietly corrupt your data. Our solution, like Hoare’s, is to provide a stricter type system that lets us move the failure earlier, blocking harmful writes and data drift. Our goal is to ensure that dramatically fewer integrity issues are persisted into the database.
In short: don’t let an invalid state exist in the first place, rather than detecting it after something has gone wrong.
Types as foundation
Hoare’s ideas, combined with countless contributions and evolutions from a huge number of people, become the Rust we know now. Both Rust and TypeDB’s type systems are essentially now providing brand new platforms for building systems, rather than extending existing ones.
We built ours on top of type theory, rather than the existing relational algebra or graph theory – which also happens to underpin modern statically typed programming languages. By reframing database operations this way, and allowing your database schema to be literally treated as your database’s type system, TypeDB and TypeQL can borrow a lot from compilers and programming languages. Treat the type system as a first-class, critical component, then correctness and integrity follow from there.
Structural analogies
Rust and TypeQL have different semantics, but share some philosophical alignments.
For example, Rust doesn’t use inheritance to share behaviour across types. It uses traits, contracts that any type can implement regardless of where it sits in a type hierarchy, or whether it sits in one at all.
trait Employer {}struct Person;struct Company;impl Employer for Person {}impl Employer for Company {}
Neither Person nor Company needs to be related to the other. Both satisfy the same contract independently, and any code written against Employer works for either.
TypeQL also favors composition over inheritance. It still offers single-parent subtyping, but many use cases choose to compose behaviour as well.
TypeQL treats both attributes and relation’s roles as interfaces: behaviours that can be applied and shared. Any entity type can declare that it plays a role in a relation, without inheriting from a common ancestor.
define
entity person,
plays employment:employer;
entity company,
plays employment:employer;
relation employment,
relates employer,
relates employee;
A query against employment doesn’t care whether the employer is a person or a company, the same way code written against the Employer trait doesn’t care whether it’s holding a Person or a Company. Both are expressing interface polymorphism. Similar to Rust, this approach lets you compose the desired data model in the type system.
Structural differences
Of course the way each language operates is unique to their domain. We can’t even necessarily have the idea of “compile time” and “execution time” be expressed the same way, when most database queries are submitted in one shot.
That being said, TypeDB’s queries do execute in two passes: the “compile” and the “execute” internally. You can even run just the compilation and type check by using TypeDB’s analyze API.
And of course, Rust has to deal with much richer problems: data mutation semantics, referencing versus owning, threading etc. TypeDB, by being a declarative data and schema language, has much simpler semantics.
Correctness, two ways
Rust’s appeal is the promise that we can avoid more bugs and unexpected behaviour in production – which is borne out in real world usage.
By paying a bit more up front in satisfying the compiler, many incoherent states can be avoided. TypeDB is that instinct, applied to the database; for data, instead of memory.
