Officially out now: The TypeDB 3.0 Roadmap

TypeDB Philosophy

Database models have failed to keep up with the rapid evolution of programming languages, and modern applications must use complex layered architectures to manage data as a result. In order to resolve this, we built TypeDB on a completely new, highly expressive database paradigm, whose origins and core ideas we introduce on this page.

Visit learning center Review features

Why do we need a polymorphic database?

Relational databases lack the expressivity to model polymorphism

TypeDB was conceived to solve the lack of expressivity in current database paradigms. Programming languages are becoming increasingly more declarative, empowering engineers to quickly write safe and expressive code backed by static type checking and abstract data constructs. Relational databases were designed at a time when procedural programming languages were the norm. They are built on Codd’s relational algebra and implemented using tables and one-dimensional tuples.

Object-oriented programming involves complex modeling constructs such as abstraction, inheritance, and polymorphism, requiring the expression of multidimensional data structures. However, relational databases are unable to natively model them due to their lack of expressivity. This fundamental incompatibility between object and relational models has become one of the biggest challenges in database engineering and left databases unable to evolve alongside programming languages.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37

// Class inheritance in Java

class User {
    String email;
    String name;

    User(String email, String name) {
        this.name = name;
        this.email = email;
    }
}

class Employee extends User {
    int employeeId;
  
    Employee(String email, String name, int employeeId) {
        super(email, name);
        this.employeeId = employeeId;
    }
}

class PartTimeEmployee extends Employee {
    int weeklyHour;
    
    PartTimeEmployee(String email, String name, int employeeId, int weeklyHour) {
        super(email, name, employeeId);
        this.wheeklyHour = weeklyHour;
    }
}

// Class instantiation in Java

PartTimeEmployee john = new PartTimeEmployee("john.doe@vaticle.com", "John Doe", 346523, 35);

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59

-- Table inheritance in SQL

CREATE TABLE Users (
    id SERIAL PRIMARY KEY,
    email TEXT NOT NULL,
    name TEXT NOT NULL,
    UNIQUE (email)
);

CREATE TABLE Employees (
    id INTEGER NOT NULL,
    employeeId INTEGER NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (id) REFERENCES Users(id),
    UNIQUE (employeeId)
);

CREATE TABLE PartTimeEmployee (
    id INTEGER NOT NULL,
    weeklyHour INTEGER NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (id) REFERENCES Employees(id)
);

-- Data inserting for extended tables in SQL

DO $$
DECLARE
    inserted_user_id INTEGER;
BEGIN
    INSERT INTO Users (id, email, name)
    VALUES (DEFAULT, 'john.doe@vaticle.com', 'John Doe')
    RETURNING id INTO inserted_user_id;

    INSERT INTO Employees (inserted_user_id, 346523)

    INSERT INTO PartTimeEmployees (inserted_user_id, 35)
COMMIT;
END $$;

-- Data retrieval for all Users and extended tables in SQL

SELECT Users.id AS id, Users.email AS email, Users.name AS name, null AS employeeId, null AS weeklyHours, 'user' AS userType 
FROM Users 
WHERE NOT EXISTS (SELECT id FROM Employees WHERE Users.id = Employees.id)
UNION ALL 
SELECT Users.id AS id, Users.email AS email, Users.name AS name, employeeId, null AS weeklyHours, 'employee' AS userType
FROM Users 
INNER JOIN Employees ON Users.id = Employees.id
WHERE NOT EXISTS (SELECT Employees.id FROM PartTimeEmployee WHERE Employees.id = PartTimeEmployee.id)
UNION ALL
SELECT Users.id AS id, Users.email AS email, Users.name AS name, employeeId, weeklyHours, 'partTimeEmployee' AS userType
FROM Users
INNER JOIN Employees ON Users.id = Employees.id
INNER JOIN PartTimeEmployee ON Employees.id = PartTimeEmployee.id

Eliminating the schema in NoSQL databases prevents declarative data retrieval

