3.2.3
Released on Jul 21, 2026
SurrealDB 3.2.3 is the third patch release on the 3.2 line. It is a focused round of fixes: root- and namespace-level bearer signin now dispatches correctly through the public entrypoint, and DEFINE PARAM permission predicates that dereference the authenticated record (for example $auth.admin) resolve correctly instead of erroring. For SurrealDS (Enterprise), it fixes a view-change livelock that could stall a cluster whose recovery rounds legitimately outlast the retry timer, and makes the retry window configurable.
v3.2.3 contains no catalog or on-disk layout changes, so you can upgrade in place from 3.2.0 / 3.2.1 / 3.2.2.
v3.2.3 is a patch release with authentication and permission fixes, plus a SurrealDS (Enterprise) view-change liveness fix, on top of 3.2.2.
Bug fixes
Authentication & permissions
Root and namespace bearer signin. Bearer (and access-method) signin now routes correctly for root- and namespace-level access through the public
signin()entrypoint, not only through the level-specific helpers, so a client sending{ [ns], ac, key }signs in as expected.DEFINE PARAMpermissions that read$auth. ADEFINE PARAMwhosePERMISSIONSpredicate dereferences the authenticated record (for example$auth.admin = true) now evaluates under a database context, matchingDEFINE FUNCTION. Permitted params resolve correctly, and a denied param returns a proper permission error instead of a misleadingDatabaseEmptyerror.
SurrealDS (Enterprise)
View-change livelock (Enterprise). Fixed a livelock where a view-change round whose records-bearing transfer and merge legitimately outlasted the retry timer was repeatedly invalidated by participants' own timers, stalling the cluster at timer cadence. The retry timer's escalation is now progress-gated — it defers the view bump while a round demonstrably advances — with a view-gap backoff covering the signal-less transfer phase. The retry window is now configurable via
SURREAL_DS_VIEW_CHANGE_RETRY_MIN_MS,SURREAL_DS_VIEW_CHANGE_RETRY_MAX_MS, andSURREAL_DS_VIEW_CHANGE_BACKOFF_CEILING_MS.
Breaking changes
None — catalog and KV on-disk layouts are unchanged from 3.2.0 / 3.2.1 / 3.2.2, so you can upgrade in place.
Upgrade or install
Get SurrealDB v3.2.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.3.
You can upgrade your SurrealDB Cloud instance to v3.2.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.2
Released on Jul 21, 2026
SurrealDB 3.2.2 is the second patch release on the 3.2 line. It hardens the RPC layer — opt-in durable RPC sessions (KV-backed with TTL expiration on the HTTP transport) and bounded, self-cleaning WebSocket transactions — alongside fixes to committed live-query cache keying, transaction-conflict reporting, and index-build resilience under shutdown and memory pressure. For SurrealDS (Enterprise), it also fixes a recovery livelock and a missed-phantom case in OCC range validation.
v3.2.2 contains no catalog or on-disk layout changes, so you can upgrade in place from 3.2.0 / 3.2.1.
v3.2.2 is a patch release with RPC session and transaction improvements, a round of engine bug fixes, and SurrealDS (Enterprise) recovery and concurrency fixes, on top of 3.2.1.
Improvements
Durable RPC sessions (opt-in). RPC sessions can now be made durable so they persist beyond a single connection, enabled opt-in at the protocol level (
RpcProtocol). On the stateless HTTP transport, durable sessions are KV-backed and expire via a TTL, so an HTTP session is persisted and reclaimed reliably instead of living only in a single node's memory.Bounded, self-cleaning WebSocket transactions. Client-managed transactions over the WebSocket RPC are now bounded and cleaned up automatically, so an abandoned client transaction no longer lingers holding resources.
Bug fixes
Query engine
Fixed committed live-query cache keying so live queries are keyed correctly.
Fixed
TransactionConflicterror-kind preservation, so a transaction conflict is surfaced as a conflict rather than being flattened into a generic error.
Indexing
Hardened concurrent index builds against node shutdown and memory pressure, so an interrupted build cleans up and rescans rather than leaving a partial index behind.
SurrealDS (Enterprise)
Recovery livelock (Enterprise). Fixed a livelock during recovery that could prevent a SurrealDS node from making progress.
OCC range validation (Enterprise). Fixed a missed-phantom case in optimistic-concurrency-control range validation, tightening isolation correctness for range reads.
Breaking changes
None — catalog and KV on-disk layouts are unchanged from 3.2.0 / 3.2.1, so you can upgrade in place.
Newer patch available
Upgrade to 3.2.3
You are viewing the 3.2.2 changelog. A newer patch in this release line is available - we recommend running 3.2.3 for the latest fixes and improvements.
3.2.1
Released on Jul 10, 2026
SurrealDB 3.2.1 is the first patch release on the 3.2 line. It fixes a batch of streaming-executor parity gaps (numeric-index FETCH, idiom recursion limits, indexed COUNT), a GraphQL input-coercion regression, FLEXIBLE field handling, and an in-memory backend that never reclaimed superseded versions — alongside two fixes from SurrealDB's internal security review.
v3.2.1 contains no catalog or on-disk layout changes, so you can upgrade in place from 3.2.0. The security fixes are enabled by default and we recommend all users on the 3.2 line upgrade.
v3.2.1 is a patch release with 2 security fixes, 7 bug fixes, and a round of performance and stability work on top of 3.2.0.
Improvements
Faster cosine HNSW index builds. Stored-vector norms are now cached during HNSW construction, giving roughly a 2.2x speed-up when building cosine-distance vector indexes.
Faster full-text
OR-in-ANDqueries. A full-textOR-of-matches nested inside anANDis now driven from a multi-index full-text union (UnionIndexScanover theFullTextScanbranches) instead of driving from a non-full-text equality index and re-checking theORas a per-row filter.Resumable concurrent index builds. Concurrent index builds now persist an initial-scan continuation checkpoint and yield cooperatively, so a same-generation takeover resumes the scan from where it stopped instead of wiping the partial index and rescanning from scratch.
Bug fixes
Query engine
Fixed the in-memory backend never reclaiming superseded MVCC versions and delete tombstones on non-versioned (zero-retention) datastores. The background GC worker — the only place the in-memory engine reclaims old versions — was disabled whenever retention was zero, so memory grew unbounded on write/delete-heavy workloads; it now runs unless versioning is enabled with unlimited retention. A misleading versioning/retention startup log was corrected at the same time.
Fixed index-backed
COUNT/ keys-only scans returning wrong counts when theWHEREclause had multiple conjuncts. Such a scan is now only used when the index answers the wholeWHEREclause, rather than counting a single index branch and dropping the otherANDconjuncts (or summing overlappingORbranches).Fixed
FETCHwith a numeric array index (for exampleFETCH refs[0]) silently fetching nothing on the streaming executor. Positive in-range indices are now fetched correctly, while negative and out-of-range indices skip the fetch as expected.Fixed the
collect,path,shortest, andrepeatrecursion strategies silently truncating instead of raising the idiom recursion limit error when an unbounded recursion exhausts the system limit, matching thedefaultstrategy and the legacy engine. An explicit user bound equal to the system limit still stops silently.
Schema
FLEXIBLEon aDEFINE FIELDis now applied to every object shape a field can take — nested literal objects, anobjectwrapped in anarrayoroption, and anobjectinside aneitherunion — and is propagated to auto-generated nested field kinds.FLEXIBLEon a type that contains no object is now rejected at definition time rather than silently having no effect.
GraphQL
Fixed GraphQL input strings being re-parsed as SurrealQL, which turned numeric- or time-looking values such as
"9000"or"10:00"into non-string values and broke coercion againstTYPE string. Input strings insideobject-typed fields are now kept verbatim; only genuinedatetime/duration/uuidformats are still coerced.
MCP
Fixed the HTTP
/mcpendpoint rejecting requests with403 Forbidden: Host header is not allowedwhen served on a non-loopback hostname. TheHost-header allowlist is now configurable viaSURREAL_MCP_ALLOWED_HOSTS(a comma-separated list that replaces the loopback default) andSURREAL_MCP_ALLOW_ALL_HOSTS(an escape hatch for deployments behind a trusted proxy). The default remains loopback-only.
Security
This release addresses two issues surfaced through SurrealDB's internal security review process. The fix for each ships in v3.2.1 and is enabled by default.
Argon2
PASSHASHexposed viaINFOHigh —INFO FOR ROOT/NS/DBandINFO FOR USERleaked each user's stored Argon2 password hash, which is offline-crackable and directly replayable. The hash is now redacted to[REDACTED]on theINFO/ RPC read surface. The privilegedsurreal exportpath is intentionally unaffected, so hash-preserving exports still round-trip.KNN
SELECTpermission bypass on the streaming executor — A KNN / ANN query with a pushed-downWHEREfilter did not apply the table's per-candidateSELECTpermission inside the ANN search on the streaming executor, letting a record user probe restricted fields by crafting aWHEREand observing the result count, order, or timing. The per-candidate permission gate is now enforced during the search, matching the legacy engine, so hidden rows are skipped before the condition can observe them.
Breaking changes
Catalog and KV on-disk layouts are unchanged from 3.2.0, so you can upgrade in place. The item below is a behaviour change that can affect tooling relying on the previous output.
INFO no longer returns user password hashes
As part of the PASSHASH redaction fix above, INFO FOR ROOT / NS / DB and INFO FOR USER now return [REDACTED] in place of the stored Argon2 hash. If you have tooling that read the real hash from INFO output, use the privileged surreal export path instead, which continues to preserve the actual hash.
Newer patch available
Upgrade to 3.2.3
You are viewing the 3.2.1 changelog. A newer patch in this release line is available - we recommend running 3.2.3 for the latest fixes and improvements.
3.2.0
Released on Jul 2, 2026
SurrealDB 3.2.0 is the second minor release on the 3.0 line. It opens up an entirely new query surface — experimental ISO GQL (OpenGQL) graph querying — and makes every graph query surface reachable beyond its HTTP route, while continuing the query-engine and scan-path performance work started in 3.1.
It also adds a faster and safer server startup path with a dedicated /ready probe, a background reaper that takes large REMOVE NAMESPACE / DATABASE / INDEX operations off the request path, write-time enforcement of a typed id field, and capability-gated nested query evaluation with eval::surql / eval::gql.
The 3.1 → 3.2 catalog and on-disk layouts are unchanged, so existing 3.1.x deployments can upgrade in place. A few behaviours and defaults have been tightened — notably write-time id typing, read-only view tables, and side-effect-free permission predicates — see Breaking changes for details.
v3.2.0 is the first stable release on the 3.2 line, landing 7 headline features, a further round of query-engine performance work, and 4 new security fixes, on top of everything already shipped across the 3.1.x patch series.
Highlights
🕸 Experimental ISO GQL (OpenGQL) querying
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 compiles parsed GQL directly onto SurrealDB's internal execution plan — reads become a binding-table plan and mutations run through the native document pipeline — so GQL runs on the same streaming engine as SurrealQL with no SurrealQL text generated or re-parsed.
Queries are 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).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.Data mutations. The surface is no longer read-only:
INSERT,SET,REMOVE, andDELETElet a single GQL query read and write in one transaction. A query is a linear program — an ordered sequence ofMATCH/OPTIONAL MATCHreads and data-modifying statements in any interleaving, optionally ending in aRETURN— 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). A record'sid, 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 {…}).
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.
This is an early, experimental surface — expect it to keep evolving.
🔌 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.
🧩 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 and returns a single value (wrap multiple statements 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.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.
🚀 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 the deferred startup import has finished and 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.ASSERTon the recordidfield is enforced again, including viaALTER FIELD.
⚡ Query-engine and scan-path performance
3.2 continues the executor performance work from 3.1, focused on the scan and graph-traversal hot paths.
Graph-traversal predicate pushdown.
WHEREfilters on graph traversals are pushed intoGraphEdgeScan, so constrained->edge->vertexwalks filter during the scan instead of materialising and filtering afterwards.Pre-decode scan filter improvements. The pre-decode filter now peeks record headers slice-directly in its wire comparator, uses a fused slice-direct opener for the record data field, and pre-encodes fused-clause needle wire to drop a per-row allocation.
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, and sort keys are extracted once per row instead of being recomputed per comparison.TCP_NODELAYis enabled on the HTTP/WS listener to disable Nagle's algorithm.
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.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.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.Improved performance for large SurrealDS clusters (Enterprise). Improved performance for SurrealDS clusters larger than 5 nodes.
Dependency updates.
wasmtime/wasmtime-wasiadvanced to 46.0.1 andammonia/anyhowwere bumped, clearing a batch of RustSec advisories (RUSTSEC-2026-0182,-0188,-0190,-0193); the Surrealism crate versions were also bumped.
Bug fixes
[Query Engine]Fixed a duplicate edge record id that could be produced during graph operations.[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.[Query Engine]Fixed collect recursion with a minimum depth greater than 1 losing nodes revisited within range in cyclic graphs.[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. 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.[Access]RejectDURATION FOR TOKEN NONEonTYPE RECORDaccess (via bothDEFINEandALTER), since record-access tokens can be consumed by third parties and must have an expiration.[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.[Config]Fixed thememory_thresholdconfigmap parse path rejecting human-readable byte suffixes (for example256mor1g) and emitting a spurious configuration-parse warning; the configmap path now shares the same suffix-aware helper as the environment-variable path.
Security
This release addresses a set of issues surfaced through SurrealDB's internal security review process and external reviewers. The fix for each ships in v3.2.0 and is enabled by default. In addition to the items below, the 3.2 line carries every security fix already shipped across the v3.1.1–v3.1.5 patch series.
Cross-tenant custom API access bypass High - GHSA-848m-r628-vrxw
Malformed SurrealML file import can panic and terminate the server process Moderate - GHSA-jwr6-6444-28xv
Side effects in
PERMISSIONSpredicates allow writes without permission Moderate - GHSA-66r2-5gwj-gxm2JWKS network-capability bypass via an allowed hostname resolving to a private IP (SSRF) Moderate - GHSA-5x4x-2946-qr67
Breaking changes
Catalog and KV on-disk layouts are unchanged from 3.1.x, so you can upgrade in place. The items below are behaviour or default changes that can affect clients or SurrealQL that relied on previous semantics. The 3.2 line also inherits the breaking changes introduced across the 3.1.x patch series (notably file access now being denied by default unless file_allowlist is configured).
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.
View tables are read-only
Direct writes (CREATE / INSERT / UPDATE / UPSERT / RELATE / DELETE) to a computed DEFINE TABLE … AS SELECT … view table are now 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.
PERMISSIONS predicates must be side-effect free
As part of the fix for GHSA-66r2-5gwj-gxm2, a stored PERMISSIONS … WHERE clause can no longer perform data-modifying statements. Clauses containing a direct write are rejected at DEFINE time, and writes reached indirectly (for example through a called function body) are blocked at query time. Read-only predicates, read-only helper-function calls, and read-only subqueries are unaffected.
OpenGQL is experimental and opt-in
The new /gql route, gql RPC method, and eval::gql are gated behind the opengql experimental capability and are disabled by default. The surface is expected to keep changing and should not be relied on in production. Likewise, eval::surql / eval::gql are gated behind the deny-by-default eval-query capability and are not enabled by --allow-all.
Newer patch available
Upgrade to 3.2.3
You are viewing the 3.2.0 changelog. A newer patch in this release line is available - we recommend running 3.2.3 for the latest fixes and improvements.
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.
Newer patch available
Upgrade to 3.2.3
You are viewing the 3.2.0-beta.3 changelog. A newer patch in this release line is available - we recommend running 3.2.3 for the latest fixes and improvements.
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.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.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.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.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