Skip to content
New

Introducing Scale: SurrealDB Cloud for high availability and scale

Learn more

1/4

LATEST STABLE

Release 3.2

7 patch releases · Latest 3.2.3 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…

3.2.3

LATEST STABLE

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

  • 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 PARAM permissions that read $auth. A DEFINE PARAM whose PERMISSIONS predicate dereferences the authenticated record (for example $auth.admin = true) now evaluates under a database context, matching DEFINE FUNCTION. Permitted params resolve correctly, and a denied param returns a proper permission error instead of a misleading DatabaseEmpty error.

  • 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, and SURREAL_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.

  1. Select your organisation and instance
  2. On the dashboard, click on the "Upgrade" button
  3. 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

  • Fixed committed live-query cache keying so live queries are keyed correctly.

  • Fixed TransactionConflict error-kind preservation, so a transaction conflict is surfaced as a conflict rather than being flattened into a generic error.

  • 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.

  • 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.

View 3.2.3 release notes

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-AND queries. A full-text OR-of-matches nested inside an AND is now driven from a multi-index full-text union (UnionIndexScan over the FullTextScan branches) instead of driving from a non-full-text equality index and re-checking the OR as 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

  • 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 the WHERE clause had multiple conjuncts. Such a scan is now only used when the index answers the whole WHERE clause, rather than counting a single index branch and dropping the other AND conjuncts (or summing overlapping OR branches).

  • Fixed FETCH with a numeric array index (for example FETCH 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, and repeat recursion strategies silently truncating instead of raising the idiom recursion limit error when an unbounded recursion exhausts the system limit, matching the default strategy and the legacy engine. An explicit user bound equal to the system limit still stops silently.

  • FLEXIBLE on a DEFINE FIELD is now applied to every object shape a field can take — nested literal objects, an object wrapped in an array or option, and an object inside an either union — and is propagated to auto-generated nested field kinds. FLEXIBLE on a type that contains no object is now rejected at definition time rather than silently having no effect.

  • 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 against TYPE string. Input strings inside object-typed fields are now kept verbatim; only genuine datetime / duration / uuid formats are still coerced.

  • Fixed the HTTP /mcp endpoint rejecting requests with 403 Forbidden: Host header is not allowed when served on a non-loopback hostname. The Host-header allowlist is now configurable via SURREAL_MCP_ALLOWED_HOSTS (a comma-separated list that replaces the loopback default) and SURREAL_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 PASSHASH exposed via INFO HighINFO FOR ROOT / NS / DB and INFO FOR USER leaked each user's stored Argon2 password hash, which is offline-crackable and directly replayable. The hash is now redacted to [REDACTED] on the INFO / RPC read surface. The privileged surreal export path is intentionally unaffected, so hash-preserving exports still round-trip.

  • KNN SELECT permission bypass on the streaming executor — A KNN / ANN query with a pushed-down WHERE filter did not apply the table's per-candidate SELECT permission inside the ANN search on the streaming executor, letting a record user probe restricted fields by crafting a WHERE and 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.

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.

View 3.2.3 release notes

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

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 /gql HTTP route or the new gql RPC method.

  • The language is gated behind the opengql experimental capability and is off by default. Enable it with --allow-experimental opengql (or SURREAL_CAPS_ALLOW_EXPERIMENTAL=opengql).

  • MATCH execution (v2). Pattern matching runs through a MatchPlan binding-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, and avg are supported, with grouping.

  • Path search. SHORTEST, ALL, and ANY path search are available, along with path modes on MATCH.

  • Data mutations. The surface is no longer read-only: INSERT, SET, REMOVE, and DELETE let a single GQL query read and write in one transaction. A query is a linear program — an ordered sequence of MATCH / OPTIONAL MATCH reads and data-modifying statements in any interleaving, optionally ending in a RETURN — and a MATCH after a mutation re-scans the live, post-write state in the same transaction.

    • SET sets a property (SET a.p = v) or replaces all user properties (SET a = {…}, a CONTENT-style replace). A record's id, and an edge's in/out, are preserved and cannot be reassigned; SET a:Label is rejected because a record belongs to exactly one table.

    • REMOVE unsets a property (REMOVE a.p); REMOVE a:Label is rejected.

    • DELETE removes a matched node or edge. NODETACH (the ISO default) errors if the node still has connected edges; DETACH DELETE cascades them.

    • INSERT creates 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 / RELATE use), 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.