The limitations of relational databases led to the emergence of NoSQL databases, particularly document and graph databases. These databases eliminated the predefined schema, making data insertion trivial, but this comes with the cost of complicating retrieval. Without a schema, structural metadata must be stored as data, hardcoded into queries, or modeled in a secondary data store. This forces engineers to access their data imperatively, as the database does not have the context to correctly interpret declarative polymorphic queries.

Document databases are optimized to store hierarchical data, but this breaks down when attempting to model highly interconnected data. To do so, engineers are required to choose between using performance-intensive foreign ID references or duplicating data across documents without native consistency control. Meanwhile, graph databases excel at linking highly interconnected data, but are severely limited by the implementation of relations as edges. This means that more complex relations are impossible to express without reifying the data model.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99

// Retrieval of polymorphic resources in MongoDB

db.resource_ownerships.aggregate([
    {
        $lookup:
        {
            from: "resources",
            localField: "resource",
            foreignField: "_id",
            as: "resource"
        }
    },
    {
        $unwind:
        {
            path: "$resource"
        }
    },
    {
        $lookup:
        {
            from: "users",
            localField: "owner",
            foreignField: "_id",
            as: "owner"
        }
    },
    {
        $unwind:
        {
            path: "$owner"
        }
    },
    {
        $unwind:
        {
            path: "$owner.emails"
        }
    },
    {
        $addFields:
        {
            resource_id: {
                $switch: {
                    branches: [
                        {
                            case: { 
                                $eq: ["$resource.resource_type", "file"]
                            }, 
                            then: "$resource.path" 
                        },
                        {
                            case: { 
                                $eq: ["$resource.resource_type", "directory"]
                            }, 
                            then: "$resource.path" 
                        },
                        {
                            case: { 
                                $eq: ["$resource.resource_type", "commit"]
                            }, 
                            then: "$resource.hash" 
                        },
                        {
                            case: { 
                                $eq: ["$resource.resource_type", "repository"]
                            }, 
                            then: "$resource.name" 
                        },
                        {
                            case: { 
                                $eq: ["$resource.resource_type", "table"]
                            }, 
                            then: "$resource.name" 
                        },
                        {
                            case: { 
                                $eq: ["$resource.resource_type", "database"]
                            }, 
                            then: "$resource.name" 
                        }
                    ]
                }
            }
        }
    },
    {
        $project: {
            _id: false,
            email: "$owner.emails",
            resource_type: "$resource.resource_type",
            id: "$resource_id"
        }
    }
 ])

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33

// Retrieval of polymorphic resources in Neo4j's Cypher

MATCH
    (user:User)-[:OWNS]->(rsrc:Resource)
WITH
    rsrc,
    [user.primary_email] + user.alias_emails AS emails,
    labels(rsrc) AS resource_types,
    keys(rsrc) AS properties
UNWIND emails AS email
UNWIND resource_types AS rsc_type
WITH
    rsrc, email, rsc_type, properties,
    {
        File: "path",
        Directory: "path",
        Commit: "hash",
        Repository: "name",
        Table: "name",
        Database: "name"
    } AS id_type_map
WHERE rsc_type IN keys(id_type_map)
AND id_type_map[rsc_type] IN properties
RETURN email, rsc_type, rsrc[id_type_map[rsc_type]] AS id

ORMs work around the fundamental problem by trading off performance

Engineers have attempted to work around the mismatch problem, building layers of abstraction over databases in an attempt to give them the expressivity they were never designed with. This requires engineers to non-natively manage structural metadata, leading to the widespread use of ORMs. They offer object-oriented APIs for managing data, but because of the imperfect translation to the underlying models, they can never express the full range of queries that can be written natively. This results in limited capabilities and poor query optimization, while introducing an additional layer of complexity and overhead to database architecture.

Databases have been left far behind programming languages in safety and expressivity. Current paradigms are unable to natively handle the data abstractions that we so easily take for granted. TypeDB aims to solve this problem by providing a database that natively understands complex object-oriented data structures and supports abstraction, inheritance, and polymorphism. By integrating the benefits of strong typing and query flexibility, TypeDB simplifies data access and eliminates the need for manual mapping.

