Meet TypeDB and TypeQL
TypeDB is a polymorphic database with a conceptual data model, a strong subtyping system, a symbolic reasoning engine, and a beautiful and elegant type-theoretic language: TypeQL.
Conceptual Modeling
Entity-Relation-Attribute
TypeQL implements the Enhanced Entity-Relation-Attribute model for its schemas and data. Entities, relations, and attributes are all first-class citizens and subtypable, allowing for expressive modeling without normalization or reification.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
id sub attribute, value string;
email sub id;
path sub id;
name sub id;
user sub entity,
owns email @unique,
plays permission:subject,
plays request:requester;
file sub entity,
owns path,
plays permission:object;
action sub entity,
owns name,
plays permission:action;
permission sub relation,
relates subject,
relates object,
relates action,
plays request:target;
request sub relation,
relates target,
relates requester;
Declarative Schema
The schema provides a structural blueprint for data organization, ensuring referential integrity in production. Extend your data model seamlessly in TypeDB, maintaining integrity during model updates and avoiding any query rewrites or code refactors.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
full-name sub attribute, value string;
id sub attribute, value string;
email sub id;
employee-id sub id;
user sub entity,
owns full-name,
owns email @unique;
employee sub user,
owns employee-id @key;
Abstract Types
Define abstract entity, relation, and attribute types in your schema to extend concrete types from. Build templates with ownership of abstract attributes and playing of abstract roles for subtypes to extend and override.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
id sub attribute, abstract, value string;
email sub id;
path sub id;
user sub entity, abstract,
owns id;
employee sub user,
owns email as id;
resource sub entity, abstract,
owns id,
plays collection-membership:member;
file sub resource,
owns path as id;
membership sub relation, abstract,
relates parent,
relates member;
team-membership sub membership,
relates team as parent;
collection-membership sub membership,
relates collection as parent;
Type Inheritance
Type inheritance in TypeDB allows you to create new types based on existing ones, providing hierarchy and abstraction in your data model. By inheriting attributes and relationships from parent types, schema design is simplified, promoting reusability and consistency.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
user sub entity,
owns full-name,
owns email;
intern sub user;
employee sub user,
owns employee-id,
owns title;
part-time-employee sub employee,
owns weekly-hours;
Strong Type System
Type Inference
TypeDB’s type inference resolves queries against the schema to generate polymorphic results. Queries on supertypes automatically return results for subtypes, and the types of variables can even be omitted to match only the shape of the data.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
user sub entity, abstract,
owns id,
plays resource-ownership:owner;
employee sub user, owns employee-id as id;
resource sub entity, abstract,
owns id,
plays resource-ownership:resource;
file sub resource, owns path as id;
database sub resource, owns name as id;
commit sub resource, owns hash as id;
resource-ownership sub relation,
relates resource,
relates owner;
match
$user has id $user-id;
$rsrc has id $rsrc-id;
($user, $rsrc) isa $relation-type;
fetch
$user-id;
$rsrc-id;
$relation-type;
Semantic Validation
TypeDB validates all queries and rules against the type system defined in the schema to ensure semantic correctness. Nonsensical writes are automatically blocked, and nonsensical reads throw an exception instead of returning an empty result set.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
weekly-hours sub attribute value long;
full-time-employee sub employee;
part-time-employee sub employee, owns weekly-hours;
insert
$francois isa full-time-employee,
has full-name "François Durand",
has email "[email protected]",
has employee-id 184,
has weekly-hours 35;
# [THW03] Invalid Write: Attribute of type 'weekly-hours' is
# not defined to be owned by type 'full-time-employee'.
Symbolic Reasoning
Rule-Based Reasoning
TypeDB’s symbolic reasoning enables the automated deduction of new facts and relationships based on existing data and rules you define. Rule chaining and branching allow complex behavior to arise from simple rules, creating rich, high-level insights.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
rule transitive-team-membership:
when {
(team: $team-1, member: $team-2) isa team-membership;
(team: $team-2, member: $member) isa team-membership;
} then {
(team: $team-1, member: $member) isa team-membership;
};
rule inherited-team-permission:
when {
(team: $team, member: $member) isa team-membership;
(subject: $team, object: $obj, action: $act) isa permission;
} then {
(subject: $member, object: $obj, action: $act) isa inherited-permission;
};
Explanations
TypeDB's reasoning engine functions on deductive reasoning, so inferred data can always be traced back to its source. Perform root-cause analysis using TypeDB’s Explanations feature, guaranteeing accountability of generated data.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
query = "match $perm isa inherited-permission; get;"
with open_session.transaction(TransactionType.READ) as tx:
results = tx.query().get(query)
for result in results:
inherited_permission = result.explainables().relation("perm")
explanations = tx.query().explain(inherited_permission)
for explanation in explanations:
condition = explanation.condition()
rule = explanation.rule()
conclusion = explanation.conclusion()
Polymorphic Queries
Variablized Types
Schema types and relation roles can be variablized in addition to data instances, making schema querying as easy as data querying. Queries can contain both schema and data constraints, allowing for patterns that represent highly complex conceptual structures.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
user sub entity, has full-name,
plays mentorship:mentor,
plays mentorship:trainee;
employee sub user;
contractor sub user;
mentorship sub relation,
relates mentor,
relates trainee;
match
$user isa $user-type, has full-name $name;
$user-type sub user;
($role-1: $user, $role-2: $other-user) isa mentorship;
mentorship relates $role-1, relates $role-2;
fetch
$name;
$user-type;
$role-1;
$role-2;
Inheritance Polymorphism
TypeQL implements inheritance polymorphism, allowing subtypes to inherit the behaviors of the supertypes they extend, whether concrete or abstract. Write TypeQL queries that return results with a common supertype, without enumerating the subtypes.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
user sub entity,
owns full-name,
owns email @unique;
employee sub user,
owns employee-id @key;
insert
$john isa employee,
has full-name "John Doe",
has email "[email protected]",
has employee-id 183;
Interface Polymorphism
Ensure conceptual consistency between defined types and their behaviors in perfect parallel to your object model by harnessing TypeQL’s interface polymorphism. Types can own the same attributes and play the same roles, even if they share no common supertypes.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
name sub attribute, value string;
user sub entity, owns name;
team sub entity, owns name;
table sub entity, owns name;
match
$x has name $n;
fetch
$n;
Parametric Polymorphism
Write queries that create or delete data instances without specifying their types by utilizing parametric polymorphism. Queries are resolved against the schema when run, allowing them to write data of multiple types matching declared properties.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$data isa $T;
$data has data-expiration-date < 2023-09-27;
delete
$data isa $T;
Modern Language
Near Natural
Due to its OOP properties and simple syntax, queries written in TypeQL read close to natural language. Domain experts and non-technical users alike can quickly grasp the intent of a query, reducing the learning curve and making query maintenance a breeze.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$kevin isa user, has email "[email protected]";
insert
$chloe isa part-time-employee,
has full-name "Chloé Dupond",
has email "[email protected]",
has employee-id 185,
has weekly-hours 35;
$hire (employee: $chloe, ceo: $kevin) isa hiring,
has date 2023-09-27;
Fully Declarative
TypeQL is fully declarative, allowing you to define query patterns without considering execution strategy. TypeDB’s query planner always deconstructs queries into the most optimized plans, so you never have to think about the logical implementation.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
user sub entity,
owns full-name,
owns email;
intern sub user;
employee sub user,
owns employee-id;
full-time-employee sub employee;
part-time-employee sub employee,
owns weekly-hours;
contractor sub user,
owns contract-number;
match
$user isa $user-type;
$user-type sub user;
fetch
$user: attribute;
$user-type;
Composable Patterns
Patterns in TypeQL are fully composable. Every complex pattern can be broken down into a conjunction of atomic constraints, which can be concatenated in any order. Any pattern composed of valid constraints is guaranteed to be valid itself, no matter how complex.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$user isa user;
fetch
$user: full-name;
match
$user isa user;
$user has email "[email protected]";
fetch
$user: full-name;
match
$user isa user;
$user has email "[email protected]";
(team: $team, member: $user) isa team-membership;
fetch
$user: full-name;
match
$user isa user;
$user has email "[email protected]";
(team: $team, member: $user) isa team-membership;
$team has name "Engineering";
fetch
$user: full-name;
Nested Subqueries
Search for complex data structures with a single query and network trip using nested subqueries. Retrieve results for nested queries as a list or perform aggregations over them, including results for optional attribute matches.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$user isa user;
fetch
$user: email, full-name, employee-id;
teams: {
match
(team: $team, member: $user) isa team-membership;
fetch
$team: name;
};
permission-count: {
match
$perm (subject: $user) isa permission;
get;
count;
};
Structured Results
Query results can be serialized for easy consumption in your application with TypeQL’s native JSON outputs. Switch from an asynchronous answer stream to a single structured collection, and define the result format using projections in the query structure.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$user isa full-time-employee;
fetch
$user as employee: attribute;
limit 1;
# JSON output:
[{
"employee": {
"type": { "root": "entity", "label": "full-time-employee" },
"attribute": [
{ "value": "Chloé Dupond", "value_type": "string", "type": { "root": "attribute", "label": "full-name" } },
{ "value": "[email protected]", "value_type": "string", "type": { "root": "attribute", "label": "email" } },
{ "value": 185, "value_type": "long", "type": { "root": "attribute", "label": "employee-id" } },
{ "value": 35, "value_type": "long", "type": { "root": "attribute", "label": "weekly-hours" } }
]
}
}]
Aggregates and Expressions
Perform basic mathematical operations directly in your queries or rules with aggregations and arithmetic expressions, enabling dynamic and efficient data computation.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$user isa user;
$perm (subject: $user) isa permission;
group $user;
get;
count;
match
$dir isa directory,
has path $path,
has size $kb;
?gb = $kb / 1024 ^ 2;
fetch
$path;
?gb;
Query Builder
Use the TypeQL query builder to auto-generate queries using a code-first approach in Java or Rust, with other languages coming soon. This permits the generation of TypeDB queries through a robust and streamlined process.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
TypeQLMatch.Filtered builtQuery = TypeQL.match(
cVar("user").isa("user").has("full-name", "Kevin Morrison"),
cVar("file").isa("file").has("path", cVar("path")),
cVar("perm").rel(cVar("user")).rel(cVar("file")).isa("permission")
).get(cVar("path"));
// builtQuery =
// match
// $user isa user, has full-name 'Kevin Morrison';
// $file isa file, has path $path;
// $perm ($user, $file) isa permission;
// get $path;
Query Templates
Build query templates that accept a tuple of attribute values as parameters and execute them repeatedly for lists of supplied values. The template is stored in the transaction cache, reducing network load and ensuring sanitization of input strings.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$fake-example isa fakefake;
$fake-example has fake-name "Faki Fake Fakee";
$fake-example has fake-age 4242;
insert
$super-fake isa fakish,
has fake-name "Fakoon",
has fake-status "Fakake",
has fake-job "Faker at FakeCorp";
$f (faker: $super-fake, fakee: $fakefake) isa faker-fakee;
Expressive Relations
N-ary Relations
Construct rich data representations by directly implementing unary, binary, ternary, and n-ary relations in your conceptual model. TypeQL’s expressivity allows you to use the same constructor format for all relations, regardless of the number of roleplayers.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$omar isa contractor, has email "[email protected]";
insert
$term (user: $omar) isa user-termination,
has termination-date 2023-09-19,
has termination-reason "end of contract";
match
$naomi isa user, has email "[email protected]";
$eng isa group, has name "Engineering";
insert
$own (group: $eng, owner: $naomi) isa group-ownership;
match
$john isa user, has email "[email protected]";
$readme isa file, has path "/usr/johndoe/repos/typedb/readme.md";
$edit isa action, has name "edit file";
insert
$perm (subject: $john, object: $readme, action: $edit) isa permission;
Nested Relations
Relations are first-class citizens in TypeQL and so can own attributes and play roles in other relations just like entities. With no limit to the depth of nesting for relations, you can express the full richness of your data without reifying your data model.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$john isa user, has email "[email protected]";
$readme isa file, has path "/usr/johndoe/repos/typedb/readme.md";
$edit isa action, has name "edit file";
$perm (subject: $john, object: $readme, action: $edit) isa permission;
$kevin isa user, has email "[email protected]";
insert
$rqst (target: $perm, requestee: $kevin) isa change-request,
has requested-change "revoke";
Variadic Relations
With TypeQL’s expressive relation constructor, you can easily implement relations where the same roleplayer plays multiple roles, multiple roleplayers play the same role, or a combination of both. Read queries always return all matched roleplayers.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$submit isa action, has name "submit order";
$approve isa action, has name "approve order";
insert
(segregated-action: $submit, segregated-action: $approve) isa segregation-policy;
match
$kevin isa user, has email "[email protected]";
insert
(reviewer: $kevin, reviewee: $kevin) isa permission-review;
Cardinality Constraints
All attributes and relations have many-to-many cardinality by default. Apply constraints in the schema to apply stricter cardinalities wherever needed, with the expressivity to select a single value or a specific range.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
name sub attribute, value string;
object-type sub attribute, value string;
action sub entity,
owns name @card(1),
owns object-type @card(1,*)
plays segregation-policy:segregated-action @card(0,*);
segregation-policy sub relation,
relates segregated-action @card(2);
Intuitive Attributes
Multi-Valued Attributes
TypeQL is a conceptual data modeling language, and all attributes have many-to-many cardinality by default. Giving an entity or relation multiple attributes of the same type is as simple as declaring them in an insert, and read queries automatically return all values.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
insert
$john isa full-time-employee,
has primary-email "[email protected]",
has email "[email protected]",
has email "[email protected]",
has email "[email protected]";
Globally Unique Attributes
Attributes are globally unique in TypeQL. If two entities each have an attribute with the same type and value, then they both have the same attribute instance. This allows for highly efficient data traversals, keeps disk usage low, and maintains a consistent model.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
insert
$roadmap isa file,
has path "/typedb/feature-roadmap.pdf",
has confidentiality "public";
$cloud isa repository,
has name "typedb-cloud",
has confidentiality "restricted";
$sales isa database,
has name "sales",
has confidentiality "restricted";
match
$rsrc has confidentiality $conf;
fetch
$conf;
No Nulls
Unlike SQL and NoSQL modeling languages, TypeQL is entirely conceptual and does not need to implement nulls to store the absence of a value. Keep nulls out of your query results without compromising for a schema-less database.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
insert
$john isa user, has full-name "John Doe";
$david isa user, has email "[email protected]";
match
$user isa user;
fetch
$user: full-name, email;
# JSON output:
[{
"user": {
"type": { "root": "entity", "label": "user" },
"full-name": [
{ "value": "John Doe", "value_type": "string", "type": { "root": "attribute", "label": "full-name" } }
],
"email": []
}
}, {
"user": {
"type": { "root": "entity", "label": "user" },
"full-name": [],
"email": [
{ "value": "[email protected]", "value_type": "string", "type": { "root": "attribute", "label": "email" } }
]
}
}]
Attribute Constraints
Define a key constraint on an attribute to make ownership of that attribute required and ensure a unique value. Alternatively, use a unique constraint instead to ensure uniqueness without requiring ownership. Apply regex constraints to string attributes to enforce defined patterns.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
define
full-name sub attribute, value string;
office-location sub attribute,
value string,
regex "^(London|Paris|Dublin)$";
id sub attribute, value string;
email sub id, regex "^(.+)@(\\S+)$";
employee-id sub id;
user sub entity,
owns full-name,
owns email @unique;
employee sub user,
owns employee-id @key,
owns office-location;
Purely Abstract Attributes
Define abstract attribute types with no declared value type, and extend them to define subtypes with different value types. Easily retrieve attribute values of different types by querying the abstract supertype.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
define
id sub attribute, abstract;
email sub id, value string;
employee-id sub id, value long;
path sub id, value string;
user sub entity, owns email;
employee sub user, owns employee-id;
resource sub entity, abstract, owns id;
file sub resource, owns path as id;
match
$ent isa entity;
fetch
$ent: id;
[{
"ent": {
"type": { "root": "entity", "label": "employee" },
"id": [
{ "value": "[email protected]", "value_type": "string", "type": { "root": "attribute", "label": "email" } },
{ "value": 184, "value_type": "long", "type": { "root": "attribute", "label": "employee-id" } }
]
}
},{
"ent": {
"type": { "root": "entity", "label": "file" },
"id": [
{ "value": "/typedb/upcoming-features.pdf", "value_type": "string", "type": { "root": "attribute", "label": "path" } }
]
}
}]
Compound Value Types
Define compound value types for your attributes constructed from primitive types.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
match
$fake-example isa fakefake;
$fake-example has fake-name "Faki Fake Fakee";
$fake-example has fake-age 4242;
insert
$super-fake isa fakish,
has fake-name "Fakoon",
has fake-status "Fakake",
has fake-job "Faker at FakeCorp";
$f (faker: $super-fake, fakee: $fakefake) isa faker-fakee;
Native Language Drivers
Go
go get github.com/typedb/typedb-driver/go
Request your language
Robust API
ACID Compliance
TypeDB is ideal for complex and highly transactional applications due to its ACID compliance, ensuring data integrity and reliability. This prevents corruption and guarantees consistency during concurrent transactions.
Asynchronous Protocol
Communication with TypeDB servers is fully asynchronous, preventing any bottlenecks due to query processing. Send queries concurrently from the client, taking only as long as the network round-trip, while the server continues to process the received queries concurrently.
Reactive Streaming
TypeDB servers return query results in a stream as they are discovered. This enables the application to consume the results lazily for built-in vertical parallelism. Answer streaming is reactive, allowing the server to optimize for the rate of consumption and network latency.
Stateful & Programmatic
TypeDB’s network API streamlines integration with the database with fine control over connections, sessions, and transactions. Maximize performance based on your use case with automatic cache optimization, from high-speed bulk loading to high-volume reads.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
let connection = Connection::new_core("localhost:1729")?;
let databases = DatabaseManager::new(connection);
databases.create("access-management-db").await?;
let session = Session::new(databases.get("access-management-db").await?, SessionType::Schema).await?;
let tx = session.transaction(TransactionType::Write).await?;
tx.query().define(access_management_schema).await?;
tx.commit().await?;
drop(session);
let session = Arc::new(Session::new(databases.get("access-management-db").await?, SessionType::Data).await?);
futures::future::try_join_all(access_management_data_batches.into_iter().map(|batch| {
let session = session.clone();
async move {
let tx = session.transaction(TransactionType::Write).await?;
batch.iter().try_for_each(|query| tx.query().insert(query).map(|_| ()))?;
tx.commit().await
}
})).await?;
let tx = session.transaction(TransactionType::Read).await?;
let mut stream = tx.query().get("match $u isa user; get;")?;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
with TypeDB.core_driver("localhost:1729") as driver:
driver.databases.create("access-management-db")
with driver.session("access-management-db", SessionType.SCHEMA) as session:
with session.transaction(TransactionType.WRITE) as tx:
tx.query.define(access_management_schema)
tx.commit()
with driver.session("access-management-db", SessionType.DATA) as session:
for batch in access_management_data_batches:
with session.transaction(TransactionType.WRITE) as tx:
for query in batch:
tx.query.insert(query)
tx.commit()
with session.transaction(TransactionType.READ) as tx:
results = tx.query.get("match $u isa user; get;")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
let driver, session, tx;
try {
driver = await TypeDB.coreDriver("localhost:1729");
await driver.databases.create("access-management-db");
session = await driver.session("access-management-db", SessionType.SCHEMA);
tx = await session.transaction(TransactionType.WRITE);
tx.query.define(accessManagementSchema);
await tx.commit();
await session.close();
session = await driver.session("access-management-db", SessionType.DATA);
for (const batch of accessManagementDataBatches) {
tx = await session.transaction(TransactionType.WRITE);
for (const query of batch) {
tx.query.insert(query);
}
await tx.commit();
}
tx = await session.transaction(TransactionType.READ);
const results = tx.query.get("match $u isa user; get;");
} finally {
if (tx) await tx.close();
if (session) await session.close();
if (driver) await driver.close();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
try (TypeDBDriver driver = TypeDB.coreDriver("localhost:1729")) {
driver.databases().create("access-management-db");
try (TypeDBSession session = driver.session("access-management-db", TypeDBSession.Type.SCHEMA)) {
try (TypeDBTransaction tx = session.transaction(TypeDBTransaction.Type.WRITE)) {
tx.query().define(accessManagementSchema);
tx.commit();
}
}
try (TypeDBSession session = driver.session("access-management-db", TypeDBSession.Type.DATA)) {
for (List<TypeQLInsert> batch: accessManagementDataBatches) {
try (TypeDBTransaction tx = session.transaction(TypeDBTransaction.Type.WRITE)) {
for (TypeQLInsert query: batch) {
tx.query().insert(query);
}
tx.commit();
}
}
try (TypeDBTransaction tx = session.transaction(TypeDBTransaction.Type.READ)) {
Stream<ConceptMap> results = tx.query().get(TypeQL.match(TypeQL.cVar("u").isa("user")).get());
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
Connection* connection = connection_open_core("localhost:1729");
DatabaseManager* databaseManager = database_manager_new(connection);
{
Options* options = options_new();
Session* session = session_new(databaseManager, "access-management-db", Schema, options);
Transaction* tx = transaction_new(session, Write, options);
void_promise_resolve(query_define(tx, accessManagementSchema, options));
void_promise_resolve(transaction_commit(tx));
session_close(session);
options_drop(options);
}
{
Options* options = options_new();
Session* session = session_new(databaseManager, "access-management-db", Data, options);
{
Transaction* tx = transaction_new(session, Write, options);
for (int i = 0; i < accessManagementDataBatchCount; i++) {
for (int j = 0; j < accessManagementDataBatchSize; j++) {
ConceptMapIterator* inserted = query_insert(tx, accessManagementDataBatches[i][j], options);
concept_map_iterator_drop(inserted);
}
}
void_promise_resolve(transaction_commit(tx));
}
{
Transaction* tx = transaction_new(session, Read, options);
ConceptMapIterator* results = query_get(tx, "match $u isa user; get;", options);
concept_map_iterator_drop(results);
transaction_close(tx);
}
session_close(session);
options_drop(options);
}
database_manager_drop(databaseManager);
connection_close(connection);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
TypeDB::Driver driver = TypeDB::Driver::coreDriver("localhost:1729");
TypeDB::Options options;
{
TypeDB::Session session = driver.session("access-management-db", TypeDB::SessionType::SCHEMA, options);
TypeDB::Transaction tx = session.transaction(TypeDB::TransactionType::WRITE, options);
tx.query.define(accessManagementSchema, options).wait();
tx.commit();
}
{
TypeDB::Session session = driver.session("access-management-db", TypeDB::SessionType::DATA, options);
for (auto& batch: accessManagementDataBatches) {
TypeDB::Transaction tx = session.transaction(TypeDB::TransactionType::WRITE, options);
for (auto& query: batch) {
tx.query.insert(query, options);
}
tx.commit();
}
{
TypeDB::Transaction tx = session.transaction(TypeDB::TransactionType::READ, options);
ConceptMapIterable results = tx.query.get("match $u isa user; get;", options);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
using (ITypeDBDriver driver = Drivers.CoreDriver("localhost:1729"))
{
driver.Databases.Create("access-management-db");
using (ITypeDBSession session = driver.Session("access-management-db", SessionType.Schema))
{
using (ITypeDBTransaction tx = session.Transaction(TransactionType.Write))
{
tx.Query.Define(accessManagementSchema).Resolve();
tx.Commit();
}
}
using (ITypeDBSession session = driver.Session("access-management-db", SessionType.Data))
{
foreach (var batch in accessManagementDataBatches)
{
using (ITypeDBTransaction tx = session.Transaction(TransactionType.Write))
{
foreach (var query in batch)
{
tx.Query.Insert(query);
}
tx.Commit();
}
}
using (ITypeDBTransaction tx = session.Transaction(TransactionType.Read))
{
IEnumerable<IConceptMap> results = tx.Query.Get("match $u isa user; get;");
}
}
}
Programmatic Schema Migration
Transactional Mutations
Execute complex schema mutations with ACID guarantees by using TypeDB’s stateful API. Mutations are executed via schema-write transactions, ensuring large-scale migrations can be carried out in production without inconsistent states or downtime.
Existing Data Validation
All schema mutation operations can be performed with data in place. By utilizing transactions, existing data can enter illegal states within the scope of the transaction, as long as they are resolved by commit. Any remaining inconsistencies will trigger a rollback.
Type Hierarchy Modification
The type hierarchies declared in the schema are entirely mutable. New types can be defined, existing types can be undefined, and the supertype of any type can be changed to any other type, with inherited behaviors automatically re-assigned where necessary.
Type Behavior Modification
Modify the behaviors of types with complete flexibility. Rename types, assign or de-assign ownership of attributes, create or remove roles from relations, and add or remove the ability for types to play roles, with new behaviors automatically inherited in hierarchies.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
let connection = Connection::new_core("localhost:1729")?;
let databases = DatabaseManager::new(connection);
let session = Session::new(databases.get("access-management-db").await?, SessionType::Schema).await?;
let tx = session.transaction(TransactionType::Write).await?;
// create a new abstract type "user"
let mut user = tx.concept().put_entity_type("user".to_owned()).await?;
user.set_abstract(&tx).await?;
// change the supertype of "employee" to "user"
let mut employee = tx.concept().get_entity_type("employee".to_owned()).await?.unwrap();
employee.set_supertype(&tx, user.clone()).await?;
// change the supertype of "contractor" to "user"
let mut contractor = tx.concept().get_entity_type("contractor".to_owned()).await?.unwrap();
contractor.set_supertype(&tx, user.clone()).await?;
// move "email" and "name" attribute types to be owned by "user" instead of "employee"
let email = tx.concept().get_attribute_type("email".to_owned()).await?.unwrap();
let mut name = tx.concept().get_attribute_type("name".to_owned()).await?.unwrap();
employee.unset_owns(&tx, email.clone()).await?;
employee.unset_owns(&tx, name.clone()).await?;
user.set_owns(&tx, email, None, Vec::new()).await?;
user.set_owns(&tx, name.clone(), None, Vec::new()).await?;
// rename "name" attribute type to "full-name"
name.set_label(&tx, "full-name".to_owned()).await?;
// commit all schema changes in one transaction, which will fail if we violate any data validation
tx.commit().await?;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
with TypeDB.core_driver("localhost:1729") as driver:
with driver.session("access-management-db", SessionType.SCHEMA) as session:
with session.transaction(TransactionType.WRITE) as tx:
# create a new abstract type "user"
user = tx.concepts.put_entity_type("user").resolve()
user.set_abstract(tx).resolve()
# change the supertype of "employee" to "user"
employee = tx.concepts.get_entity_type("employee").resolve()
employee.set_supertype(tx, user).resolve()
# change the supertype of "contractor" to "user"
contractor = tx.concepts.get_entity_type("contractor").resolve()
contractor.set_supertype(tx, user).resolve()
# move "email" and "name" attribute types to be owned by "user" instead of "employee"
email = tx.concepts.get_attribute_type("email").resolve()
name = tx.concepts.get_attribute_type("name").resolve()
employee.unset_owns(tx, email).resolve()
employee.unset_owns(tx, name).resolve()
user.set_owns(tx, email).resolve()
user.set_owns(tx, name).resolve()
# rename "name" attribute type to "full-name"
name.set_label(tx, "full-name").resolve()
# commit all schema changes in one transaction, which will fail if we violate any data validation
tx.commit()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
try {
driver = await TypeDB.coreDriver("localhost:1729");
session = await driver.session("access-management-db", SessionType.SCHEMA);
tx = await session.transaction(TransactionType.WRITE);
// create a new abstract type "user"
let user = await tx.concepts.putEntityType("user");
await user.setAbstract(tx);
// change the supertype of "employee" to "user"
let employee = await tx.concepts.getEntityType("employee");
await employee.setSupertype(tx, user);
// change the supertype of "contractor" to "user"
let contractor = await tx.concepts.getEntityType("contractor");
await contractor.setSupertype(tx, user);
// move "email" and "name" attribute types to be owned by "user" instead of "employee"
let email = await tx.concepts.getAttributeType("email");
let name = await tx.concepts.getAttributeType("name");
await employee.unsetOwns(tx, email);
await employee.unsetOwns(tx, name);
await user.setOwns(tx, email);
await user.setOwns(tx, name);
// rename "name" attribute type to "full-name"
await name.setLabel(tx, "full-name");
// commit all schema changes in one transaction, which will fail if we violate any data validation
await tx.commit()
} finally {
if (tx) await tx.close();
if (session) await session.close();
if (driver) await driver.close();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
try (TypeDBDriver driver = TypeDB.coreDriver("localhost:1729")) {
try (TypeDBSession session = driver.session("access-management-db", TypeDBSession.Type.SCHEMA)) {
try (TypeDBTransaction tx = session.transaction(TypeDBTransaction.Type.WRITE)) {
// create a new abstract type "user"
EntityType user = tx.concepts().putEntityType("user").resolve();
user.setAbstract(tx).resolve();
// change the supertype of "employee" to "user"
EntityType employee = tx.concepts().getEntityType("employee").resolve();
employee.setSupertype(tx, user).resolve();
// change the supertype of "contractor" to "user"
EntityType contractor = tx.concepts().getEntityType("contractor").resolve();
contractor.setSupertype(tx, user).resolve();
// move "email" and "name" attribute types to be owned by "user" instead of "employee"
AttributeType email = tx.concepts().getAttributeType("email").resolve();
AttributeType name = tx.concepts().getAttributeType("name").resolve();
employee.unsetOwns(tx, email).resolve();
employee.unsetOwns(tx, name).resolve();
user.setOwns(tx, email).resolve();
user.setOwns(tx, name).resolve();
// rename "name" attribute type to "full-name"
name.setLabel(tx, "full-name").resolve();
// commit all schema changes in one transaction, which will fail if we violate any data validation
tx.commit();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
Connection* connection = connection_open_core("localhost:1729");
DatabaseManager* databaseManager = database_manager_new(connection);
Options* options = options_new();
Session* session = session_new(databaseManager, "access-management-db", Schema, options);
Transaction* tx = transaction_new(session, Write, options);
// create a new abstract type "user"
Concept* user = concept_promise_resolve(concepts_put_entity_type(tx, "user"));
void_promise_resolve(thing_type_set_abstract(tx, user));
// change the supertype of "employee" to "user"
Concept* employee = concept_promise_resolve(concepts_get_entity_type(tx, "employee"));
void_promise_resolve(entity_type_set_supertype(tx, employee, user));
// change the supertype of "contractor" to "user"
Concept* contractor = concept_promise_resolve(concepts_get_entity_type(tx, "contractor"));
void_promise_resolve(entity_type_set_supertype(tx, contractor, user));
// move "email" and "name" attribute types to be owned by "user" instead of "employee"
Concept* email = concept_promise_resolve(concepts_get_attribute_type(tx, "email"));
Concept* name = concept_promise_resolve(concepts_get_attribute_type(tx, "name"));
void_promise_resolve(entity_type_set_supertype(tx, contractor, user));
void_promise_resolve(thing_type_unset_owns(tx, employee, email));
void_promise_resolve(thing_type_unset_owns(tx, employee, name));
const Annotation* noAnnotations[1] = {NULL};
void_promise_resolve(thing_type_set_owns(tx, user, email, NULL, noAnnotations));
void_promise_resolve(thing_type_set_owns(tx, user, name, NULL, noAnnotations));
// rename "name" attribute type to "full-name"
void_promise_resolve(thing_type_set_label(tx, name, "full-name"));
// commit all schema changes in one transaction, which will fail if we violate any data validation
void_promise_resolve(transaction_commit(tx));
session_close(session);
options_drop(options);
database_manager_drop(databaseManager);
connection_close(connection);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
TypeDB::Driver driver = TypeDB::Driver::coreDriver("localhost:1729");
TypeDB::Options options;
TypeDB::Session session = driver.session("access-management-db", TypeDB::SessionType::SCHEMA, options);
TypeDB::Transaction tx = session.transaction(TypeDB::TransactionType::WRITE, options);
// create a new abstract type "user"
std::unique_ptr<EntityType> user = tx.concepts.putEntityType("user").get();
user->setAbstract(tx).get();
// change the supertype of "employee" to "user"
auto employee = tx.concepts.getEntityType("employee").get();
employee->setSupertype(tx, user.get()).get();
// change the supertype of "contractor" to "user"
auto contractor = tx.concepts.getEntityType("contractor").get();
contractor->setSupertype(tx, user.get()).get();
// move "email" and "name" attribute types to be owned by "user" instead of "employee"
std::unique_ptr<AttributeType> email = tx.concepts.getAttributeType("email").get();
std::unique_ptr<AttributeType> name = tx.concepts.getAttributeType("name").get();
employee->unsetOwns(tx, email.get()).get();
employee->unsetOwns(tx, name.get()).get();
user->setOwns(tx, email.get()).get();
user->setOwns(tx, name.get()).get();
// rename "name" attribute type to "full-name"
name->setLabel(tx, "full-name").get();
// commit all schema changes in one transaction, which will fail if we violate any data validation
tx.commit();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
using (ITypeDBDriver driver = Drivers.CoreDriver("localhost:1729"))
{
using (ITypeDBSession session = driver.Session("access-management-db", SessionType.Schema))
{
using (ITypeDBTransaction tx = session.Transaction(TransactionType.Write))
{
// create a new abstract type "user"
IEntityType user = tx.Concepts.PutEntityType("user").Resolve();
user.SetAbstract(tx).Resolve();
// change the supertype of "employee" to "user"
IEntityType employee = tx.Concepts.GetEntityType("employee").Resolve();
employee.SetSupertype(tx, user).Resolve();
// change the supertype of "contractor" to "user"
IEntityType contractor = tx.Concepts.GetEntityType("contractor").Resolve();
contractor.SetSupertype(tx, user).Resolve();
// move "email" and "name" attribute types to be owned by "user" instead of "employee"
IAttributeType email = tx.Concepts.GetAttributeType("email").Resolve();
IAttributeType name = tx.Concepts.GetAttributeType("name").Resolve();
employee.UnsetOwns(tx, email).Resolve();
employee.UnsetOwns(tx, name).Resolve();
user.SetOwns(tx, email).Resolve();
user.SetOwns(tx, name).Resolve();
// rename "name" attribute type to "full-name"
name.SetLabel(tx, "full-name").Resolve();
// commit all schema changes in one transaction, which will fail if we violate any data validation
tx.Commit();
}
}
}
Beautiful IDE
Dedicated Environment
TypeDB Studio is a cross-platform IDE for developing with TypeDB that offers a consistent experience across Windows, macOS, and Linux operating systems. Manage databases, build and execute queries, and explore results with an integrated experience.
Schema Manager
Use TypeDB Studio’s schema manager to simplify schema editing, with a graphical interface for defining and visualizing the types in your data model and their properties. Create, maintain, explore, and extend schemas with ease.
Data Visualizer
TypeDB Studio features an interactive visualizer for query results in a hypergraph format. Explore your schemas and data, and discover the root causes of data inferred by the reasoning engine in an easy-to-access visual manner using TypeDB’s Explanations.
Powerful CLI
Database Administration
Access essential database management tools directly from the command line with TypeDB Console. Create and delete databases, build and extend schemas, or define and undefine rules with ease.
Access Control
TypeDB Console simplifies user access control by providing a powerful command line tool, allowing administrators to easily grant or restrict access, and reset their passwords.
Data Management
TypeDB Console allows you to easily insert, modify, and query your data, enabling you to interface directly with the database to rapidly fix issues in production.
Resilient Clustering
Automated Failover
TypeDB’s automatic failover ensures continual service by seamlessly switching to a backup node if the primary becomes unresponsive, minimizing downtime and preventing data loss.
Automated Load Balancing
Active-active clustering in TypeDB distributes read transactions across all active nodes to evenly balance the workload, ensuring efficient use of resources, strong consistency, and high availability.
Resilient Sessions
All TypeDB clients have built-in session resiliency for communication with TypeDB clusters. If a client has an open session to a node that goes down, the session is seamlessly reallocated to another node when a new transaction is opened.
Cluster Resizing
Easily resize TypeDB clusters by seamlessly adding or removing nodes without any downtime, using the CLI for TypeDB Enterprise and GUI for TypeDB Cloud. TypeDB Cloud clusters can also be configured to resize automatically based on load.
Secured Environment
User Authentication
TypeDB includes robust password authentication with customizable policies for controlling password length, complexity, and expiration.
Network Encryption
TypeDB ensures ironclad security by employing TLS 1.3 with user-provided certificates, safeguarding client-server communication with robust network encryption.
Audit Logs
The security of TypeDB is enhanced through audit logs, keeping track of authentication events, user and database management events, sessions and transactions opened, and queries executed.
User Authorization
Restrict database management and querying permissions granted to users in your organization by assigning them roles.
Easy Management
Fully Managed
Enjoy all the features of TypeDB - without any of the work needed to install it. Using a fully managed cloud service, deploy in minutes with the click of a button. With scalable clusters, rest easy in the knowledge that nodes will automatically recover in the event of failure.
Cloud Agnostic
TypeDB offers global coverage on AWS, GCP and Azure, ensuring seamless accessibility and optimal performance for your data-driven success. And for medium/large clusters, connect your cloud provider's Marketplace account for seamless billing.
Collaborative Tools
Manage data across your users, teams, and organizations with TypeDB’s collaborative tools. Create projects to group clusters and control project access on a per-user or per-team basis.
Full Web Interface
TypeDB simplifies cloud instance management with a real-time web interface, serving as a powerful control panel for deployment and control of managed clusters. Manage clusters, projects, teams, and users. Access support in your browser.
Seamless Upgrades
Upgrade your TypeDB databases to the most recent version with no downtime and with all schema and data migrations automatically handled.
Seamless Backups
Backup and restore TypeDB databases using the TypeDB Cloud CLI or the web interface.
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
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.