The graph query surfaces are now reachable beyond their HTTP routes.

  • Added a graphql RPC method, so GraphQL queries can be issued over the WebSocket/RPC protocol instead of only the /graphql HTTP endpoint.

  • Both GraphQL and OpenGQL are now exposed through the first-party MCP server, letting MCP clients run graph queries directly.

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 so LET bindings thread across them and the final value is returned); eval::gql("…") evaluates an ISO GQL string and additionally inherits the opengql experimental 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 an eval call 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.

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 /ready endpoint reports readiness: it returns 200 only once the deferred startup import has finished and the node's cluster heartbeat is fresh; otherwise it returns 503 (or 500 if 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 /ready stay reachable so probes and scrapers keep working throughout startup.

Large structural removals no longer reclaim their data inline on the statement's transaction.

  • REMOVE NAMESPACE, REMOVE DATABASE, and REMOVE INDEX now 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 REMOVE can finish first. On TiKV this is coordinated with the MVCC GC safepoint — the effective grace is max(reclaim_grace, tikv_gc_lifetime), so raising the GC lifetime alone can never make reclaim unsafe.

  • New configuration:

    • --reclaim-interval / SURREAL_RECLAIM_INTERVAL (default 60s) — how often the reaper runs.

    • --reclaim-grace / SURREAL_RECLAIM_GRACE (default 10m) — minimum age before tombstoned data is physically reclaimed.

DEFINE FIELD id is now a first-class typed field that is validated when records are written.

  • A TYPE on the id field is enforced at write time: creating a record whose id does not match the declared type fails with a coercion error (for example, an int id field rejects badtype:notanint).

  • DEFAULT on the id field is supported and is evaluated against the session and coerced to the declared kind (for example TYPE uuid DEFAULT rand::uuid()), but DEFAULT ALWAYS is 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.

  • ASSERT on the record id field is enforced again, including via ALTER FIELD.

3.2 continues the executor performance work from 3.1, focused on the scan and graph-traversal hot paths.

  • Graph-traversal predicate pushdown. WHERE filters on graph traversals are pushed into GraphEdgeScan, so constrained ->edge->vertex walks 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.

  • DELETE skips 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 + LIMIT heap 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_NODELAY is enabled on the HTTP/WS listener to disable Nagle's algorithm.

Improvements

  • DEFINE ANALYZER ... FUNCTION hardening. Tightened the function-backed analyzer path: SurrealML model functions are rejected, Surrealism module (mod::) functions require the surrealism experimental capability, the FUNCTION clause expects a function name rather than a function call (fn::some, not fn::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 diskann dependency was upgraded to 0.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 (default 1000); larger batches reduce ID-allocation coordination between nodes.

  • Orphaned LIVE query metric. A new counter tracks orphaned LIVE SELECT registrations, making it easier to spot live queries that have lost their owning session.

  • Surrealism version in the CLI. A new surreal module version subcommand reports the Surrealism (WASM plugin) runtime version, separate from surreal version which continues to report the SurrealDB server version.

  • [$] (last element) on sets. Sets now support the [$] last-part accessor, matching arrays.

  • SHOW CHANGES surfaces delete pre-images. With INCLUDE ORIGINAL, the change feed now includes the pre-image of deleted records in SHOW CHANGES output.

  • record::exists() and LIMIT 0 cleanups. record::exists() now always returns a boolean, returning false for a record on an undefined table instead of erroring. Separately, SELECT ... LIMIT 0 no longer short-circuits the table-existence check: it now behaves like the same query without LIMIT 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-wasi advanced to 46.0.1 and ammonia / anyhow were 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 (computed AS SELECT) tables are now read-only — direct CREATE / INSERT / UPDATE / UPSERT / RELATE / DELETE against 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 of ASSERT on the record id field, including via ALTER FIELD, so assertions declared on id are applied at write time again.

  • [Functions] duration::secs, duration::millis, duration::micros, and duration::nanos no 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 as decimal instead of being silently truncated, and values too large for decimal raise an error rather than wrapping.

  • [Access] Reject DURATION FOR TOKEN NONE on TYPE RECORD access (via both DEFINE and ALTER), since record-access tokens can be consumed by third parties and must have an expiration.

  • [Define API] Reject duplicate methods in DEFINE API, whether declared across separate FOR clauses 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 the memory_threshold configmap parse path rejecting human-readable byte suffixes (for example 256m or 1g) 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.1v3.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 PERMISSIONS predicates allow writes without permission Moderate - GHSA-66r2-5gwj-gxm2

  • JWKS 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).

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.

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.

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.

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.