What defines a polymorphic database?

There are three forms of polymorphism in computer science

Inheritance Polymorphism: The ability to define a class hierarchy where children inherit properties from their parents, and to interpret queries that operate on instances of a class and all its children.

Interface Polymorphism: The ability to define properties as interfaces that classes can implement independently of their parents, and to interpret queries that operate on instances of all classes that implement a specified interface.

Parametric Polymorphism: The ability to interpret queries that are generic and able to operate on instances of any class supplied as a parameter to the query.

To be fully polymorphic, a database has to implement three systems

Variablized Language: A query language that is expressive enough to variablize classes, either explicitly or implicitly. This is required to describe interface and parametric polymorphism, and so declaratively capture the intent of the query.

Polymorphic Schema: A schema or equivalent metadata store containing the semantic context for interpreting the query’s intent. It must contain the class and interface definitions, the class hierarchy, and the interface implementations.

Inference Engine: An engine for reducing the declarative query into an imperative form before being sent to the query planner. This is based on the structure of the query combined with the semantic context provided by the schema.

Current databases do not implement any form of polymorphism

Existing database paradigms do not satisfy all three requirements. Relational schemas define tables and columns as direct analogs of classes and their properties. As columns cannot be independently implemented by multiple tables, relational databases cannot natively implement interface polymorphism. Tables and columns also cannot be variablized in SQL, meaning that SQL cannot express interface and parametric polymorphism. Document and graph databases can define a limited number of constraints on inserted data, but this does not have the expressivity of a hierarchical schema built with classes and interfaces. As a result, these databases cannot natively implement all three types of polymorphism.

A fully polymorphic database implements all three requirements: a polymorphic query language, schema, and inference engine. It is able to express all three fundamental kinds of polymorphism possible in object-oriented programming, which can be combined to yield unique and powerful features, not possible with any one kind alone. These include the ability to write polymorphic queries in near-natural language, to construct polymorphic views that extend themselves when the schema is extended, and to perform polymorphic deductions that generate new data using rules. It also displays model polymorphism: the ability to natively model data from relational, document, graph, and other database paradigms.

What makes TypeDB the polymorphic database?

A conceptual and polymorphic data model with a type-theoretic language

TypeDB is a database with a strongly-typed, polymorphic schema for defining inheritance and interfaces, a variablized query language for composing declarative polymorphic queries, and a type inference engine for resolving queries against the schema. TypeDB schemas implement the polymorphic entity-relation-attribute (PERA) model for data, an extension of Chen’s entity-relationship (ER) model. The ER model is the most widely used tool for building conceptual data models prior to translating them into the logical bounds of a database paradigm.

TypeDB implements the PERA model as its database paradigm, which allows schemas to be built directly from the conceptual models that people use to represent domains and their data. Schemas and queries for TypeDB are described using TypeQL, its type-theoretic query language. By combining a strongly typed schema, a fully variablizable query language, and a type inference engine, TypeDB implements all three fundamental kinds of polymorphism, making it a truly polymorphic database.

Types are defined in a hierarchy

The PERA model is described by types, defined in the schema as templates for data instances, analogous to classes. Each user-defined type extends one of three root types: entity, relation, and attribute, or a previously user-defined type. Entities represent independent concepts. Relations represent concepts dependent on roles played by entities and other relations. Attributes represent properties of entities and relations. Any type can be made concrete or abstract, and roles in relations can be overridden by their subtypes.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33

define

id sub attribute, abstract, value string;
email sub id;
name sub id;
path sub id;

user sub entity;
admin sub user;
user-group sub entity;
resource sub entity, abstract;
file sub resource;

ownership sub relation, abstract,
    relates owned,
    relates owner;
group-ownership sub ownership,
    relates group as owned;
resource-ownership sub ownership,
    relates resource as owned;

Behaviors are shared and inherited

