3.2.0-beta.3
Released on Jul 1, 2026
This is the third beta in the 3.2 series. It extends the experimental ISO GQL surface with data mutations, adds a new capability-gated way to evaluate nested queries from within a function, and rolls up a round of stability, correctness, and dependency updates.
Everything introduced in v3.2.0-beta.1 and v3.2.0-beta.2 — experimental ISO GQL (OpenGQL) querying, GraphQL/OpenGQL over RPC and MCP, the faster and safer server startup path, the background reaper for large REMOVE operations, write-time enforcement of a typed id field, and the query-engine performance work — is included in this build and is not repeated here.
Highlights
GQL mutations for OpenGQL (INSERT / SET / REMOVE / DELETE)
The experimental ISO GQL surface, previously read-only, now supports the four ISO data-modifying statements, so a single GQL query can read and write in one transaction.
A query is now a linear program: an ordered sequence of
MATCH/OPTIONAL MATCHread clauses and data-modifying statements in any interleaving, optionally ending in aRETURN. The binding table threads through every step in textual order, and aMATCHafter a mutation re-scans the live (post-write) state in the same transaction.SETsets a property (SET a.p = v) or replaces all user properties (SET a = {…}, aCONTENT-style replace). The recordid, and an edge'sin/out, are preserved and cannot be reassigned;SET a:Labelis rejected because a record belongs to exactly one table.REMOVEunsets a property (REMOVE a.p);REMOVE a:Labelis rejected.DELETEremoves a matched node or edge.NODETACH(the ISO default) errors if the node still has connected edges;DETACH DELETEcascades them.INSERTcreates new nodes and edges, e.g.INSERT (a:Label {…})-[:Edge {…}]->(b:Label {…}). A leadingINSERTruns once; with a precedingMATCHit runs once per binding row.Mutations execute through SurrealDB's native document pipeline (the same one
CREATE/UPDATE/DELETE/RELATEuse), so record- and field-level permissions, field validation, events, indexes, references, and live-query notifications all apply. A mutation-only query (noRETURN) returns an empty result; with aRETURN, projected bindings reflect the post-mutation state (a deleted binding becomesnull).This remains part of the experimental,
opengql-gated surface, reachable over the same/gqlHTTP route andgqlRPC method.
Nested query evaluation with eval::surql and eval::gql
New built-in functions evaluate a runtime query string inside the caller's transaction, behind a dedicated, deny-by-default capability.
eval::surql("…")evaluates a SurrealQL string (statements are wrapped in a block, soLETbindings thread across them and the final value is returned);eval::gql("…")evaluates an ISO GQL string and additionally inherits theopengqlexperimental gate.Both are governed by a new eval-query capability, exposed as
--allow-eval-query/--deny-eval-query, which takes one or more subject classes (guest,record,system, or*). For example:--allow-eval-query system.The capability is denied for every subject by default and is not turned on by
--allow-all— it must be enabled explicitly. Because anevalcall is itself an arbitrary query, it must also pass the existing arbitrary-query gate, so eval can never grant more query power than the front door already allows. The eval subject is derived from the current execution auth, so a record-scoped caller invoking an owner-defined function that callsevalis still treated asrecord.eval rejects transaction-control and session-level top-level statements (
BEGIN/CANCEL/COMMIT/USE/LIVE/KILL/OPTION/SHOW/access), bounds nesting depth, and honours protected parameter names for caller bindings.
Improvements
Resumable index builds. Index builds orphaned by a crashed or lease-expired owner node are now resumed by another node, so an interrupted build no longer stalls indefinitely.
DiskANN pending-key sharding. DiskANN pending keys are now sharded to remove a scan hotspot on the vector index, and the
diskanndependency was upgraded to0.54.0.
Bug fixes
[Query Engine]View (computedAS SELECT) tables are now read-only — directCREATE/INSERT/UPDATE/UPSERT/RELATE/DELETEagainst a view table is rejected rather than silently corrupting the materialized view. If you have code that wrote directly to a view table, it will now return an error.[Schema]Restored enforcement ofASSERTon the recordidfield, including viaALTER FIELD, so assertions declared onidare applied at write time again.[Functions]duration::secs,duration::millis,duration::micros, andduration::nanosno longer overflow to incorrect (often negative) values for very large durations. More broadly, integer-to-number conversions that exceed a signed 64-bit integer are now stored asdecimalinstead of being silently truncated, and values too large fordecimalraise an error rather than wrapping — so these functions now return adecimalfor counts beyond thei64range.
Breaking changes
This beta introduces no new intentional breaking changes beyond those already listed for v3.2.0-beta.1 (write-time enforcement of a typed id, and the experimental, opt-in OpenGQL surface). Note, however, that direct writes to view tables are now rejected (see Bug fixes); any code relying on that previously-unsupported behaviour will need to be updated.
Upgrade or install
Get SurrealDB v3.2.0-beta.3
Pick how you want to install or upgrade. Surrealist can update connected instances in place, or choose a platform below to copy a CLI command for v3.2.0-beta.3.
You can upgrade your SurrealDB Cloud instance to v3.2.0-beta.3 effortlessly through the Surrealist app.
- Open the Surrealist app
- Select your organisation and instance
- On the dashboard, click on the "Upgrade" button
- Your instance will be updated and restarted automatically
3.2.0-beta.2
Released on Jun 26, 2026
This is the second beta in the 3.2 series — a small, incremental build on top of v3.2.0-beta.1. It improves performance for larger SurrealDS clusters and fixes configuration parsing for human-readable memory_threshold byte suffixes.
Items tagged [Enterprise] refer to the SurrealDB Enterprise product. Everything else applies to community.
Everything introduced in v3.2.0-beta.1 — experimental ISO GQL (OpenGQL) querying, GraphQL/OpenGQL over RPC and MCP, the faster and safer server startup path, the background reaper for large REMOVE operations, write-time enforcement of a typed id field, and the query-engine performance work — is included in this build and is not repeated here.
Improvements
[Enterprise]Improved performance for SurrealDS clusters larger than 5 nodes.
Bug fixes
[Config]Fixed thememory_thresholdconfigmap parse path rejecting human-readable byte suffixes (for example256mor1g) and emitting a spurious configuration-parse warning for theMEMORY_THRESHOLDkey. The configmap path now shares the same suffix-awareparse_memory_thresholdhelper as the environment-variable path, so suffixed values are honoured without warnings.
Breaking changes
This beta introduces no new breaking changes beyond those already listed for v3.2.0-beta.1 (write-time enforcement of a typed id, and the experimental, opt-in OpenGQL surface).
Newer patch available
Upgrade to 3.2.0-beta.3
You are viewing the 3.2.0-beta.2 changelog. A newer patch in this release line is available - we recommend running 3.2.0-beta.3 for the latest fixes and improvements.
3.2.0-beta.1
Released on Jun 24, 2026
This is the first beta in the 3.2 series. It opens the line with a brand-new query surface — experimental ISO GQL (OpenGQL) querying — alongside a faster and safer server startup path, a background reaper that takes large REMOVE operations off the request path, write-time enforcement of a typed id field, and a further round of query-engine performance work.
The items below cover what is new in the 3.2 line. The fixes already released across the v3.1.1–v3.1.5 patches are also included in this build but are not repeated here.
Highlights
Experimental ISO GQL querying (OpenGQL)
A first cut of standards-track ISO GQL graph querying lands as an experimental feature, built as a self-contained pipeline in surrealdb-core (opengql) with its own lexer, parser, and AST. A lowering stage translates the parsed GQL onto SurrealDB's internal SurrealQL AST, so lowered queries execute through the same pipeline as SurrealQL (no SurrealQL text is generated or re-parsed).
Queries can be sent over a new
POST /gqlHTTP route or the newgqlRPC method.The language is gated behind the
opengqlexperimental capability and is off by default. Enable it with--allow-experimental opengql(orSURREAL_CAPS_ALLOW_EXPERIMENTAL=opengql). ThegqlHTTP route itself follows the usual route capabilities, which allow all routes by default.MATCHexecution (v2). Pattern matching runs through aMatchPlanbinding-table executor that supports multi-pattern joins,OPTIONAL MATCH, and per-path traversal rather than a single fused chain.Aggregates and
GROUP BY.count,sum,collect,min,max, andavgare supported, with grouping.Path search.
SHORTEST,ALL, andANYpath search are available, along with path modes onMATCH.
This is an early, experimental surface — expect it to evolve across the 3.2 beta cycle.
GraphQL and OpenGQL over RPC and MCP
The graph query surfaces are now reachable beyond their HTTP routes.
Added a
graphqlRPC method, so GraphQL queries can be issued over the WebSocket/RPC protocol instead of only the/graphqlHTTP endpoint.Both GraphQL and OpenGQL are now exposed through the first-party MCP server, letting MCP clients run graph queries directly.
Faster, safer server startup
surreal start now separates "the listener is up" from "the datastore is ready to serve", which makes startup behave well behind orchestrators like Kubernetes.
The HTTP/WS listener is bound before the startup import runs, and the startup import runs concurrently rather than blocking the bind.
A new
/readyendpoint reports readiness: it returns200only once deferred startup work (import and credential setup) has finished and — when a heartbeat budget is configured — the node's cluster heartbeat is fresh; otherwise it returns503(or500if the heartbeat can't be read).While the instance is still starting up, user-facing endpoints return
503, but/,/status(liveness),/health(backend reachability),/version,/metrics, and/readystay reachable so probes and scrapers keep working throughout startup.
Background reaper for REMOVE NAMESPACE / DATABASE / INDEX
Large structural removals no longer reclaim their data inline on the statement's transaction.
REMOVE NAMESPACE,REMOVE DATABASE, andREMOVE INDEXnow delete only the catalog definition and enqueue the orphaned data prefix; a background reaper destroys the data out-of-band. This keeps the removing statement fast and bounded regardless of how much data the namespace/database/index held.The reaper honours a snapshot-safety grace period before physically reclaiming data, so read transactions whose snapshot predates the
REMOVEcan finish first. On TiKV this is coordinated with the MVCC GC safepoint — the effective grace ismax(reclaim_grace, tikv_gc_lifetime), so raising the GC lifetime alone can never make reclaim unsafe.New configuration:
--reclaim-interval/SURREAL_RECLAIM_INTERVAL(default60s) — how often the reaper runs.--reclaim-grace/SURREAL_RECLAIM_GRACE(default10m) — minimum age before tombstoned data is physically reclaimed.
Typed id enforced at write time
DEFINE FIELD id is now a first-class typed field that is validated when records are written.
A
TYPEon theidfield is enforced at write time: creating a record whose id does not match the declared type fails with a coercion error (for example, anintid field rejectsbadtype:notanint).DEFAULTon theidfield is supported and is evaluated against the session and coerced to the declared kind (for exampleTYPE uuid DEFAULT rand::uuid()), butDEFAULT ALWAYSis rejected because an explicit id must always win.An explicitly supplied id (via the target record id or the data clause) always takes precedence over the
DEFAULT.
Improvements
DEFINE ANALYZER ... FUNCTIONhardening. Tightened the function-backed analyzer path: SurrealML model functions are rejected, Surrealism module (mod::) functions require thesurrealismexperimental capability, theFUNCTIONclause expects a function name rather than a function call (fn::some, notfn::some()), and the analyzer function is validated to return a string.Configurable full-text doc-ids batch size. The batch size used to allocate sequence-based document IDs for the concurrent full-text index is now configurable via
SURREAL_FTS_DOC_IDS_BATCH_SIZE(default1000); larger batches reduce ID-allocation coordination between nodes.Orphaned LIVE query metric. A new counter tracks orphaned
LIVE SELECTregistrations, making it easier to spot live queries that have lost their owning session.Surrealism version in the CLI. A new
surreal module versionsubcommand reports the Surrealism (WASM plugin) runtime version, separate fromsurreal versionwhich continues to report the SurrealDB server version.[$](last element) on sets. Sets now support the[$]last-part accessor, matching arrays.SHOW CHANGESsurfaces delete pre-images. WithINCLUDE ORIGINAL, the change feed now includes the pre-image of deleted records inSHOW CHANGESoutput.record::exists()andLIMIT 0cleanups.record::exists()now always returns a boolean, returningfalsefor a record on an undefined table instead of erroring. Separately,SELECT ... LIMIT 0no longer short-circuits the table-existence check: it now behaves like the same query withoutLIMIT 0(for example, erroring on a nonexistent table in strict mode) rather than returning an empty array.Query-engine performance.
DELETEskips the reference purge scan entirely when the schema proves no references can exist.Filtered kNN queries cut record I/O via batching, bounded prefetch, and missing-record skipping.
TopK threshold pushdown skips record decode for rows that fall below the
ORDER BY+LIMITheap threshold.Zero-copy table scans via a per-row visitor (
for_each) on the KV layer.Sort keys are extracted once per row instead of being recomputed per comparison.
The pre-decode scan filter peeks record headers slice-directly in its wire comparator.
TCP_NODELAYis enabled on the HTTP/WS listener to disable Nagle's algorithm.
Dependency updates.
wasmtimebumped to 44.0.3 (addressesRUSTSEC-2026-0182), and the Surrealism crate versions were bumped.
Bug fixes
[Access]RejectDURATION FOR TOKEN NONEonTYPE RECORDaccess (via bothDEFINEandALTER), since record-access tokens can be consumed by third parties and must have an expiration rather than being non-expiring.[Define API]Reject duplicate methods inDEFINE API, whether declared across separateFORclauses or within a single one.[KV/TiKV]Fan multi-get results to every position of a duplicate key, so a batched lookup that contains the same key more than once now fills each slot correctly.[KV/TiKV]Treat the TSO physical component as milliseconds rather than microseconds when interpreting timestamps.[Query Engine]Fixed a duplicate edge record id that could be produced during graph operations.
Breaking changes
Typed id is enforced at write time
If you have a DEFINE FIELD id with a TYPE, writes whose record id does not match the declared type are now rejected with a coercion error. Records created before this change are unaffected on read, but inserts/updates that previously slipped through with a mismatched id type will now fail. Review any DEFINE FIELD id definitions to confirm the declared type matches the ids you actually write.
OpenGQL is experimental and opt-in
The new /gql route and gql RPC method are gated behind the opengql experimental capability and are disabled by default. The surface is expected to change during the 3.2 beta cycle and should not be relied on in production.
Newer patch available
Upgrade to 3.2.0-beta.3
You are viewing the 3.2.0-beta.1 changelog. A newer patch in this release line is available - we recommend running 3.2.0-beta.3 for the latest fixes and improvements.
Our newsletter
Get tutorials, AI agent recipes, webinars, and early product updates in your inbox every two weeks
No newer release line.
3.1
Updated Jun 19, 2026