Ask AI

EdgeDB v5

To play with the new features, make sure to specify version 5.0 when initializing the project as pre-release versions are not considered stable and will not be automatically suggested:

edgedb project init

Local and Cloud instances

To upgrade a local project, first ensure that your CLI is up to date with edgedb cli upgrade. Then run the following command inside the project directory.

edgedb project upgrade

Alternatively, specify an instance name if you aren’t using a project.

edgedb instance upgrade -I my_instance

The CLI will first check to see if your schema will migrate cleanly to EdgeDB 5.0. If the upgrade check finds any problems, it will report them back to you.

Hosted instances

To upgrade a remote (hosted) instance, we recommend the following dump-and-restore process.

  1. EdgeDB v5.0 supports PostgreSQL 14 (or above). So check the version of PostgreSQL you are using before upgrading EdgeDB. If you’re using Postgres 13 or below, you should upgrade Postgres first.

  2. Spin up an empty 5.0 instance. You can use one of our deployment guides.

    Under Debian/Ubuntu, when adding the EdgeDB package repository, use this command instead:

    echo deb [signed-by=/usr/local/share/keyrings/edgedb-keyring.gpg] \ \
      $(grep "VERSION_CODENAME=" /etc/os-release | cut -d= -f2) main \
      | sudo tee /etc/apt/sources.list.d/edgedb.list

    Use this command for installation under Debian/Ubuntu:

    sudo apt-get update && sudo apt-get install edgedb-5

    Under CentOS/RHEL, use this installation command:

    sudo yum install edgedb-5

    In any required systemctl commands, replace edgedb-server-4 with edgedb-server-5.

    Under any Docker setups, supply the 5.0 tag.

  3. Take your application offline, then dump your v4.x database with the CLI

    edgedb dump --dsn <old dsn> --all --format dir my_database.dump/

    This will dump the schema and contents of your current database to a directory on your local disk called my_database.dump. The directory name isn’t important.

  4. Restore the empty v5.x instance from the dump

    edgedb restore --all my_database.dump/ --dsn <new dsn>

    Once the restore is complete, update your application to connect to the new instance.

    This process will involve some downtime, specifically during steps 2 and 3.

We’ve added an ext::ai extension for handling the integration of EdgeDB with various AI backends such as: OpenAI, Mistral and Anthropic.

There is a special ext::ai::index that can be used to delegate the search functionality of EdgeDB objects to a specific AI search provider.

The function ext::ai::to_context(object: anyobject) evaluates the expression of the specific ext::ai::index defined on the passed object type and returns it.

The function ext::ai:search(object: anyobject, query: array<float32>) searches the specified objects using the associated AI search provider and the specified semantic query representation.

There are also two HTTP API points for interacting with the data:

  • /ai/embeddings

  • /ai/rag

EdgeDB 5.0 adds branching functionality in order to help bridge the gap between the code (and schema) managed by version control systems and the actual development database.

The first thing to note is that we’re updating our terminology and replacing the old (and potentially confusing) term database with branch. This means that the old create database and drop database commands are considered deprecated in favor of create empty branch and drop branch, respectively. However, the new branch commands provide more options and functionality than the old database commands:

  1. create empty branch <newbranch>

    The most basic command creates a new branch with an empty schema (exactly the same as create database).

  2. create schema branch <newbranch> from <oldbranch>

    This command creates a new branch and copies the schema of an existing branch to it. Only the schema is copied; the data is still empty and needs to be populated separately.

  3. create data branch <newbranch> from <oldbranch>

    This command creates a new branch and copies both the schema and the data of an existing branch to it.

  4. drop branch <oldbranch>

    Removes an existing branch from the instance.

  5. alter branch <oldname> rename to <newname>

    The command to rename a branch.

The intent is to provide a mechanism that helps developers keep branches of the database corresponding to the code branches that introduce certain schema changes.

With these new commands, here’s how we envision developers using them to manage “feature” branches:

  1. Create a new “feature” VCS branch (a clone of the “main” branch) and a corresponding “feature” EdgeDB branch.

  2. Work on the “feature” branch, add migrations, etc.

  3. When it is time to merge the feature work back into the main branch we want to arrange things so that the “feature” branch is in a state that is a simple fast-forward w.r.t the “main” branch.

  4. In order to achieve the above state we need to make sure the “main” code branch as well as the EdgeDB branch are both up-to-date.

  5. Then we want to rebase the “feature” branch code on top of the “main” branch code.

  6. After that we need to replicate the same rebase operation with the EdgeDB branch. Our CLI tools may need to first clone the “main” branch with the data into a “temp” branch. Then we can introspect the migration histories of the “temp” and “feature” branches so that we can establish where they diverge. Take all the divergent migrations from the “feature” branch and apply them to the “temp” branch. If the operation is successful, drop the “feature” branch and rename “temp” to “feature”. We now have successfully rebased “feature” branch on top of “main”.

  7. Since the state of “feature” is now a straightforward fast-forward w.r.t. the “main” branch we can finally merge “feature” back into main in VCS and then merge the EdgeDB branch as well (or rename the “feature” EdgeDB branch to “main”, if the old branch is no longer needed).