Once the entity, relation, and attribute type hierarchies have been defined, the attributes that entities and relations own and the roles they play in relations are implemented like interfaces. Declarations of owned attributes and played roles are independent of each other, and multiple entity and relation types can own the same attribute or play the same role. The attributes a type owns and the roles it plays are inherited by its subtypes, and can be overridden to specialize them.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33

define

user owns email,
    plays resource-ownership:owner;
admin plays group-ownership:owner;
user-group owns name,
    plays group-ownership:group,
    plays resouce-ownership:owner;
resource owns id,
    plays resource-ownership:resource;
file owns path as id;

Data is semantically validated

With the type hierarchies and interfaces defined in the schema, data can be instantiated with an insert query. Data instances and types are defined by variables using a $variable-name that exists in the scope of the query and can be reused to describe complex data patterns. Relations are defined with a tuple of roleplayers and the roles they play. Insert queries undergo semantic validation against the schema, ensuring that the inserted data patterns are valid. Queries that would insert data not allowed by the schema are rejected.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33

insert

$naomi isa admin, has email "naomi@vaticle.com";
$amos isa user, has email "amos@vaticle.com";
$engineers isa user-group, has name "engineers";
$benchmark isa file, has path "/amos/benchmark-results.xlsx";
$roadmap isa file, has path "/vaticle/feature-roadmap.pdf";

(group: $engineers, owner: $naomi) isa group-ownership;
(resource: $benchmark, owner: $amos) isa resource-ownership;
(resource: $roadmap, owner: $engineers) isa resource-ownership;

Data is queried polymorphically

Data is queried with high-level patterns, in which any element can be variablized. Queries are analyzed by the type inference engine before going to the query planner. It resolves polymorphism by identifying possible types that could fit patterns as defined by the schema, and queries return instances of all those types. Querying a supertype returns instances of subtypes that inherit from it. Querying an interface returns instances of types that implement it. Querying a variablized type parametrically returns instances of all types that match the pattern.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57

match
(owned: $object, owner: $owner) isa! $ownership-type;
fetch
$ownership-type;
$object: id;
$owner: id;

# Results:
[{
    "ownership-type": { "root": "relation", "label": "group-ownership" },
    "object": {
        "type": { "root": "entity", "label": "user-group" },
        "id": [
            { "value": "engineers", "value_type": "string", "type": { "root": "attribute", "label": "name" } }
        ]
    },
    "owner": {
        "type": { "root": "entity", "label": "admin" },
        "id": [
            { "value": "naomi@vaticle.com", "value_type": "string", "type": { "root": "attribute", "label": "email" } }
        ]
    }
},
{
    "ownership-type": { "root": "relation", "label": "resource-ownership" },
    "object": {
        "type": { "root": "entity", "label": "file" },
        "id": [
            { "value": "/amos/benchmark-results.xlsx", "value_type": "string", "type": { "root": "attribute", "label": "path" } }
        ]
    },
    "owner": {
        "type": { "root": "entity", "label": "user" },
        "id": [
            { "value": "amos@vaticle.com", "value_type": "string", "type": { "root": "attribute", "label": "email" } }
        ]
    }
},
{
    "ownership-type": { "root": "relation", "label": "resource-ownership" },
    "object": {
        "type": { "root": "entity", "label": "file" },
        "id": [
            { "value": "/vaticle/feature-roadmap.pdf", "value_type": "string", "type": { "root": "attribute", "label": "path" } }
        ]
    },
    "owner": {
        "type": { "root": "entity", "label": "user-group" },
        "id": [
            { "value": "engineers", "value_type": "string", "type": { "root": "attribute", "label": "name" } }
        ]
    }
}]

How does TypeDB impact database engineering?

A unified way of working with data in the database and application

As a truly polymorphic database, TypeDB has a number of unique capabilities not natively attainable with other database paradigms. It is possible to implement these features in other databases by building a layer of abstraction over the database, but the lack of native support means that engineers have to build, maintain, and debug these solutions themselves. Such solutions are also poorly optimized because they cannot take advantage of direct integration with the database. With TypeDB, all of these features are built-in, robust, and performant.