View 3.2.3 release notes

3.2.0-beta.3

PRE-RELEASE

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

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 MATCH read clauses and data-modifying statements in any interleaving, optionally ending in a RETURN. The binding table threads through every step in textual order, and a MATCH after a mutation re-scans the live (post-write) state in the same transaction.

  • SET sets a property (SET a.p = v) or replaces all user properties (SET a = {…}, a CONTENT-style replace). The record id, and an edge's in/out, are preserved and cannot be reassigned; SET a:Label is rejected because a record belongs to exactly one table.

  • REMOVE unsets a property (REMOVE a.p); REMOVE a:Label is rejected.

  • DELETE removes a matched node or edge. NODETACH (the ISO default) errors if the node still has connected edges; DETACH DELETE cascades them.

  • INSERT creates new nodes and edges, e.g. INSERT (a:Label {…})-[:Edge {…}]->(b:Label {…}). A leading INSERT runs once; with a preceding MATCH it runs once per binding row.

  • Mutations execute through SurrealDB's native document pipeline (the same one CREATE/UPDATE/DELETE/RELATE use), so record- and field-level permissions, field validation, events, indexes, references, and live-query notifications all apply. A mutation-only query (no RETURN) returns an empty result; with a RETURN, projected bindings reflect the post-mutation state (a deleted binding becomes null).

  • This remains part of the experimental, opengql-gated surface, reachable over the same /gql HTTP route and gql RPC method.

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, so LET bindings thread across them and the final value is returned); eval::gql("…") evaluates an ISO GQL string and additionally inherits the opengql experimental 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 an eval call 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 calls eval is still treated as record.

  • 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 diskann dependency was upgraded to 0.54.0.

Bug fixes

  • [Query Engine] View (computed AS SELECT) tables are now read-only — direct CREATE/INSERT/UPDATE/UPSERT/RELATE/DELETE against 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 of ASSERT on the record id field, including via ALTER FIELD, so assertions declared on id are applied at write time again.

  • [Functions] duration::secs, duration::millis, duration::micros, and duration::nanos no 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 as decimal instead of being silently truncated, and values too large for decimal raise an error rather than wrapping — so these functions now return a decimal for counts beyond the i64 range.

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.

View 3.2.3 release notes

3.2.0-beta.2

PRE-RELEASE

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 the memory_threshold configmap parse path rejecting human-readable byte suffixes (for example 256m or 1g) and emitting a spurious configuration-parse warning for the MEMORY_THRESHOLD key. The configmap path now shares the same suffix-aware parse_memory_threshold helper 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.

View 3.2.3 release notes

3.2.0-beta.1

PRE-RELEASE

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.1v3.1.5 patches are also included in this build but are not repeated here.

Highlights

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 /gql HTTP route or the new gql RPC method.

  • The language is gated behind the opengql experimental capability and is off by default. Enable it with --allow-experimental opengql (or SURREAL_CAPS_ALLOW_EXPERIMENTAL=opengql). The gql HTTP route itself follows the usual route capabilities, which allow all routes by default.

  • MATCH execution (v2). Pattern matching runs through a MatchPlan binding-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, and avg are supported, with grouping.

  • Path search. SHORTEST, ALL, and ANY path search are available, along with path modes on MATCH.

This is an early, experimental surface — expect it to evolve across the 3.2 beta cycle.