We’ve added edgedb branch commands to our CLI as well that create, copy, rename, drop, and rebase EdgeDB branches.

A new HNSW (Hierarchical Navigable Small Worlds) index has been added to the pgvector extension. Just like IVFFlat indexes there are three flavors of HNSW corresponding to different operations:

  • ext::pgvector::hnsw_euclidean

  • ext::pgvector::hnsw_ip

  • ext::pgvector::hnsw_cosine

We have also updated the mechanism for tuning all of the indexes provided in this extension. The probes (for IVFFlat) and ef_search (for HNSW) parameters can now be accessed via the ext::pgvector::Config object.

The current config values can be found by examining the extensions link of the cfg::Config object. Notice that in order to see the specific extension config properties you need to use the type filter [is ext::pgvector::Config]:

select cfg::Config.extensions[is ext::pgvector::Config]{*};
  ext::pgvector::Config {
    id: 12b5c70f-0bb8-508a-845f-ca3d41103b6f,
    probes: 1,
    ef_search: 40,

Updating the value can be done using the configure session command:

configure session
set ext::pgvector::Config::probes := 5;

It is also possible to restore the default config value:

configure session reset ext::pgvector::Config::probes;

We’re bringing two popular “passwordless” authentication schemes to our auth extension: the Web Authentication API (commonly known as WebAuthn or Passkeys), as well as email-based “magic links”.

We’ve also added two popular chat platforms to our list of supported OAuth providers: Slack and Discord.

We also have the following updates:

  • Allow passing WebAuthn user_handle in request body (#6942)

  • Handle WebAuthn challenge having multiple factors (#6945)

  • Explicitly pass WebAuthn credential properties (#6975)

  • Return JSON for magic link register (#6974)

  • Ensure built-in UI verification redirect includes code (#6982)

  • Ensure WebAuthn redirect matches expected shape (#6987)

  • Fallback to PKCE RFC parameter names (#7034)

  • Add optional PKCE challenge in email verification (#7037)

The query compilation cache is now persisted across restarts, and cached queries are automatically recompiled after migrations are applied.

We’ve also improved processing of large schemas and migrations.

  • Allow omitting union in for if the body is a statement. (#6810)

    If the for query body involves a statement such as insert, update, delete, etc., you no longer need to write the union keyword and add parentheses around the statement expression:

    for name in {'Alice', 'Billie', 'Cameron'}
    union (
    insert User { name := name }
  • Add administer vacuum() command. (#6663)

    The command administer vacuum() can take a list of object types, multi properties, multi links or links with link properties. There is also a named only argument full that reclaims storage to the OS rather than just to the database. All of the arguments can be omitted. In case no target types are specified, everything accessible to the user will be vacuumed.

    The vacuum command will use already allocated space better so that it will reduce the growth rate of the database, or will reclaim storage space to the operating system with full. Since certain aspects such as multi properties and links as well as links with link properties require additional underlying tables they can be listed separately when reclaiming storage space.

    If the full option is set to true, reclaimed storage is returned to the OS, but it can take much longer and will exclusively lock the underlying tables.

    For example, the following command will vacuum the User type reclaiming storage to the OS:

    administer vacuum(User, full := true)
  • Integer/UUID to bytes conversion. (#6553)

    It is now possible to convert int16, int32, int64, and uuid to bytes and vice-versa using the corresponding conversion functions.

    Use the to_bytes() to convert values into bytes:

    select to_bytes(<int32>31, Endian.Big);
    select to_int32(b'\x01\x02\x00\x07', Endian.Big);
    select to_bytes(<uuid>'1d70c86e-cc92-11ee-b4c7-a7aa0a34e2ae');
    select to_uuid(
  • Add bytes option to array_join. (#6918)

    The array_join() can now operate on bytes the same way it operates on str:

    select array_join([b'\x01', b'\x02', b'\x03'], b'\xff');
  • Support closing all connections to a database on drop database. (#6780)

  • Add a std::get_current_branch() function. (#7001)

  • Add cfg::Config.query_cache_mode (#7158)

  • Fix issues with empty sets leaking out of optional scopes (#6747)

  • Fix an SDL scalar type dependency bug

  • Suppress idle transaction timeout during migrations (#6760)

  • Use a consistent interface for ext::auth errors (#6751)

  • Stop recording extension version in dumps (#6787)

  • For any index changes don’t attempt to update the index, drop and recreate instead (#6797, #6843)

  • Fix duration/memory config in config objects (#6827)

  • Properly report errors involving newly created types (#6852)

  • Changes to vector length in migrations result in suggesting a drop/create (#6882)

  • Report topological cycle errors in migrations as real errors (#6883)

  • Make constraint error details contain useful information for developers (#6796)

  • Fix interaction between DML and if...then...else (#6917)

  • Don’t leak objects out of access policies when used in a computed global (#6926)

  • Allow grouping to have trailing comma (#7002)

  • Fix computed single scalar globals (#6999)

  • Fix ISE when creating an alias with a name that already exists (#6946)

  • Fix parser at unrecoverable errors (#7046)

  • Improve error when applying a shape to a parameter (#7044)

  • Skip creating @source/@target on derived views improving performance (#7051)

  • Fix issues with cached global shapes and global cardinality inference (#7062)

  • Add error when a constant set is used in singleton mode (#7065)

  • Fix update rewrites on types that are children of updated type (#7073)

  • Make escaping strings more consistent (#7059)

  • Allow an update to trigger an insert of the same type, and vice versa (#7082)

  • Set “Connection: close” for non-keep-alive requests (#7087)

  • Fix volatility of fts::search (#7106)

  • Allow trailing commas and semicolons in most places (#6963)

  • Drop special handling of type intersection in cardinality inference (#7089)

  • Add error when enum length exceeds 63 (#7123)

  • Fix two issues directly reading pointers from a group (#7130)

  • Check singleton expressions in constraints and indexes (#7128)

  • Fix two bugs affecting unions in computed links (#7139)

  • Fix two group bugs involving using clauses (#7143)

  • Fix deserialization of persistent cache entries after upgrade (#7203)

  • Accept session changes in transactions (#7187)

  • Fix ISEs in constant detection for fts::with_options (#7192)

  • pg_ext: don’t yield NoData in SimpleQuery (#7200)

  • Make changing fts and ai indexes work consistently in migrations (#7218)

  • Include fts and ai shadow index columns in dumps (#7235)

  • Make ai::search have integrated sort and hit indexes (#7242)

  • Fix upgrading from rc1 that had been updated itself from a beta (#7245)

  • Allow multiple authentication methods per transport in --default-auth-method. (#7224)

    We now allow multiple authentication methods to be tried in sequence (according to the specified order in --default-auth-method).

  • Drop ad-hoc TLS requirement from JWT and Password auth (#7231)

  • Reject ai indexes that have different parameters than in parent types (#7229)

  • Allow except in link constraints. (#7250)

  • Force return cast on range get upper and lower functions. (#7251)

  • Prevent dump hangups from leaving stray Postgres queries. (#7262)

  • Switch EDGEDB_DEBUG_EDGEQL_TEXT_IN_SQL to encode string as json (#7267)

  • Don’t inject exclusive conflict checks for updates without children. (#7271)

  • Fix doing a no-op update to an exclusive multi pointer with children. (#7272)

  • Fix constraint handling when pointer has cardinality or computedness changed. (#7279)

  • Fix regression in using some tuple literals as a default. (#7281)

  • Make link properties (including @source/@target) work in conflict selects. (#7284)

  • Create key derivation function for signing each different kind of JWTs in the auth extension (#7285)

    This avoids accidentally being able to use other (short-lived) JWT tokens as the auth_token JWT directly.

  • Improve error message when creating union with incompatible types. (#7278)

  • Fix handling of enums in arrays and multi properties for GraphQL. (#3990)

  • Fix modifying global that is used in a policy on a type it refers to. (#7310)

  • Fix a bug involving globals in a somewhat complex interaction with policies. (#7314)

  • Set content-type header for AI extension errors. (#7324)

  • Fix an UNLESS CONFLICT on links performance regression. (#7349)

  • Fix EDGEDB_SERVER_CONFIG configuration of enum values. (#7350)

  • Only decode url encoded slashes in db/branch name after splitting path into parts. (#7352)

  • Fix an issue with collection types that affected some migrations. (#7375)

  • Fix recompilation slowdowns after several migrations (#7099)

  • Fix dumps of types that have both AI and FTS indexes (#7405)

  • Fix single-tenant metrics not to filter by tenant (#7385)

  • Fix rewrite expressions using __specified__ sometimes generating InvalidReferenceError. (#7392)

  • Raise error when using query params in schema. (#7400)

  • Add expression to index friendly name. (#7401)

  • Treat target and link properties as different when expanding splats. (#7402)

  • Remove redundant primary key constraint on ‘id’. (#7418)

  • workflows: Use an explicit label when selecting runners for builds (#7416)

  • Log errors raised when handling ext::ai HTTP requests (#7436)

  • ai: Properly forward non-successful responses from non-streaming chat (#7440)

  • Fix ai::to_context duplication (#7464)

  • Support configuring more arguments with env vars (#7470)

  • Use SQL’s ON CONFLICT to implement UNLESS CONFLICT more often (#7472)

  • Fix a race condition where older database configs can overwrite newer ones (#7485)

  • Allow subdomains in redirects in the auth extension (#7488)

  • Fix tenant shutdown in multi-tenant mode (#7495)

  • Fix migration creation when adding a new base class with certain constraints (#7508)

  • Fix pg_dump of an empty schema using the SQL adapter (#7445)

  • Fix SQL adapter COPY command (#7446)

  • Fix interaction of implicit limit with explicit OFFSET (#7509)

  • Make persistent query cache work for queries that have no constant literals in them (#7237)

  • Unbreak cache recompilation after a restart (#7515, #7520)

  • Add a auto_rebuild_query_cache_timeout config (#7518)