Gel v6
To explore the new features, ensure you specify version 6.0 when initializing your project. Pre-release versions are not considered stable and will not be automatically suggested:
$
gel project init --server-version 6.0-rc.2
Local instances
To upgrade a local project, first ensure that your CLI is up to date with
gel cli upgrade
. Then run the following command inside the project
directory.
$
gel project upgrade --to-testing
Alternatively, specify an instance name if you aren't using a project:
$
gel instance upgrade -I my_instance
The CLI will check if your schema can migrate cleanly to Gel 6.0. If any issues are found, they will be reported.
Hosted instances
To upgrade a remote instance, we recommend the following dump-and-restore process:
-
Gel v6.0 supports PostgreSQL 14 or above. Verify your PostgreSQL version before upgrading Gel. If you're using Postgres 13 or below, upgrade Postgres first.
-
Spin up an empty 6.0 instance. You can use one of our deployment guides.
For Debian/Ubuntu, when adding the Gel package repository, use this command:
Copy$
echo deb [signed-by=/usr/local/share/keyrings/gel-keyring.gpg] \ https://packages.geldata.com/apt \ $(grep "VERSION_CODENAME=" /etc/os-release | cut -d= -f2) main \ | sudo tee /etc/apt/sources.list.d/gel.list
Copy$
sudo apt-get update && sudo apt-get install gel-6
For CentOS/RHEL, use this installation command:
Copy$
sudo yum install gel-6
In any required
systemctl
commands, replaceedgedb-server-5
withgel-server-6
.For Docker setups, use the
6.0
tag. -
Take your application offline, then dump your v5.x database with the CLI:
Copy$
gel 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. -
Restore the empty v6.x instance from the dump:
Copy$
gel 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.
New features
SQL write support
You can now use SQL DML (insert
, update
, delete
) when connecting to
your Gel instance via the PostgreSQL protocol. Our aim is to support most
typical use cases from tools like SQL ORMs and SQL clients.
This allows more developers to use Gel, leveraging our advanced data model, tooling, and high-performance connection management. Teams can migrate their existing SQL codebases to Gel without rewriting their queries. Once adopted, you can gradually take advantage of EdgeQL's powerful query capabilities.
Existing Gel users who already use EdgeQL can benefit too. While some SQL features like window functions, recursive queries, and explicit locking are not yet supported, you can use these features in SQL today. We will continue to add support for more features in the future.
In-place upgrade
We aim for this version to be the last requiring a full dump and restore process for major version upgrades. We understand that dump-and-restore is disruptive, so enabling in-place upgrades will make it easier for teams to upgrade more frequently.
Query performance observability
We now store statistics about query performance. These statistics are available
in sys::QueryStats
objects.
select sys::QueryStats {
query,
queryType,
tag,
plans,
total_plan_time,
mean_plan_time,
calls,
total_exec_time,
mean_exec_time,
} filter .branch.name = sys::get_current_branch();
More details to come in the reference documentation.
ext::postgis
We've added support for the popular PostGIS extension for PostgreSQL. This extension adds support for geographic objects and spatial data types.
std::net
We've introduced a new standard library module for sending network requests, initially supporting HTTP. This module schedules asynchronous requests and allows you to poll for responses.
ext::auth
We've introduced several new features to our authentication extension:
-
You can now configure generic OpenID Connect providers.
-
If using an OAuth provider that returns an
id_token
(like an OpenID Connect compatible provider), you will now receive that validated token in your callback. This simplifies using some of that data for your own User or Profile objects, saving a roundtrip to the identity provider. -
As an alternative (or in addition) to configuring SMTP for sending emails, you can now configure a webhook for various authentication lifecycle events. Use these webhooks to send custom emails, update analytics, or trigger other workflows.
-
Previously, a missing PKCE session during email verification was treated as an error. Now, we support verifying end-user emails from a different device than the one used to start the sign-up or sign-in process. To enable verification without PKCE, direct the end-user to attempt a login after verifying their email, which will initiate a new flow.
Previously, the application couldn't identify which identity was being created during sign-up until email verification was successful. When verification occurred on the same device, it concluded with an auth token, allowing the creation of a new
User
based on that token's identity. With the new process, where users are directed to sign in after email verification, there's no clear distinction between a regular sign-in (which shouldn't create a newUser
) and an interrupted sign-up (which should create a newUser
). To address this, we now return anidentity_id
in the sign-up response, enabling you to create aUser
type before the email is verified. -
We now configure a development-only SMTP provider for instances hosted on our Cloud. This SMTP proxy is heavily rate limited, and requires a fixed sender email address. It is intended to be used for development and testing purposes. Once you're ready to start sending real emails, you can configure your own SMTP provider. We hope this will make it easier to get started with a simple email-based authentication flow during early development.
-
Handle multiple WebAuthn email factors. (#7861)
-
Add logs to
auth
extension. (#7944) -
Migrate
ext::auth::SMTPConfig
tocfg::EmailProvider
. (#7942) -
Allow Magic Link to specify a custom link URL. (#8030)
-
Do not fail if SMTP provider is not configured. (#8228)
Breaking changes
-
We have moved our SMTP configuration into a new top-level
cfg::SMTPProviderConfig
configuration object. During the upgrade process, your existing SMTP configuration will be migrated to this new object. If you have any scripts that configure SMTP directly, update them to use the new object.
ext::ai
-
We've updated the built-in list of models from our first-party LLM providers to match the latest offerings from OpenAI, Anthropic, and Mistral.
-
We now pass LLM configuration query parameters through to the downstream provider.
-
Add delays to AI embeddings requests based on rate limits provided by provider.
-
Allow specifying underlying vector dimensions when creating an index. (#8068)
Simpler scoping rules
We've simplified the scoping rules for queries. See our RFC 1027 outlining the changes.
The RFC highlights two main reasons for removing path factoring: the need to simplify and enhance the language, and concerns about implementation. Path factoring is complex and makes it hard to quickly understand a query's behavior. It also undermines several key design principles of EdgeQL. Although EdgeQL is intended to be read from top to bottom, path factoring allows later parts of a query to change its meaning significantly.
By default in 6.0, we will generate new schemas that opt-in to the new scoping rules. Existing schemas will continue to use the old rules and emit warnings when queries that trigger the old behavior are encountered at query time.
Command Hooks
We've added hooks for gel
CLI operations. Certain operations like
switching branches or applying migrations have a profound effect on the state
of the database. These types of changes may occasionally need to be
synchronized with the rest of the project codebase. Whether it's a need to
re-run some schema introspection tools or some fixture validation or
re-generation tools, we now have a way to add hooks that will automatically
execute after certain commands in your project.
These hooks are declared in the gel.toml
(or deprecated edgedb.toml
) file. For example:
[hooks]
schema.update.after="scripts/extract_schema_docs.sh"
This would run scripts/extract_schema_docs.sh
script any time the schema
changes (whether due to branch switch or applying a migration). In this
example the script is meant to introspect the schema annotations and
automatically generate some documentation files used in the project. But the
mechanism is flexible enough to be used for automating a variety of project
tasks.
File Watchers
We've also added a way to respond to certain file changes within a project.
The gel.toml
(or deprecated edgedb.toml
) now supports [[watch]]
configuration to specify the files
being watched and the script to be executed when changes occur. In order to
enable this mode the gel
watch
command is used.
For example, the following configuration will watch for changes in the queries files and automatically attempt to re-generate the functions that allow executing these queries in a type-safe way:
[[watch]]
files = ["queries/*.edgeql"]
script = "npx @edgedb/generate queries"
Multiple [[watch]]
entires can be added to the gel.toml
(or deprecated edgedb.toml
) file, so that
you can fine-tune how your project responds to important file changes.
This changes how watch
command funcitons. By default, gel watch
will
start the watch process and monitor files specified in gel.toml
(or deprecated edgedb.toml
). In order to
access the old functionality of edgedb watch
(which was monitoring schema
file changes and automatically applying them to the database) you now need to
run gel watch --migrate
.
Additional changes
EdgeQL
-
Free objects no longer have an
id
property. This is a breaking change, though we expect the real-world impact to be minor. If you need a dynamically generated new ID for free objects, it can be added manually, using one of our UUID generation functions.Copyselect { id := uuid_generate_v1mc(), property := 'Some string', }
-
Add
__default__
keyword to refer to default value. (#7214)This keyword allows referring to the default value in
insert
andupdate
statements. For example, consider the following schema:Copytype Item { name: str { default := 'New item' } }
We can then insert a 'New item #1' by using the
__default__
value:Copydb>
insert Item {name := __default__ ++ ' #1'};
{default::Item {id: ebcfff62-eb91-11ef-a6b9-5ffb2f0b2940}}
Copydb>
select Item{name};
{default::Item {name: 'New item #1'}}
-
Add support for type expressions in intersections. (#7172)
Allow using
&
and|
in expressions like this:Copyselect Shape[is Circle | Triangle & HasRightAngle];
-
Add array modifying functions
array_set()
(added in 6.0) andarray_insert()
(added in 6.0). (#7427) -
Add trigonometry functions. (#8071)
Add
math::pi()
,math::acos()
,math::asin()
,math::atan()
,math::atan2()
,math::cos()
,math::cot()
,math::sin()
,math::tan()
. -
Allow
update
anddelete
on type intersections. (#7655)Given types
A
,B
, andC
, allows expressions such as:Copyupdate A[is B & C] set { foo := 123 }
-
Implement
\(expr)
-style string interpolation. (#8210)This enables the following expression:
Copydb>
select "1 + 1 = \(1 + 1)"
{'1 + 1 = 2'}
-
Allow complex types as function params. (#7759)
Allow functions such as:
Copyfunction foo(x: A | B) -> int64 using (x.n);
-
Search
std
for module name when usingwith
clause. (#7753, #7836, #7743)We've consolidated many of the built-in modules as sub-modules under the
std
umbrella. -
Support accessing link properties through
for
bindings. (#7805)Now you can write something like this:
Copyselect User { cards := (( for c in .deck[is HeartsCard] select (c.name, c@order) )), }
-
Enable DML in user-defined functions. (#7945)
It is now possible to create this kind of function:
Copyfunction add_foo(x: int64) -> Foo using (( insert Foo { val := x } ));
A new
Modifying
volatility level is introduced to represent this. (#7808) -
Support
drop extension package
of user-installed extensions. (#7926) -
Warn when a
filter
clause hasMany
cardinality. (#8089) -
Mark
assert_exists()
,assert_single()
, andassert_distinct()
functions as beingImmutable
. (#8292) -
Expose
administer statistics_update()
. (#8335)
Other changes
-
Require extension modules to live in
ext::
. (#7526) -
Use LRU/MRU to improve connection re-use. (#7583)
-
Change how globals affect internal alias names that may appear in introspection. (#7641)
-
Rename
sys::Database
tosys::Branch
. (#7653) -
Add
sys::Branch.last_migration
. (#7654) -
Record SDL in
schema::Migration
object. (#7673) -
Get
std::net::http
max connections from config. (#7767) -
Add extension
ext::pg_unaccent
. (#7741) -
Implement warnings in the server. (#7823)
-
Update the
ext::pgvector
extension. (#7812)Add
sparcevec
andhalfvec
types and update indexes and operators. -
Avoid computing globals json if not needed for inlined function. (#7920)
-
Allow volatile
with
in DML statements. (#7969) -
Make
admin
the default role instead ofedgedb
. (#8010) -
Support extension upgrades. (#7998)
-
Replace headers with annotations in Parse/Execute. (#8037)
-
Add TOML config file support. (#8121)
-
Allow tuples in GIN, GIST and BRIN indexes. (#8232)
-
Add a
cors-always-allowed-origins
option. (#8233)
Bug fixes
-
Tweak parser to correctly report certain missing semicolons. (#7252)
-
Fix regression in using some tuple literals as a default. (#7281)
-
Fix handling of enums in arrays and multi properties in GraphQL. (#3990)
-
Improve error message when casting to collections. (#7300)
-
Improve error when accessing a non-existent tuple field. (#7373)
-
Fix an ISE on some specific operations with arrays. (#7363)
-
Catch illegal aggregate calls in constraints and indexes during
migration create
. (#7343) -
Raise error when computed
global
is set or reset. (#7374) -
Improve error messages for casts,
is
, andintrospect
. (#7351) -
Fix recursive definition error when computed property refers to different object's computed property. (#7431)
-
Fix issue with abstract types, exclusive constraints, and
analyze
. (#7454) -
Fix an issue with deletion policies affecting properties. (#7675)
-
Fix errors when resolving type intersections. (#7662)
-
Fix issues with
branch
commands that arise from network issues. (#7773) -
Fix a regression involving optional arguments and
assert_exists()
. (#7798) -
Include more information in HTTP protocol errors. (#7817)
-
Raise error when passing multi cardinality args to modifying functions. (#7816)
-
Encode offset positions as integers in json error encoding. (#7842)
-
Make
configure current database
block until configuration is actually set. (#7865) -
Fix shape not being copied when inlining parameters. (#7872)
-
Garbage collect
std::net::http::ScheduleRequest
. (#7888) -
Fix error when dropping non overloaded function. (#7899)
-
Fix embedding data being stored with the wrong entry. (#7932)
-
Fix an obscure bug deleting doubly nested alias tuples. (#7956)
-
Fix an schema issue with deleting collections. (#7957)
-
Automatically create array types for all scalars to avoid introspeciton issues. (#7970)
-
Fix an edge case of calling value functions from range vars. (#7982)
-
Fix ISE when enumerating a call to an aggregate function. (#7988)
-
Fix free objects being materialized as if they are volatile. (#8000)
-
Fix aliases always being considered
Immutable
. (#8009) -
Fix ISE when taking intersection of types with pointers of the same name. (#8012)
-
Fix static types in subtypes under
sysconfig
. (#8054) -
Fix extension package installation on non
--testmode
servers. (#8096) -
Fix cache key of source. (#8103)
-
Fix handling of invalid link properties. (#8156)
-
Delete old
.s.EDGEDB.admin.XXX
sockets. (#8248) -
Fix broken error messages for type mismatches in a number of schema objects. (#8294)
-
Don't emit instance configs matching their defaults in
describe instance config
. (#8316)