The graph query surfaces are now reachable beyond their HTTP routes.

  • Added a graphql RPC method, so GraphQL queries can be issued over the WebSocket/RPC protocol instead of only the /graphql HTTP endpoint.

  • Both GraphQL and OpenGQL are now exposed through the first-party MCP server, letting MCP clients run graph queries directly.

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 /ready endpoint reports readiness: it returns 200 only 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 returns 503 (or 500 if 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 /ready stay reachable so probes and scrapers keep working throughout startup.

Large structural removals no longer reclaim their data inline on the statement's transaction.

  • REMOVE NAMESPACE, REMOVE DATABASE, and REMOVE INDEX now 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 REMOVE can finish first. On TiKV this is coordinated with the MVCC GC safepoint — the effective grace is max(reclaim_grace, tikv_gc_lifetime), so raising the GC lifetime alone can never make reclaim unsafe.

  • New configuration:

    • --reclaim-interval / SURREAL_RECLAIM_INTERVAL (default 60s) — how often the reaper runs.

    • --reclaim-grace / SURREAL_RECLAIM_GRACE (default 10m) — minimum age before tombstoned data is physically reclaimed.

DEFINE FIELD id is now a first-class typed field that is validated when records are written.

  • A TYPE on the id field is enforced at write time: creating a record whose id does not match the declared type fails with a coercion error (for example, an int id field rejects badtype:notanint).

  • DEFAULT on the id field is supported and is evaluated against the session and coerced to the declared kind (for example TYPE uuid DEFAULT rand::uuid()), but DEFAULT ALWAYS is 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 ... FUNCTION hardening. Tightened the function-backed analyzer path: SurrealML model functions are rejected, Surrealism module (mod::) functions require the surrealism experimental capability, the FUNCTION clause expects a function name rather than a function call (fn::some, not fn::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 (default 1000); larger batches reduce ID-allocation coordination between nodes.

  • Orphaned LIVE query metric. A new counter tracks orphaned LIVE SELECT registrations, making it easier to spot live queries that have lost their owning session.

  • Surrealism version in the CLI. A new surreal module version subcommand reports the Surrealism (WASM plugin) runtime version, separate from surreal version which continues to report the SurrealDB server version.

  • [$] (last element) on sets. Sets now support the [$] last-part accessor, matching arrays.

  • SHOW CHANGES surfaces delete pre-images. With INCLUDE ORIGINAL, the change feed now includes the pre-image of deleted records in SHOW CHANGES output.

  • record::exists() and LIMIT 0 cleanups. record::exists() now always returns a boolean, returning false for a record on an undefined table instead of erroring. Separately, SELECT ... LIMIT 0 no longer short-circuits the table-existence check: it now behaves like the same query without LIMIT 0 (for example, erroring on a nonexistent table in strict mode) rather than returning an empty array.

  • Query-engine performance.

    • DELETE skips 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 + LIMIT heap 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_NODELAY is enabled on the HTTP/WS listener to disable Nagle's algorithm.

  • Dependency updates. wasmtime bumped to 44.0.3 (addresses RUSTSEC-2026-0182), and the Surrealism crate versions were bumped.

Bug fixes

  • [Access] Reject DURATION FOR TOKEN NONE on TYPE RECORD access (via both DEFINE and ALTER), 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 in DEFINE API, whether declared across separate FOR clauses 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

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.

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.

View 3.2.3 release notes

Our newsletter

Get tutorials, AI agent recipes, webinars, and early product updates in your inbox every two weeks

SurrealDB

The context layer for AI agents.

Documents, graphs, vectors, time-series, and memory.
One transaction, one query, one deployment.

Explore with AI

Stay in the loop

Tutorials, AI agent recipes, and product updates, every two weeks.

Independently verified

SOC 2 Type 2

GDPR

Cyber Essentials Plus

ISO 27001

Trust Centre

Copyright © 2026 SurrealDB Ltd. Registered in England and Wales. Company no. 13615201

Registered address: 3rd Floor 1 Ashley Road, Altrincham, Cheshire, WA14 2DT, United Kingdom

Trading address: Huckletree Oxford Circus, 213 Oxford Street, London, W1D 2LG, United Kingdom