Light
Dark
System
v2latest
v3dev
v2latest
v1

Migrations

EdgeDB’s baked-in migration system lets you painlessly evolve your schema throughout the development process. If you want to work along with this guide, start a new project with edgedb project init. This will create a new instance and create some empty schema files to get you started.

The recommended workflow has been improved in version 3.0, so if you’re running our beta, try the new workflow instead.

By convention, your EdgeDB schema is defined inside one or more .esdl files that live in a directory called dbschema in the root directory of your codebase.

.
├── dbschema
│   ├── default.esdl          # schema file (written by you)
│   └── migrations            # migration files (typically generated by CLI)
│       └── 00001.edgeql
│       └── ...
└── edgedb.toml

The schema itself is written using EdgeDB’s schema definition language.

Copy
type User {
  required property name -> str;
}

type Post {
  required property title -> str;
  required link author -> User;
}

It’s common to keep your entire schema in a single file, typically called default.esdl. However it’s also possible to split it across a number of .esdl files.

To spin up a new instance and populate it with an initial schema, execute the following commands in a fresh directory.

Copy
$ 
edgedb project init
Do you want to initialize a new project? [Y/n]
> Y
<additional prompts>
Copy
$ 
edgedb migration create
Created dbschema/migrations/00001.edgeql (id: <hash>)
Copy
$ 
edgedb migrate
Applied dbschema/migrations/00001.edgeql (id: <hash>)

As your application evolves, directly edit your schema files to reflect your desired data model.

Copy
type User {
  required property name -> str;
}

type BlogPost {
  property title -> str;
  required link author -> User;
}

type Comment {
  required property content -> str;
}

To generate a migration that reflects these changes, run edgedb migration create.

Copy
$ 
edgedb migration create

The CLI reads your schema file and sends it to the active EdgeDB instance. The instance compares the file’s contents to its current schema state and determines a migration plan. The migration plan is generated by the database itself.

This plan is then presented to you interactively; each detected schema change will be individually presented to you for approval. For each prompt, you have a variety of commands at your disposal. Type y to approve, n to reject, q to cancel the migration, or ? for a breakdown of some more advanced options.

Copy
$ 
edgedb migration create
Did you create object type 'default::Comment'? [y,n,l,c,b,s,q,?]
> y
Created dbschema/migrations/00002.edgeql (id: <hash>)

We’ve generated a migration file, but we haven’t yet applied it against our database! The following command will apply all unapplied migration files:

Copy
$ 
edgedb migrate
Applied m1virjowa... (00002.edgeql)

That’s it! You’ve created and applied your first EdgeDB migration. Your instance is now using the latest schema.

Depending on how the schema was changed, you may be prompted to provide an EdgeQL expression to map the contents of your database to the new schema. To see this happen, let’s make the title property required.

Copy
type User {
  required property name -> str;
}

type BlogPost {
  property title -> str;
  required property title -> str;
  required link author -> User;
}

Then we’ll create another migration.

Copy
$ 
edgedb migration create
Did you make property 'title' of object type
'default::BlogPost' required? [y,n,l,c,b,s,q,?]
> y
Please specify an expression to populate existing objects in order to make
property 'title' of object type 'default::Post' required:
fill_expr>

Because title is currently optional, the database may contain blog posts without a title property. The expression you provide will be used to assign a title to any post that doesn’t have one. We’ll just provide a simple default title: 'Untitled'.

fill_expr> 'Untitled'
Created dbschema/migrations/00002.edgeql, id:
m1yt3gbstvyfzy2rhqt5335ld6br2amw7ywqu2bvjiqsacbcdxzyya

Nice! It accepted our answer and created a new migration file 00002.edgeql. Let’s see what the newly created 00002.edgeql file contains.

Copy
CREATE MIGRATION m1yt3gbstvyfzy2rhqt5335ld6br2amw7ywqu2bvjiqsacbcdxzyya
  ONTO m1cvx47vntfoy24evwrdli7o5unarx2c5t3i2rfspd2qosi6d6iahq
{
  ALTER TYPE default::Post {
      ALTER PROPERTY title {
          SET REQUIRED USING ('Untitled');
      };
  };
};

We have a CREATE MIGRATION block containing an ALTER TYPE statement to make Post.title required. We can see that our fill expression ('Untitled') is included directly in the migration file.

Note that we could have provide an arbitrary EdgeQL expression! The following EdgeQL features are often useful:

assert_exists

This is an “escape hatch” function that tells EdgeDB to assume the input has at least one element.

fill_expr> assert_exists(.title)

If you provide a fill_expr like the one above, you must separately ensure that all movies have a title before executing the migration; otherwise it will fail.

assert_single

This tells EdgeDB to assume the input has at most one element. This will throw an error if the argument is a set containing more than one element. This is useful is you are changing a property from multi to single.

fill_expr> assert_single(.sheep)

type casts

Useful when converting a property to a different type.

cast_expr> <bigint>.xp

For guides on advanced migration workflows, refer to the following guides.

For more information on how migrations work in EdgeDB, check out the CLI reference or the Beta 1 blog post, which describes the design of the migration system.

Light
Dark
System