TypeDB natively models and implements complex object-oriented features like abstraction, inheritance, and polymorphism. With these capabilities, TypeDB enables engineers to work with flexible and adaptable data models, making it easier to manage, query, and reason over complex data structures. By integrating a conceptual data model, a strong subtyping system, a symbolic reasoning engine, and a type-theoretic language, TypeDB has redefined database architecture and achieved the native expressivity required for modern applications.

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37

// Class inheritance in Java

class User {
    String email;
    String name;

    User(String email, String name) {
        this.name = name;
        this.email = email;
    }
}

class Employee extends User {
    int employeeId;
  
    Employee(String email, String name, int employeeId) {
        super(email, name);
        this.employeeId = employeeId;
    }
}

class PartTimeEmployee extends Employee {
    int weeklyHour;
    
    PartTimeEmployee(String email, String name, int employeeId, int weeklyHour) {
        super(email, name, employeeId);
        this.wheeklyHour = weeklyHour;
    }
}

// Class instantiation in Java

PartTimeEmployee john = new PartTimeEmployee("john.doe@vaticle.com", "John Doe", 346523, 35);

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33

# Type inheritance in TypeQL

define

email sub attribute, value string;
name sub attribute, value string;
emloyee-id sub attribute, value long;
weekly-hour sub attribute, value long;

user sub entity,
    owns name,
    owns email;

employee sub user,
    owns employee-id;

part-time-employee sub employee,
    owns weekly-hour;

# insert of a PartTimeEmployees
insert $john isa part-time-employee,
    has email "john.doe@vaticle.com", 
    has name "John Doe",
    has employee-id 346523, 
    has weekly-hour 35;

Object Model Parity

TypeDB’s type-theoretic schemas allow for perfect parity with object models. Constructs that can be challenging to natively model in other databases are simple and intuitive in TypeDB. Utilize type hierarchies, abstract types, multivalued attributes, n-ary relations, nested relations, variadic relations, and complex cardinality constraints all without normalization, reification, or any other process that warps the designed conceptual model.

Continuous Extensibility

Types can be polymorphically queried, so the results of queries automatically extend to include new valid types that are added to the schema after the query is written. This minimizes the need to maintain and update queries when the schema is extended, so long as the semantic intent of the query remains the same. With careful design of the schema to ensure extensibility, migrations can be entirely avoided.

Integrated Application Logic

TypeDB allows you to integrate application logic by defining rules for the native symbolic reasoning / rules engine. They are written using the same patterns as queries and resolved against the schema, combining the flexibility of polymorphism with the power of symbolic reasoning. By employing sequential and recursive triggering of rules, extremely complex logical behaviors can arise from rules that are individually very simple, mirroring the true semantic logic of complex data domains.

Data Consistency

When utilizing symbolic reasoning, new fact generation occurs at query time, ensuring that generated data is never stale. By using rules to govern data dependencies within the database, all inferred data can be made to have a single source of truth, preventing data conflicts from ever occurring. This ensures that the database is always in a consistent and current state, preventing the need for precomputation cycles.

Near-Natural Language

Due to the declarative nature of TypeQL and its careful syntax design, schemas and queries read close to natural language. This allows engineers to state the intent of their queries at the highest level, without having to use imperative language to describe low-level data structure. Owing of this, engineers and domain experts can understand the intent of queries, even with no experience of writing them.

Unified Data Models

The high-level conceptual data model means that schemas in relational, document, and graph databases can be translated with no loss of information, and then enhanced with TypeDB’s unique modeling constructs. This allows for easy transfer of data from other databases, as part of migrations or a multi-database architecture.

Get started today

Deploy locally or in the cloud and start building now, or explore more about TypeDB and how its unique capabilities as a polymorphic database can refine and empower your applications.

Start building with TypeDB

Cloud or container, a polymorphic database with a conceptual data model, a strong subtyping system, a symbolic reasoning engine, and a type-theoretic language is minutes away.

Deploy
Feedback