Light
Dark
System
v4latest
v5dev
v4latest
v3
v2
v1

Schema

EdgeDB schemas are declared using SDL (EdgeDB’s Schema Definition Language).

Your schema is defined inside .esdl files. It’s common to define your entire schema in a single file called default.esdl, but you can split it across multiple files if you wish.

By convention, your schema files should live in a directory called dbschema in the root of your project.

Copy
# dbschema/default.esdl

type Movie {
  required title: str;
  required director: Person;
}

type Person {
  required name: str;
}

Syntax highlighter packages/extensions for .esdl files are available for Visual Studio Code, Sublime Text, Atom, and Vim.

EdgeDB’s baked-in migration system lets you painlessly evolve your schema over time. Just update the contents of your .esdl file(s) and use the EdgeDB CLI to create and apply migrations.

Copy
$ 
edgedb migration create
Created dbschema/migrations/00001.esdl
Copy
$ 
edgedb migrate
Applied dbschema/migrations/00001.esdl.

For a full guide on migrations, refer to the Creating and applying migrations guide.

A migration consists of a sequence of imperative schema-modifying commands like create type, alter property, etc. Collectively these commands are known as DDL (data definition language). We recommend using SDL and the migration system when building applications, however you’re free to use DDL directly if you prefer.

Instance

An EdgeDB instance is a collection of databases that store their data in a shared directory, listen for queries on a particular port, and are managed by a running EdgeDB process. Instances can be created, started, stopped, and destroyed locally with the EdgeDB CLI.

Database

Each instance can contain several databases, each with a unique name. At the time of creation, all instances contain a single default database called edgedb. All incoming queries are executed against it unless otherwise specified.

Module

Each database has a schema consisting of several modules, each with a unique name. Modules can be used to organize large schemas into logical units. In practice, though, most users put their entire schema inside a single module called default.

Copy
module default {
  # declare types here
}

You may define nested modules using the following syntax:

Copy
module dracula {
    type Person {
      required property name -> str;
      multi link places_visited -> City;
      property strength -> int16;
    }

    module combat {
        function fight(
          one: dracula::Person,
          two: dracula::Person
        ) -> str
          using (
            (one.name ?? 'Fighter 1') ++ ' wins!'
            IF (one.strength ?? 0) > (two.strength ?? 0)
            ELSE (two.name ?? 'Fighter 2') ++ ' wins!'
          );
    }
}

Here we have a dracula module containing a Person type. Nested in the dracula module we have a combat module which will be used for all the combat functionality for our game based on Bram Stoker’s Dracula we built in the Easy EdgeDB textbook.

Name resolution

When referencing schema objects from another module, you must use a fully-qualified name in the form module_name::object_name.

The following module names are reserved by EdgeDB and contain pre-defined types, utility functions, and operators.

  • std: standard types, functions, and operators in the standard library

  • math: algebraic and statistical functions

  • cal: local (non-timezone-aware) and relative date/time types and functions

  • schema: types describing the introspection schema

  • sys: system-wide entities, such as user roles and databases

  • cfg: configuration and settings

You can chain together module names in a fully-qualified name to traverse a tree of nested modules. For example, to call the fight function in the nested module example above, you would use dracula::combat::fight(<arguments>).

Light
Dark
System

We use ChatGPT with additional context from our documentation to answer your questions. Not all answers will be accurate. Please join our Discord if you need more help.