Gel v7
To explore the new features, ensure you specify version 7.0 when initializing your project. Pre-release versions are not considered stable and will not be automatically suggested:
$
gel project init --server-version 7.0Local 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-testingAlternatively, specify an instance name if you aren't using a project:
$
gel instance upgrade -I my_instanceThe CLI will check if your schema can migrate cleanly to Gel 7.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 v7.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 7.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.listCopy$
sudo apt-get update && sudo apt-get install gel-7For CentOS/RHEL, use this installation command:
Copy$
sudo yum install gel-7In any required
systemctlcommands, replaceedgedb-server-6withgel-server-7.For Docker setups, use the
7.0tag. -
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.
Breaking Changes
SQL adapter access policies on by default
The default value of apply_access_policies_pg has been changed
from false to true.
This means that by default, EdgeQL access policies will be applied when running SQL queries over the SQL protocol connection.
To accomodate third-party tools that cannot be configured to run
configuration commands, we have introduced the
apply_access_policies_pg_default field to Role in order to
override this:
CREATE SUPERUSER ROLE pg_connector {
# ...
SET apply_access_policies_pg_default := false;
}Third-party SQL tools can use the pg_connector role and access policies will be disable.
Session configuration for GraphQL and EdgeQL HTTP interfaces
The GraphQL and EdgeQL HTTP interfaces now support passing in session configuration variables.
If you are exposing HTTP/GraphQL endpoints to users and relying on them not being able to perform configuration, you will need to instead have them use roles that have not been given permission to modify sensitive configs.
Simpler scoping rules deprecation warnings
In 6.0, we began simplifying our scoping rules. See our RFC 1027 outlining the changes.
In 7.0, we emit a warning when creating a migration if the schema does
not contain using simple_scoping; or using warn_old_scoping;.
We plan to remove the old scoping in 8.0.
New features
Role Based Access Control (RBAC)
Gel 7.0 introduces more fine-grained access controls. It is now possible to create non-SUPERUSER roles, with limited permissions.
Non-SUPERUSER roles deliberately choose the "secure by default" end of the security-vs-convenience tradeoff, and are extremely locked down by default.
CREATE ROLE my_role {
# ...
SET permissions := {
sys::perm::data_modifiction,
sys::perm::query_stats,
cfg::perm::configure_timeouts,
cfg::perm::configure_apply_access_policies,
ext::auth::perm::auth_read,
ext::auth::perm::auth_write,
};
};Will create a user that can do DDL, look at query stats, configure timeouts and whether to use access policies, and read and write the auth extension tables.
See our RFC 1029 for more details on the changes.
-
Look up role permissions when executing queries. (#8760)
-
Make role permission computation look at all ancestors (#8784)
-
Add sys::data_modification to grant non-superusers the ability to run DML. (#8771)
-
rbac: Implement RBAC permissions for session configs (#8806)
-
rbac: Make the HTTP interfaces aware of the current role (#8809)
-
rbac: Support required_permissions for function (#8812)
-
rbac: Restrict dump, restore, ADMINISTER, DESCRIBE, ANALYZE (#8810)
-
rbac: Make a branch_config permission but require superuser for system (#8822)
-
rbac: Make system-wide DDL require SUPERUSER (#8823)
-
rbac: Add a branches field to Role to restrict a role to certain branches (#8830)
-
rbac: Add sys::perm::superuser which is granted to superusers only. (#8853)
-
rbac: Add permissions to stdlib objects and functions. (#8846)
-
Add permissions to sys types and functions. (#8865)
-
Add
global sys::current_role(#8889)
Auth extension: One-time code-based flow
Gel's ext::auth module now supports one-time codes (OTCs) as an alternative to email links for all email-based authentication flows. This feature dramatically simplifies the end user experience by allowing users to enter a short numeric code from their email instead of clicking a link. The primary benefit is solving the common cross-device usability problem where users start authentication on one device (like their desktop) but check email on another device (like their phone). With one-time codes, users can easily transcribe the code between devices without worrying about PKCE session mismatches that would cause link-based authentication to fail.
The one-time code verification method covers all forms of email-based flows in EdgeDB that traditionally use links, including email verification for account registration, password reset flows, magic link authentication, and email verification for WebAuthn registration. When configured to use the Code verification method, the system decouples the PKCE session from the initial authentication request - the code generation is PKCE-agnostic, while the verification step handles PKCE creation and completion. This allows for both same-device flows (where the existing PKCE session is reused) and cross-device flows (where a new PKCE session is created during verification). The codes are securely hashed, include rate limiting protection, and automatically expire after 10 minutes.
The feature is fully backwards compatible, with the default verification_method remaining as Link to ensure existing projects continue working without changes. To enable one-time codes for magic link authentication, you can configure your provider like this:
configure current branch insert ext::auth::MagicLinkProviderConfig {
verification_method := ext::auth::VerificationMethod.Code,
};The same verification_method property is also available for EmailPasswordProviderConfig and WebAuthnProviderConfig, allowing you to standardize the verification experience across all your email-based authentication methods. See RFC 1043: Email-Based One-Time Code Authentication for more details on the motivations, and the Auth docs.
Other features
-
Support required link properties (#8735)
-
Allow (most) unparenthesized statements in calls, etc (#8763)
-
Implement sys::approximate_count() (#8692)
-
Implement
splat_strategyqualifier for pointers (#8757) -
Add http schedule_request with json body. (#8724)
-
Support graphql over the binary protocol (#8878)
-
One-time code implementation for
ext::auth(#8905) -
Add
math::expandmath::e(#8982) -
Support
FOR OPTIONALas a "semi-undocumented" feature (#8991) -
Add support for max batch size to AI embedding models. (#9040)
-
Add a
.?>linkoperator to dereference link while suppressing "hidden by policy" (#9101) -
Configurable query cache size (#9104)
-
Add Discord OAuth
promptparameter with default (#9111) -
Support specifying session configs in http and graphql endpoints (#9110)
Additional changes
Fixes
-
Fix schema type inconsistencies with collection aliases (#8672)
-
Fix mangled type names leaking into introspectable names (#8772)
-
Drop bionic support (#8328)
-
Check that function parameter and return types exist when migrating. (#8386)
-
Add hint to partial path errors if anchor is available. (#8380)
-
Implement permissions in access policies over SQL adapter (#8837)
-
Support creating indexes concurrently (#8747)
-
Fix WITH computation duplication in auth module (#8851)
-
Access policies for link tables over SQL adapter (#8849)
-
Fix params with union types producing ISEs (#8863)
-
Support intersection and complex composite types in SDL parameters. (#8864)
-
Add
std::identifierannotations to abstract operators (#8862) -
Fix modifying and dropping inherited AI indexes (#9041)
-
Fix some issues with overloading AI and FTS indexes (#9049)
-
Fix /rag on subtypes (#9044)
-
Make SET REQUIRED USING (…) work on link properties (#9015)
-
Fix OTC flow for built-in auth UI (#8913)
-
Loosen Magic Code register/email data requirements (#9000)
-
Fix missing return_data in no email found case (#9004)
-
Fix inplace upgrade when
authis being used (#9008) -
Allow Magic Link sign in to register new user (#9007)
-
Return json from magic code authenticate endpoint if no callback_url is given (#9012)
-
Return identity_id when registering new Magic Link (#9039)
-
Fix in-place upgrade repairs (#9073)
-
Fix creating branch when a schema has nested arrays (#9074)
-
Check for explicit id write presence in a slightly more resilient way (#9090)
-
Fix work_mem setting over SQL adapter (#9094)
-
Fix applying type intersection to aliases and iterators (#9096)
-
Fix an interaction between aliases and optional globals with a default (#9109)