Environment variables can be used to tailor the behaviour of a running SurrealDB instance.
Environment variables are divided into four types:
SurrealDB environment variables: environment variables that pertain to the overall running of a SurrealDB server. Example:
SURREAL_DEFAULT_DATABASE. Includes an operator and internal config subsection for advanced settings.Command environment variables: environment variables that can be used in lieu of a command flag. Example:
SURREAL_CAPS_ALLOW_ALL=true surreal db start, equivalent tosurreal db start --allow-all.Storage backend environment variables: environment variables that pertain to a certain storage backend. Example:
SURREAL_SURREALKV_ENABLE_VLOG.SurrealDB Cloud environment variables: environment variables that are set via the Configure instance sidebar for a SurrealDB Cloud instance.
Every variable on this page belongs to the database and starts with SURREAL_. They are read by surreal db, and by the server in a container that runs surreal start directly. The launcher has its own variables, which start with SURREAL_CLI_ and are documented in the launcher reference. The surreal cloud component reads SURREAL_CLOUD_* variables, described in the Cloud reference. The prefixes are kept apart deliberately: a database credential such as SURREAL_TOKEN is not a Cloud credential, and must not be sent to the SurrealDB Cloud API.
Many environment variables have a maximum value equivalent to the greatest possible usize, which is an unsigned integer with a number of bytes depending on the target that the database runs on. For most systems this will be 64 bits, leading to a maximum size of 18_446_744_073_709_551_615 (264), while for 32 bits the maximum will be 4_294_967_296 (232).
Byte size suffixes
Available since: v3.0.0
Environment variables that set a size in bytes, such as SURREAL_HTTP_MAX_SQL_BODY_SIZE and SURREAL_WEBSOCKET_MAX_MESSAGE_SIZE, accept either a raw byte count or a number with a suffix. Suffixes are case-insensitive, and all of them are powers of 1024, so 4GB and 4GiB both mean 4,294,967,296 bytes.
| Suffix | Multiplier |
|---|---|
none, b | 1 |
k, kb, kib | 1024 |
m, mb, mib | 10242 |
g, gb, gib | 10243 |
A value that cannot be parsed is discarded and the default is used instead - the server does not fail to start. On 2.x these variables take a raw byte count only, so a suffixed value such as 16MiB is silently ignored there and the default remains in effect.
SurrealDB environment variables
These environment variables can be used to configure a SurrealDB server to configure areas such as the HTTP server and client, limits, telemetry, and so on.
Batch config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_NORMAL_FETCH_SIZE | 500 | A usize | The maximum number of keys that should be scanned at once in general queries. Read only before 3.1.0; later versions use a fixed batch of 500. |
SURREAL_EXPORT_BATCH_SIZE | 1000 | A usize | The maximum number of keys that should be scanned at once for export queries. |
SURREAL_COUNT_BATCH_SIZE | 50,000 (10,000 on 2.x) | A usize | The maximum number of keys that should be scanned at once for count queries. Read only before 3.1.0; later versions use a fixed batch of 50,000. |
SURREAL_INDEXING_BATCH_SIZE | 250 | A usize | The maximum number of keys to scan at once per concurrent indexing batch. Read only before 3.1.0; later versions use a fixed batch of 250. |
SURREAL_TABLE_DOC_IDS_BATCH_SIZE | 1000 | A u32 | The number of document ids allocated at once from a table's shared document id sequence, which full-text, HNSW and DiskANN indexes use. Larger batches reduce coordination on the distributed sequence, at the cost of larger gaps in the ids when a node is lost before it uses up its current batch. Replaces SURREAL_FTS_DOC_IDS_BATCH_SIZE, which 3.3.0 no longer reads. |
SURREAL_GRAPH_FOLD_BATCH | 1024 | A usize | How many graph adjacency keys one background fold pass packs into blocks per transaction. This bounds the transaction size on a vertex with many edges, which is then folded over several passes. See SURREAL_GRAPH_FOLD_INTERVAL. |
Cache config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_TRANSACTION_CACHE_SIZE | 512 (10,000 before 3.1.0) | A usize | Specifies the number of items which can be cached within a single transaction. |
SURREAL_DATASTORE_CACHE_SIZE | 1,000 | A usize | The number of definitions which can be cached across transactions. |
SURREAL_HNSW_CACHE_SIZE | 268,435,456 (256 MiB) | A usize | The maximum total size, in bytes, of the HNSW vector cache, shared across all HNSW indexes in the process. This bounds the cached element vectors used for distance computation - it is not a cap on total HNSW memory: the adjacency graph is loaded into resident memory on first use and stays there, outside this budget. Contrast SURREAL_DISKANN_CACHE_SIZE, which does page graph structure. |
SURREAL_DISKANN_CACHE_SIZE | 268,435,456 (256 MiB) | A usize | The maximum total size, in bytes, of the DISKANN index cache, shared across all DISKANN indexes in the process. DISKANN graph data lives in the key-value store and is paged through this bounded cache. The DISKANN counterpart of SURREAL_HNSW_CACHE_SIZE. |
SURREAL_FULLTEXT_CACHE_SIZE | 134,217,728 (128 MiB) | A u64 | The maximum total size, in bytes, of the cache of compacted full-text terms, which every read-only full-text query on the node shares. Changes that are not compacted yet are always read from storage, and write transactions do not use the cache. 0turns it off. |
SURREAL_GRAPH_RESOLVE_CACHE_SIZE | 67,108,864 (64 MiB) | A u64 | The maximum total size, in bytes, of the cache that maps document ids back to record keys when a traversal reads numeric-encoded graph adjacency entries. Only relevant once SURREAL_GRAPH_NUMERIC_IDShas written numeric blocks. |
File config
Server-side filesystem access for features that read paths from disk (notably the mapper() filter and the segment() tokenizer on DEFINE ANALYZER). This is separate from SURREAL_BUCKET_FOLDER_ALLOWLIST (below), which gates the experimental files feature.
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_FILE_ALLOWLIST | none (deny all) | Colon-separated paths on Unix; semicolon-separated on Windows | Directories the server may read when an analyzer uses mapper('<path>'). An empty or unset value denies every path. Each mapper file must resolve under one of the listed directories. See DEFINE ANALYZER - mapper . |
SURREAL_SEGMENT_DICTIONARY_PATH | none (use the dictionaries built into the binary) | A path to a directory | Directory holding the morphological dictionaries the segment(<language>)tokenizer reads, one subdirectory per language: chinese, japanese, korean. The released binaries already carry all three, so this is only needed to replace them with a custom or updated dictionary, or for a build made without them. Each language is overridden only if the directory holds a dictionary for it; the rest keep using the built-in one. See DEFINE ANALYZER - segment . |
SURREAL_BUCKET_FOLDER_ALLOWLIST | none | Comma-separated paths | Specifies a list of paths in which files can be accessed. |
SURREAL_GLOBAL_BUCKET | none | A string | The backend URL of the global bucket, in the same form as the BACKENDof a bucket, such as memory, file:/pathor an object storage URL. A bucket uses part of it through a global://backend. See Global backend . |
SURREAL_GLOBAL_BUCKET_ENFORCED | false | true, false | Whether every bucket must use the global bucket. When true, global://is the only backend a bucket can have, and only a root user can give a bucket that backend. |
SURREAL_BUCKET_PRESIGN_SECRET | none (presigned URLs off) | A string of at least 32 bytes | The secret that signs presigned URLs . Without it, or with a shorter value, file::presign_getand file::presign_putfail and a signed request is refused. Set the same value on every node of a cluster. Changing it revokes every URL already issued. |
SURREAL_BUCKET_PRESIGN_MAX_TTL | 1h | A duration, up to 7d | The longest expiresa presigned URL can have. A larger value is reduced to 7 days. |
SURREAL_BUCKET_PRESIGN_MAX_SIZE | 5 GiB | A byte size, such as 100MiB | The largest max_sizea presigned upload URL can have, and the max_sizeof one created without it. |
SURREAL_PUBLIC_ORIGIN | none | An origin with a scheme and no path, such as https://db.example.com | The address at which clients reach the server, returned as the originof a presigned URL and placed before its pathin href. A value without a scheme or with a path is ignored, and originis then NONE. |
HTTP client config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_MAX_HTTP_REDIRECTS | 10 | A usize | The maximum number of HTTP redirects allowed within http functions. |
SURREAL_MAX_HTTP_IDLE_CONNECTIONS_PER_HOST | 128 | A usize | The maximum number of idle HTTP connections to maintain per host. |
SURREAL_MAX_HTTP_IDLE_CONNECTIONS | 1000 | A usize | The maximum number of idle HTTP connections to maintain. Has no effect: earlier versions read the value without applying it to the HTTP client, and 3.3.0 no longer reads it. Use SURREAL_MAX_HTTP_IDLE_CONNECTIONS_PER_HOSTinstead. |
SURREAL_HTTP_IDLE_TIMEOUT_SECS | 90 | A usize | The timeout for idle HTTP connections before closing. |
SURREAL_HTTP_CONNECT_TIMEOUT_SECS | 30 | A usize | The timeout for connecting to HTTP endpoints. |
SURREAL_SURREALDB_USER_AGENT | SurrealDB | A string | The USER-AGENT string used by HTTP requests. Before 3.1.0 this variable was named SURREAL_USER_AGENT, which later versions ignore. |
HTTP server config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_NET_MAX_CONCURRENT_REQUESTS | 1,048,576 | A usize | How many concurrent network requests can be handled at once |
SURREAL_HTTP_MAX_MCP_BODY_SIZE | 4,194,304 (4 MiB) | A usize | Maximum HTTP body size of the HTTP /mcpendpoint. See Embedded MCP. |
SURREAL_HTTP_MAX_SQL_BODY_SIZE | 1,048,576 (1 MiB) | A usize | Maximum HTTP body size of the HTTP /sql endpoint |
SURREAL_HTTP_MAX_GQL_BODY_SIZE | 1,048,576 (1 MiB) | A usize | Maximum HTTP body size of the HTTP /gqlendpoint. See GQL via HTTP . |
SURREAL_HTTP_MAX_GRAPHQL_BODY_SIZE | 1,048,576 (1 MiB) | A usize | Maximum HTTP body size of the HTTP /graphqlendpoint. See GraphQL . |
SURREAL_HTTP_MAX_API_BODY_SIZE | 4,194,304 (4 MiB) | A usize | The maximum HTTP body size of the HTTP /api endpoint. |
SURREAL_HTTP_MAX_BUCKET_BODY_SIZE | 5,368,709,120 (5 GiB) | A usize | The maximum size of an upload to the HTTP /bucketroute, whether it uses a session or a presigned URL. |
SURREAL_HTTP_MAX_RPC_BODY_SIZE | 4,194,304 (4 MiB) | A usize | Maximum HTTP body size of the HTTP /rpc endpoint. |
SURREAL_HTTP_MAX_ATTACHED_SESSIONS | 16384 | A usize | The maximum number of attached HTTP RPC sessions that a node keeps. A session counts against the node it was attached through until it is detached or expires, wherever it is used. When the limit is reached, the node first releases the sessions that were detached or expired through other nodes, and then refuses the attach. |
SURREAL_GRAPHQL_SUBSCRIPTION_CHANNEL_CAPACITY | 1024 | A usize | How many notifications can be buffered for one GraphQL subscription. When the buffer is full, new notifications for that subscription are dropped. |
SURREAL_GRPC_MAX_MESSAGE_SIZE | The value of SURREAL_HTTP_MAX_RPC_BODY_SIZE, so 4,194,304 (4 MiB) unless that is raised | A usize, clamped to a ceiling of 4,294,967,295 (4 GiB less one byte), the largest size a gRPC length prefix can express. A value below the floor needed to carry one streaming file chunk is raised to it. | From 3.3.0. The largest single gRPC message the server will accept or emit, also reported to clients as Limits.max_message_bytes. This is the gRPC counterpart of SURREAL_WEBSOCKET_MAX_MESSAGE_SIZE: raise it for a transaction that writes a large batch in one request. |
SURREAL_GRPC_MAX_ATTACHED_SESSIONS | 16384 | A usize | The maximum number of explicitly attached sessions the gRPC transport keeps at once. The count is for the whole process rather than per connection, because a gRPC channel reconnects transparently and one session's requests can arrive on different connections. Per-request sessions do not count towards it. |
SURREAL_GRPC_NOTIFICATION_BUFFER | 1024 | A usize | How many live query notifications can be buffered for a gRPC subscription whose client is not keeping up. When the buffer is full, the server ends that subscription with a RESOURCE_EXHAUSTEDstatus instead of waiting. |
SURREAL_HTTP_MAX_KEY_BODY_SIZE | 16,384 (16 KiB) | A usize | Maximum HTTP body size of the HTTP /key endpoints |
SURREAL_HTTP_MAX_SIGNUP_BODY_SIZE | 1024 (1 KiB) | A usize | Maximum HTTP body size of the HTTP /signup endpoint. |
SURREAL_HTTP_MAX_IMPORT_BODY_SIZE | 4,294,967,296 (4 GiB) | A usize | Maximum HTTP body size of the HTTP /importendpoint. Counted cumulatively across the whole request, not per chunk. Also enforced on the gRPC import stream. See Request size limits. |
SURREAL_HTTP_MAX_SIGNIN_BODY_SIZE | 1024 (1 KiB) | A usize | The maximum HTTP body size of the HTTP /signin endpoints |
Before SurrealDB 3.3.0, SURREAL_HTTP_MAX_SIGNUP_BODY_SIZE and SURREAL_HTTP_MAX_SIGNIN_BODY_SIZE were applied to each other's endpoint. Both default to 1 KiB, so no default deployment was affected, but raising one of them had no effect on the endpoint it names and the other endpoint kept returning 413 Payload Too Large. If you worked around this by tuning the opposite variable, move the value back to the one that matches the endpoint.
MCP config
Available since: v3.1.0
Used by the built-in Model Context Protocol server (/mcp on surreal db start, surreal db mcp on stdio). Stdio namespace/database selection uses SURREAL_MCP_NS and SURREAL_MCP_DB on the mcp subcommand.
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_MCP_QUERY_TIMEOUT_SECS | 60 | Seconds (integer); 0disables | Outer timeout on each MCP tool execution. |
SURREAL_MCP_MAX_RESULT_BYTES | 262,144 (256 KiB) | Bytes (integer); 0disables | Maximum serialised tool / resource response size; larger results are truncated with a marker. |
SURREAL_MCP_RUN_MAX_ARGS | 64 | A positive integer | Maximum arguments for a single runtool call. |
SURREAL_MCP_PARAMS_MAX_KEYS | 256 | A positive integer | Maximum top-level keys in MCP parameter / data objects. |
SURREAL_MCP_PARAMS_MAX_QL_BYTES | 4,096 (4 KiB) | A positive integer; values ≤ 0 fall back to the default | Maximum byte length of a single $qlSurrealQL pass-through string inside a *_datapayload. |
SURREAL_MCP_SCHEMA_RESOURCE_MAX_TABLES | 200 | A positive integer; values ≤ 0 fall back to the default | Maximum tables the database-level schema resource enriches with per-table fields / indexes / events. Tables beyond the cap keep a bare DEFINE TABLEand the body includes a tables_truncated_atmarker. |
SURREAL_MCP_ALLOWED_HOSTS | loopback only ( localhost, 127.0.0.1, ::1) | Comma-separated exact hostnames | Hostnames accepted in the HTTP Hostheader for /mcp(DNS-rebinding guard). A non-empty list replaces the loopback default, so include localhostyourself if you still need it. Entries without a port match any port. Ignored when SURREAL_MCP_ALLOW_ALL_HOSTSis set. |
SURREAL_MCP_ALLOW_ALL_HOSTS | false | true/ 1to enable | Disables the Host-header allowlist (accept any Host). Escape hatch for a trusted proxy or load balancer. Takes precedence over SURREAL_MCP_ALLOWED_HOSTS. |
GQL config
Available since: v3.2.0
Resource limits for ISO GQL MATCH execution. Errors name the limit when it is exceeded. From 3.3.0, GQL is enabled by default; on 3.2.x, enable it with --allow-experimental gql.
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_GQL_MAX_PATH_ROWS | 1,000,000 | A usize | Per source row, bounds live and emitted rows during variable-length path expansion in a GQL MATCH. |
SURREAL_GQL_MAX_JOIN_BUILD_ROWS | 1,000,000 | A usize | Bounds the in-memory build side of hash joins between GQL match patterns (and distinct-operator working sets). |
SURREAL_GQL_MAX_OUTPUT_ROWS | 1,000,000 | A usize | Bounds cumulative rows emitted by GQL hash-join operators (including cross joins). |
Limits config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_GRAPH_INLINE_PROPS_CAP | 64 | A number of bytes, without a unit suffix | Largest encoded payload an INLINEfield set may occupy inside a graph adjacency entry. A larger payload spills, leaving the values on the edge record only. |
SURREAL_BITMAP_BRANCH_BUDGET | 250,000 | A usize; 0disables the budget | How many index entries one range branch of a bitmap plan, which combines several indexes into a bitmap of candidate records, may read before that branch is abandoned. The abandoned branch's condition is then checked as an ordinary WHEREfilter, so an unselective range cannot make the bitmap plan slower than scanning. The same budget is the upper limit for the allow-list built for a pre-filtered vector search, which from 4.0 has a smaller limit when the search width is small (see Vector search config ). |
SURREAL_EXTERNAL_SORTING_BUFFER_LIMIT | 50000 | A usize | The number of result records which will trigger on-disk sorting. |
SURREAL_STRING_SIMILARITY_LIMIT | 16384 | A usize | The maximum input string length for similarity/distance functions |
SURREAL_FAN_OUT_ROW_THRESHOLD | 4 | A usize | A batch with fewer items than this is evaluated one item at a time. A larger batch has its items evaluated concurrently, but only when the evaluation is read-only. Set it above the batch size to turn concurrent evaluation off. |
SURREAL_GENERATION_ALLOCATION_LIMIT | 20 (2 20 = 1,048,576 bytes) | A power of two, as its exponent: an integer up to 28 (256 MiB); larger values are treated as 28 | Limits the memory that a single call to array::combine, array::concat, array::range, array::repeat, array::sequence, array::transpose, array::windows, string::concat, string::join, string::repeator string::replacecan allocate for its result, and the number of values that a scripting function can return. A call over the limit fails with an error. The value is an exponent, not a byte count: the limit is 2 to the power of the value, so the default of 20allows 1,048,576 bytes. Setting a byte count such as 1048576sets the limit to its maximum of 2 28 bytes. |
SURREAL_IDIOM_RECURSION_LIMIT | 256 | A usize | The maximum recursive idiom path depth allowed. Read only before 3.1.0; later versions use a fixed limit of 256. |
SURREAL_MEMORY_LIMIT | 0 (half of SURREAL_MEMORY_THRESHOLDif set, otherwise 2 GiB) | A usize or suffixed integer | The bytes that all queries on the node may hold in sorts, grouped aggregates, DISTINCTand join builds before they spill to disk. See Memory limits and spilling to disk . |
SURREAL_QUERY_MEMORY_MAX | 0 (the node memory limit) | A usize or suffixed integer | The bytes that a single query may hold which it cannot spill, such as gathered values and its transaction buffers. A query that passes it fails with the memory threshold error, and other queries are not affected. |
SURREAL_QUERY_MEMORY_MINIMUM | 4 MiB | A usize or suffixed integer | The bytes that every query holding a sort, group, DISTINCTor join build is guaranteed, in addition to what spilling takes. |
SURREAL_MEMORY_WAIT | 1000 | A number of milliseconds | The longest that a query waits in total for other queries to release memory before it continues past the node limit. 0never waits. |
SURREAL_SPILL_PART_SIZE | 1 MiB | A suffixed integer greater than zero | The size of the parts in which a spilled run is written and read. |
SURREAL_SPILL_MERGE_FAN_IN | 8 | A usize, at least 2 | The number of spilled runs that a merge reads at once. A merge of more runs takes several passes. |
SURREAL_MEMORY_RESERVE_CHUNK | 256 KiB | A suffixed integer greater than zero | The bytes that a sort, group, DISTINCTor join build reserves from its query at a time. |
SURREAL_STREAM_STAGE_BYTES | No limit | A byte count, or a size such as 64KiB | The estimated bytes of result rows that a write statement streaming its results, in a transaction of its own, holds back until it commits. Held rows let a statement that meets a retryable conflict at commit run again without its client receiving the rows of the failed attempt. Past this size the held rows are sent and the rest stream as they are produced, and the statement is no longer run again on a conflict. 0holds nothing back. By default every row is held until the commit. |
SURREAL_MAX_COMPUTATION_DEPTH | 120 | A usize | Specifies how deep recursive computation will go before erroring. |
SURREAL_MAX_CONCURRENT_TASKS | 64 | A usize | Specifies how many concurrent jobs can be buffered in the worker channel. Removed in 4.0.0, which no longer reads it, so setting it has no effect. |
SURREAL_MAX_EXPRESSION_PARSING_DEPTH | 128 | A usize | How deep the parser will build an expression operator tree. This bounds long operator chains such as 1 + 1 + 1 + …and prefix/postfix chains, which consume neither of the other two parsing budgets. |
SURREAL_MAX_OBJECT_PARSING_DEPTH | 100 | A usize | How deep the parser will parse nested objects and arrays. Type annotations such as array<option<array<int>>>count against it as well. For data arriving over an SDK or RPC this is the governing limit. For a query written as text, see Nesting depth in queries versus data . |
SURREAL_MAX_ORDER_LIMIT_PRIORITY_QUEUE_SIZE | 1000 | A usize | The maximum size of the priority queue triggering usage of the priority queue for the result collector. |
SURREAL_MAX_QUERY_PARSING_DEPTH | 20 | A usize | How deep the parser will parse recursive queries (queries within queries). Object and array literals written into a query count against this budget as well as against SURREAL_MAX_OBJECT_PARSING_DEPTH, and this one is the smaller of the two - see Nesting depth in queries versus data . |
SURREAL_OPERATOR_BUFFER_SIZE | 2 | A usize | The number of batches each operator buffers ahead of downstream demand. Set to 0 to disable operator-level pipeline buffering. |
SURREAL_REGEX_SIZE_LIMIT | 10,485,760 (10 MiB) | A usize | Limits the maximum allowed size (in bytes) for regular expressions. This prevents excessive memory consumption when building complex or very large regex patterns. |
SURREAL_SCAN_BATCH_BYTES | 2,097,152 (2 MiB) | A byte count, or a size such as 512KiB | The approximate decoded size of each batch of records that a query fetches from an index result, such as the matches of a full-text search. A batch also holds at most 1,000 records. Every operator after the scan holds whole batches, so the memory a query uses grows with this value. Lower it to limit memory on a small node, or raise it for fewer, larger batches. 0and values that cannot be parsed are ignored. |
SURREAL_TRANSACTION_MAX_WRITE_KEYS | 0 (disabled) | A u64; 0disables | Maximum number of key writes a single statement transaction may buffer before it is aborted and rolled back. Cascaded deletes, full-text index maintenance, graph-edge cleanup, and commit-time changefeed / live-query events all count toward the limit; each range delete counts as one write. Tripping the guard poisons the transaction so an explicit client COMMITcannot persist a partial statement. Internal maintenance transactions (index builds, compaction, GC) are not bounded. On TiKV, range deletes may expand further inside the storage layer - size distributed clusters with both this limit and SURREAL_TIKV_DELR_MAX_KEYSin mind. Scale / multi-node deployments often use a limit in the 50,000-100,000 range; leave at 0for typical single-node use. |
SURREAL_READ_SNAPSHOT_MAX_STALENESS_SECS | 3600 (one hour) | A u64 (seconds) | The largest MAX STALENESSthat a read-only transaction can ask for. A larger request fails when the transaction begins, with The requested MAX STALENESS of 5s is above the maximum of 1s this datastore allows. It also limits how long a permission that has been revoked can still apply to a stale read. |
SURREAL_READ_SNAPSHOT_FALLBACK | allow | allow, deny, rate:<n> | What a read-only transaction with MAX STALENESSdoes when no published snapshot is recent enough: read the current state ( allow), fail ( deny), or read the current state at most ntimes a second. STRICTon the statement fails in that case whatever this setting says. A datastore that publishes no snapshots, which includes every storage engine of the open-source release, always reads the current state, which meets every bound. |
Memory limits and spilling to disk
Available since: v4.0.0
From SurrealDB 4.0, each node holds its queries to a memory limit, set by SURREAL_MEMORY_LIMIT. By default the limit is half of SURREAL_MEMORY_THRESHOLD where that is set, and 2 GiB otherwise. Each query is guaranteed a minimum share, set by SURREAL_QUERY_MEMORY_MINIMUM.
When a sort, a grouped aggregate, a DISTINCT or a join build outgrows its share, it writes sorted runs to temporary files and merges them. The query is slower, but it does not fail, and it does not need the TEMPFILES clause. If memory is short, a query first spills, then waits for other queries to release memory for up to SURREAL_MEMORY_WAIT milliseconds in total, and then continues past the limit.
Values that a query cannot spill, such as a gathered subquery result or a value bound with LET, are bounded for each query by SURREAL_QUERY_MEMORY_MAX. A query that passes it fails with the memory threshold error, and other queries are not affected.
Spill files go to the directory in SURREAL_TEMPORARY_DIRECTORY, or to a surrealdb folder in the system temporary directory. SurrealDB clears the files left by a process that has stopped the next time it opens the directory. There is no disk quota on this directory, so give it enough space and, in a container, mount it on a volume of suitable size. If the directory cannot be created, the server logs Queries will not spill to disk and starts with no memory limit on its queries.
SURREAL_MEMORY_THRESHOLD is a separate guard over the whole process. Spilling does not exempt a query from it, so a query is still refused when the tracked memory of the process passes the threshold, whatever SURREAL_MEMORY_LIMIT is set to.
The following command lowers the node limit to 512 MiB and spills to a dedicated volume:
SURREAL_MEMORY_LIMIT=512MiB SURREAL_TEMPORARY_DIRECTORY=/var/lib/surrealdb/spill surreal db start --user root --pass secret surrealkv://mydbNesting depth in queries versus data
Four separate budgets bound recursion, and which one a deeply nested value hits depends on how it reaches the server.
A value written into query text is read by the SurrealQL parser, and each level of an object or array costs one level of SURREAL_MAX_QUERY_PARSING_DEPTH as well as one of SURREAL_MAX_OBJECT_PARSING_DEPTH. Since the query budget defaults to 20 against the object budget's 100, the query budget is what a nested literal runs out of first.
A value arriving as data (the body of an SDK call, an RPC message, or a WebSocket frame) is never parsed as SurrealQL, so it spends only the object budget and nests roughly five times deeper for the same default configuration.
The practical effect is that one document can be accepted through an SDK and rejected as a literal in surreal db sql, which reads as an inconsistency but is two budgets doing their own jobs. A structure alternating object and array, as in { inner: [{ inner: [ … ] }] }, spends two levels per step:
| Path | Governing default | Levels of { inner: [ … ] } |
|---|---|---|
Query text (surreal db sql, /sql) | SURREAL_MAX_QUERY_PARSING_DEPTH = 20 | 9 |
| SDK, RPC, WebSocket | SURREAL_MAX_OBJECT_PARSING_DEPTH = 100 | 49 |
Exceeding either is a parse error, not a crash, giving the error Exceeded query recursion depth limit for the first, Exceeded object recursion depth limit for the second. To send deep literals as text, raise SURREAL_MAX_QUERY_PARSING_DEPTH - raising the object budget alone changes nothing on that path.
Two further depth limits are fixed and cannot be configured: recursive idiom paths stop at 256, and the binary protocol's decoder rejects frames nested beyond 512. Neither is reachable before the parsing budgets above under a default configuration.
Runtime config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_KVS_THREADPOOL_SIZE | Number of CPU cores (minimum 16) | A usize, at least 4 | Number of worker threads the in-memory and SurrealKV engines use for storage work. A value below 4 or a value that is not a number logs a warning and the default is used. |
SURREAL_RUNTIME_MAX_BLOCKING_THREADS | 512 | A usize | Number of threads which can be started for blocking operations. |
SURREAL_RUNTIME_STACK_SIZE | 10,485,760 (10 MiB) | A usize | Runtime thread memory stack size. Default stack size is doubled if compiled from source in Debug mode. |
SURREAL_RUNTIME_WORKER_THREADS | Number of CPU cores (minimum 4) | A usize | Number of runtime worker threads used to start. See CPU cores and concurrent queries . |
SURREAL_MORSEL_PLACES | No limit | A usize | The most places of the node's worker pool that one statement can hold at once to scan in parallel. The pool has one place for each core beyond the one a statement's own task runs on. 0runs every statement on its own task. Index builds and background index compaction draw on the same pool. |
SURREAL_MORSEL_OLTP_RESERVE | 1 | A usize | The places of the worker pool that parallel scans never take, so that short statements keep a core. On a host with two cores or fewer, the default leaves no place to share, so index builds and compaction run on one task unless this is set to 0. |
SURREAL_MORSEL_PLACE_QUANTUM | 8 | A u32 | How many chunks of its work a parallel worker finishes while another statement waits for a place, before it hands what is left of its work back and frees the place. |
SURREAL_MORSEL_SPLIT_PASS_PPM | 50000 | A u32 | The most records in a million that a scan's WHEREconditions can keep for the scan to be split into parts that run in parallel. The default is one record in twenty. A scan that keeps a larger share of the records it reads stays on one task, because most of its time is spent reading records, which more workers do not make faster. The share is measured from the records the scan has read so far. With 1000000, a scan with a WHEREcondition can be split whatever share of its records the condition keeps. |
Scripting config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_SCRIPTING_MAX_STACK_SIZE | 262_144 (256 KiB) | A usize | Maximum stack size of the JavaScript function runtime. |
SURREAL_SCRIPTING_MAX_MEMORY_LIMIT | 2,097,152 (2 MiB) | A usize | Maximum memory limit of the JavaScript function runtime. |
SURREAL_SCRIPTING_MAX_TIME_LIMIT | 5000 (5000 milliseconds or 5 seconds) | A usize | Maximum allowed time in milliseconds that a JavaScript function is allowed to run for. |
Security config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_INSECURE_FORWARD_ACCESS_ERRORS | false | true, false | Forward all signup/signin/authenticate query errors to a client performing authentication. Do not use in production. |
SURREAL_JWKS_CACHE_COOLDOWN_SECONDS | 300 | seconds | The shortest time between two fetches of a JWKS object that a token with an unknown key identifier ( kid) can cause. |
SURREAL_JWKS_CACHE_EXPIRATION_SECONDS | 43200 | seconds | How long a fetched JWKS object stays in the cache before it is fetched again. The default is 12 hours. |
SURREAL_JWKS_REMOTE_TIMEOUT_MILLISECONDS | 1000 | milliseconds | How long a request for a JWKS object from its URL may take before it fails. Raise it for an identity provider that answers slowly. |
Surrealism config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_LAZY_SURREALISM | false | true, false | Whether to lazy-load Surrealism modules instead of eagerly compiling them at server startup. |
SURREAL_SURREALISM_CACHE_SIZE | 100 | A usize | The number of surrealism modules which can be cached across transactions. |
SURREAL_SURREALISM_MAX_POOL_SIZE | 8 | A usize | Per-module controller pool size ceiling for Surrealism WASM modules. Has no effect: the server does not read this variable, so the ceiling stays at 8. Removed in 4.0.0, which runs each call on a fresh instance; see SURREAL_SURREALISM_MAX_CONCURRENT_INVOCATIONS. |
SURREAL_SURREALISM_MAX_MEMORY | None (unlimited) | A usize | Per-module WASM linear memory ceiling in bytes. From 4.0.0, an extension's CAPABILITIEScan set a lower limit, and the smaller of the two applies. |
SURREAL_SURREALISM_MAX_EXECUTION_TIME | None (unlimited) | A u64 (milliseconds) | Per-invocation execution time ceiling for Surrealism WASM modules. From 4.0.0, an extension's CAPABILITIESand the query's timeout can set a lower limit, and the smallest applies. |
SURREAL_SURREALISM_MAX_CONCURRENT_INVOCATIONS | 64 | A u32 | How many extension calls can run at once across the datastore. Each call runs on a fresh instance in one of these slots, and each slot reserves about 4 GiB of virtual address space (not resident memory) on 64-bit hosts, which a virtual memory limit such as RLIMIT_ASmust allow. A quarter of the slots is kept for calls made from inside another extension. A call that finds no free slot waits, within its query's timeout. |
SURREAL_SURREALISM_MAX_FS_BYTES | 104857600 (100 MiB) | A u64 | The largest total size, in bytes, of the files that an extension archive bundles in its read-only filesystem. Applied when an archive is unpacked by DEFINE EXTENSIONor at startup. |
SURREAL_SURREALISM_ALLOW_UNBOUNDED_EXECUTION | false | true, false | Whether an extension defined with CAPABILITIES { strict_timeout: false }runs without time checks. Without this setting, every call is stopped by the execution time ceiling and the query's timeout, whatever the definition says. With it, such an extension holds its slot and its worker thread until it returns. |
SURREAL_SURREALISM_MAX_KV_ENTRIES | None (unlimited) | A usize | Per-module KV store entry count ceiling. Has no effect from 4.0.0, which removes the module KV store. |
SURREAL_SURREALISM_MAX_KV_VALUE_BYTES | None (unlimited) | A usize | Per-module KV store maximum value size in bytes. Has no effect from 4.0.0, which removes the module KV store. |
SURREAL_SURREALISM_LOG_LEVEL | debug | none, full, error, warn, info, debug, trace | Controls the tracing level at which Surrealism module stdout is emitted. |
SURREAL_SURREALISM_SILO_ENDPOINT | https://silo.surrealdb.com | A URL | Not read from 4.0.0, where silo::packages always come from https://silo.surrealdb.com. Before 4.0.0: the base URL that a silo::package in DEFINE EXTENSION is fetched from, as {endpoint}/{organisation}/{package}/{major}.{minor}.{patch}.surli. A trailing slash is removed. Set it to a mirror to serve packages from somewhere else. |
Telemetry config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_METRICS_ENABLED | true | true, false | Whether the Prometheus /metricsendpoint is served on the HTTP port. When false, the route returns 404. See Metrics . |
SURREAL_PROCESS_METRICS_REFRESH_INTERVAL | 5 | Seconds (integer); values below 1 are raised to 1 | How often the process memory and CPU snapshot is refreshed. The surrealdb.process.*gauges and INFO FOR ROOTread this snapshot. |
SURREAL_SLOW_QUERY_METRIC_THRESHOLD_MS | 1000 | Milliseconds (integer); 0disables the counter | The duration above which a completed statement is also counted by the surrealdb.slow_query.totalmetric. |
SURREAL_TELEMETRY_DISABLE_METRICS | false | true, false | Whether to disable sending metrics to the GRPC OTEL collector. |
SURREAL_TELEMETRY_DISABLE_TRACING | false | true, false | Whether to disable sending traces to the GRPC OTEL collector. |
SURREAL_TELEMETRY_NAMESPACE | none | A string | If set then use this as value for the namespace label when sending telemetry |
SURREAL_TELEMETRY_PROVIDER | none | otlp | If set to "otlp" then telemetry is sent to the GRPC OTEL collector. |
SURREAL_TOKIO_CONSOLE_ENABLED | false | true, false | Whether to enable tokio console. |
SURREAL_TOKIO_CONSOLE_RETENTION | 60 | A usize | How long, in seconds, to retain data for completed events. |
SURREAL_TOKIO_CONSOLE_SOCKET_ADDR | none | String to a socket address | The socket address that Tokio Console will bind to. |
Vector search config
Available since: v3.3.0
These variables tune vector search on HNSW and DiskANN indexes. Most of them tune pre-filtered vector search: when a KNN query on an HNSW or DiskANN index has WHERE conditions that other indexes can answer, SurrealDB first evaluates those conditions into an allow-list of matching records and restricts the vector search to it. See How the filter is applied.
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_HNSW_BUILD_PARALLELISM | auto | auto, serial, or a number of tasks ( 0means auto) | How many tasks one batch of HNSW index compaction builds its graph changes on. autouses as many tasks as the machine reports available parallelism, and serialuses one. A batch that removes vectors always runs on one task. |
SURREAL_INDEX_BUILD_PARALLELISM | auto | auto, serial, or a number of tasks ( 0means auto) | How many batches of records the initial scan of a standard or UNIQUEindex build indexes at the same time, each in a transaction of its own. autouses the machine's available parallelism, up to 16, and serialindexes one batch at a time. |
SURREAL_DISKANN_FILTER_PREFETCH_MIN_CHUNK | 64 | A usize greater than zero | The first and smallest number of candidate records that a filtered KNN search on a DiskANN index reads at once. Each following read doubles, up to SURREAL_DISKANN_FILTER_PREFETCH_MAX_CHUNK. |
SURREAL_DISKANN_FILTER_PREFETCH_MAX_CHUNK | 4096 | A usize greater than zero | The largest number of candidate records that a filtered KNN search on a DiskANN index reads at once. |
SURREAL_KNN_PREFILTER_ENABLED | true | true, false | Whether KNN queries build an allow-list from their WHEREconditions. When false, the conditions are checked for each candidate during the index traversal instead, as before 3.3.0. |
SURREAL_KNN_PREFILTER_EXACT_THRESHOLD | 2000 | A u64 | The allow-list size at or below which the search does not use the index graph at all, and instead scores every allowed record exactly. At this size an exact search is cheaper than a traversal and always finds the true nearest neighbours. |
SURREAL_KNN_PREFILTER_EXACT_COST | 5 | A u32 | How strongly an HNSW search above SURREAL_KNN_PREFILTER_EXACT_THRESHOLDfavours walking the graph over scoring the allowed records exactly. The search scores them exactly when the number of allowed records, squared and multiplied by this value, is at most efmultiplied by the index's M0and by the number of nodes in the graph. A larger value keeps more searches on the graph. |
SURREAL_KNN_PREFILTER_EF_BOOST | 4 | A u32 | The multiplier applied to the search width ( ef) of a DiskANN traversal restricted to an allow-list. From 4.0, an HNSW traversal reads SURREAL_KNN_PREFILTER_HNSW_EF_BOOSTinstead. A selective allow-list rejects most candidates, and a wider search recovers the recall that loses. The result is capped by SURREAL_KNN_PREFILTER_EF_MAXand is never lower than the efthe query asks for. |
SURREAL_KNN_PREFILTER_HNSW_EF_BOOST | 1 | A u32 | The multiplier applied to the search width ( ef) of an HNSW traversal restricted to an allow-list. The traversal already continues past the candidates the allow-list rejects, so the default of 1does not widen it. Set it to 4for the width that 3.x used. |
SURREAL_KNN_PREFILTER_EF_BOOST_THRESHOLD | 100,000 | A u64 | The allow-list size above which the traversal stops multiplying ef, because a large allow-list rejects few candidates. Results are still restricted to the allow-list at every size. |
SURREAL_KNN_PREFILTER_EF_MAX | 1024 | A u32 | The ceiling for the multiplied ef. It never lowers the efa query asks for. |
SURREAL_DISKANN_QUANTIZED_SEARCH | true | true, false | Whether a KNN search on a DiskANN index of TYPE F32or TYPE F16compares candidates using an 8-bit code of each vector, and then ranks its nearest results from the full vectors. The distances a query returns are exact either way. falsecompares full vectors throughout. Only an index defined or rebuilt on SurrealDB 4.0 keeps the codes, and other indexes ignore the setting. |
SURREAL_DISKANN_SEARCH_BEAM_WIDTH | 1 | A usize | How many candidates a DiskANN search expands in each step. A wider beam reads the neighbours of all of them in one batched read, so the search makes fewer storage round trips, but it also expands some candidates that a narrower beam would skip. The value is limited to between 1 and the search size of the query. |
The allow-list is built within an entry budget for each index it reads. From SurrealDB 4.0 the budget is 512 entries for each unit of the search width ef, never less than twice SURREAL_KNN_PREFILTER_EXACT_THRESHOLD or 4,096, and never more than SURREAL_BITMAP_BRANCH_BUDGET. Before 4.0 the budget is SURREAL_BITMAP_BRANCH_BUDGET. When the budget is exceeded, the query falls back to checking the conditions during the traversal. A vector index created before 3.3.0 uses the allow-list only after it is rebuilt with REBUILD INDEX.
WebSocket config
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_WEBSOCKET_MAX_MESSAGE_SIZE | 134,217,728 (128 MiB) | A usize | The maximum WebSocket message size, which is also used as the maximum frame size. From 3.0.0 this replaces SURREAL_WEBSOCKET_MAX_FRAME_SIZE, which no longer exists and has no effect if set. |
SURREAL_WEBSOCKET_MAX_WRITE_BUFFER_SIZE | Greatest possible usize value | A usize | The maximum write buffer size before backpressure is applied. |
SURREAL_WEBSOCKET_READ_BUFFER_SIZE | 131,072 (128 KiB) | A usize | The size of the read buffer for WebSocket connections. This controls how much data can be buffered when reading from WebSocket connections. Larger values can improve performance for high-throughput connections but consume more memory per connection. |
SURREAL_WEBSOCKET_WRITE_BUFFER_SIZE | 131,072 (128 KiB) | A usize | The size of the write buffer for WebSocket connections. This controls how much data can be buffered when writing to WebSocket connections. Larger values can improve performance for high-throughput connections but consume more memory per connection. |
SURREAL_WEBSOCKET_RESPONSE_BUFFER_SIZE | 0 | A usize | How many responses can be buffered when delivering to the client. |
SURREAL_WEBSOCKET_RESPONSE_CHANNEL_SIZE | 100 | A usize | Number of messages that can be queued for sending via WebSocket. From 3.3.0, replies and live query notifications have separate queues on each connection, each holding this many messages, and a value below 2 is raised to 2. A connection whose notification queue is full is closed, with a close frame giving the reason, rather than dropping notifications. |
SURREAL_WEBSOCKET_RESPONSE_FLUSH_PERIOD | 3 | A usize | How often (in milliseconds) any buffered responses are flushed to the WebSocket client. |
SURREAL_WEBSOCKET_MAX_CONCURRENT_STREAMS | 32 | A usize | Maximum number of streaming queries (the query_streamRPC method) running at once on a single WebSocket connection. Each open stream holds an executing query, with its read snapshot or transaction, for as long as the client keeps reading. A request over the limit is refused with an error rather than queued. |
SURREAL_WEBSOCKET_STREAM_SEND_TIMEOUT | 30 | Seconds (integer), clamped to 1-86,400 | How long a streaming query may wait to hand one frame to the connection before the stream is stopped. The wait resets for every frame, so it limits a stalled client rather than the length of a stream, and it applies even when SURREAL_QUERY_TIMEOUTis not set. |
SURREAL_WEBSOCKET_MAX_ATTACHED_SESSIONS | 256 | A usize | The maximum number of explicitly attached sessions that a single WebSocket connection can hold at once. The sessions of a connection end when it closes. |
SURREAL_MAX_TRANSACTIONS_PER_CONNECTION | 64 | A usize | Maximum concurrently open client-managed transactions ( beginRPC) on a WebSocket connection's implicit default session. Further begincalls return Too many open transactionsuntil a slot is freed by commit, cancel, reset, or disconnect. Does not apply to attached sessions (see SURREAL_MAX_TRANSACTIONS_PER_SESSION). |
SURREAL_MAX_TRANSACTIONS_PER_SESSION | 64 | A usize | Maximum concurrently open client-managed transactions within a single attached WebSocket session. Counted per session and independent of the connection default-session limit. Detaching or resetting a session cancels its open transactions and frees their slots. |
Operator and internal config
Available since: v3.2.0
These settings are for operators, benchmarks, and advanced debugging - not typical application configuration. They are documented so core contributors and self-hosted deployments can find configuration options that already exist in the engine. Changing them can affect performance, reproducibility, or live-query behaviour; leave defaults in place unless you have a specific reason to tune them.
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_RAND_SEED | none (non-deterministic) | A u64 | Seeds the engine-wide RNG for reproducible runs in benchmarks and tests. Do not use in production. |
SURREAL_LIVE_QUERY_ENGINE | inline | inline, router | Selects the live-query execution engine. inlineis the historical behaviour; routerdecouples write cost from subscriber count (experimental rollout). |
SURREAL_LIVE_QUERY_RETENTION | 1h | A duration | How long the router engine retains live-query event history for subscriber resume. Only applies when SURREAL_LIVE_QUERY_ENGINE=router. |
SURREAL_HNSW_BUILD_SEED | none | A u64 | Seeds HNSW index construction for reproducible graph layouts in benchmarks. Do not use in production. |
SURREAL_GRAPH_NUMERIC_IDS | false | true, false | Whether background graph folds write numeric-encoded adjacency blocks, which store each entry's record id as a compact table-level document id. Existing blocks are converted on their next fold, and reads handle both encodings. Size the lookup cache with SURREAL_GRAPH_RESOLVE_CACHE_SIZE. |
Other environment variables
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_BUILD_METADATA | Automatically populated | A string | The version identifier of this build. Defaults to the CARGO_PKG_VERSION environment variable if not specified. |
SURREAL_DATASTORE_AOL | never | never|sync|async | Append-only log mode. Only used by the memory engine. |
SURREAL_DATASTORE_PERSIST | none | String to a file path | Filesystem path for persistence. Only used by the memory engine. |
SURREAL_DATASTORE_RETENTION | 0 (unlimited) | A duration | Version retention period as a duration string. Used by the surrealkv engine. From 3.3.0 the memory engine refuses a non-zero value and the server does not start. |
SURREAL_DATASTORE_SNAPSHOT | never | never|duration | Snapshot interval. Only used by the memory engine. |
SURREAL_DATASTORE_SYNC | every (never on the memory engine) | never|every|duration | The sync mode for the database, the same setting as the syncpath parameter. Used by the memory and surrealkv engines. When both are set, it takes precedence over SURREAL_DATASTORE_SYNC_DATA. |
SURREAL_DATASTORE_SYNC_DATA | every (never on the memory engine) | never|every|duration | The sync mode for the database. Used by the memory and surrealkv engines. |
SURREAL_DATASTORE_VERSIONED | false | true|false|0|1 | Whether MVCC versioning is enabled, for use with the VERSIONclause . Used by the surrealkv engine. From 3.3.0 the memory engine does not support versioned queries, and refuses trueso that the server does not start. |
SURREAL_EXPERIMENTAL_UPGRADE_FROM_3X | false | true|false|0|1 | Lets a 4.0 node open a datastore that a 3.x release wrote, and upgrade it in place. The upgrade is experimental. Without this variable, the node refuses to start on such a datastore and leaves the data unchanged. A datastore that 4.0 has already upgraded opens without it. An embedded SDK reads the experimental_upgrade_from_3xdatastore option instead. See Opting in to the upgrade . |
SURREAL_FEATURE_LEVEL | none | 4.0|current | The record format release a datastore is switched to when a node starts. A datastore in memory or SurrealKV switches to the 4.0 format on its first 4.0 start without it. A TiKV datastore keeps the 3.x format until a node starts with this set, and the switch is refused, with a warning, while a node that runs an older release is still running. It never moves a datastore back to an earlier format. See The 4.0 record format . |
SURREAL_MEMORY_THRESHOLD | 0 (disabled) | A usize or suffixed integer | The tracked memory, in bytes, above which queries are refused with The query was not executed due to the memory threshold being reached. The value can be specified as bytes (b, or without any suffix), kibibytes (k, kb, or kib), mebibytes (m, mb, or mib), or gibibytes (g, gb, or gib); Kubernetes-style Giand Miare not accepted. Unset or 0disables the guard, and any other value is raised to at least 1 MiB. Tracked memory is the size the allocator reserves for each live heap allocation, which includes the SurrealKV block cache and is less than the process's resident memory, so set the threshold below the container's memory limit and above SURREAL_SURREALKV_BLOCK_CACHE_CAPACITY: at or below the cache size, a full cache refuses every query until the server restarts. Before 4.0, the RocksDB block cache was counted in the same way, and the threshold had to be above SURREAL_ROCKSDB_BLOCK_CACHE_SIZE. From 3.3.0 the reserved size rather than the requested size is counted, so a threshold carried over from an earlier release refuses queries at a lighter workload and may need raising. From 3.3.1 the threshold also stops a query that is already running: a query that reads records checks it after each batch, and fails with the same error once tracked memory is above it, rather than growing until the operating system stops the server. From 4.0.0 it also sets the default node memory limit, which is half of the threshold when SURREAL_MEMORY_LIMITis not set. The threshold still refuses queries when the whole process passes it, whether or not their sorts and groups would spill. See Memory limits and spilling to disk . |
SURREAL_MEMORY_THRESHOLD_UNHEALTHY_AFTER | 60 | Seconds (integer); 0disables the check | How long the memory threshold may refuse requests without a break before /healthanswers 503 Service Unavailable, so that a liveness probe restarts the process. Any observation below the threshold resets the clock. Has no effect while SURREAL_MEMORY_THRESHOLDis not set. |
SURREAL_OBJECT_STORE | a storefolder in the current directory | A URL, such as file:///var/lib/surrealdb/store | Where SurrealML model files were stored. SurrealDB 4.0 removed SurrealML, so a 4.0 server stores nothing here. The folder is created when it does not exist. |
SURREAL_CACHE_STORE | a cachefolder in the current directory | A URL, such as file:///var/lib/surrealdb/cache | Where SurrealML model files were cached. SurrealDB 4.0 removed SurrealML, so a 4.0 server caches nothing here. The folder is created when it does not exist. |
SURREAL_REGEX_CACHE_SIZE | 1000 | An integer from 10 to 100,000; a value outside that range is treated as the nearest end of it | The number of computed regexes which can be cached in the engine. |
Command environment variables
Many of the arguments passed into the CLI can be set using the above environment variables instead.
As each of these environment variables correspond to a flag or a required argument passed into a command, it is good practice to put together a command that matches the environment variables you wish to set. Once the database server conforms to your expected behaviour, you can then pull out the values passed into each flag for your environment variables.
For example, take the following command to start the database.
surreal db start --user root --pass secret --allow-net --deny-funcs "crypto::md5, http::post, http::delete"If we now wanted to use environment variables instead of the --allow-net and --deny-funcs flags, we would use the SURREAL_CAPS_ALLOW_NET and SURREAL_CAPS_DENY_FUNC environment variables.
As the --allow-net flag was passed in without a following value, the same will be the case with the SURREAL_CAPS_ALLOW_NET environment variable, becoming SURREAL_CAPS_ALLOW_NET=. The --deny-funcs flag can also be used on its own to deny execution of all functions, but in this case is followed by a string to indicate which exact functions are not allowed to be executed. As such, the SURREAL_CAPS_DENY_FUNC environment variable must also be followed by a string, becoming SURREAL_CAPS_DENY_FUNC="crypto::md5, http::post, http::delete".
The command would then look like the following:
export SURREAL_CAPS_ALLOW_NET=
export SURREAL_CAPS_DENY_FUNC="crypto::md5, http::post, http::delete"
surreal db start --user root --pass secretA command environment variable that takes a boolean will be set to true if the flag is present, and following it with true will cause an error.
For example, the SURREAL_CAPS_ALLOW_ALL environment variable is used to set whether to allow all capabilities such as scripting and allowing network access. The flag --allow-all is all that is needed to set to true. But as an environment variable, the value true must be included to override its default false value.
# set to default false
surreal db start
# Same, but implicitly shown
SURREAL_CAPS_ALLOW_ALL=false surreal db start
# Set to true
SURREAL_CAPS_ALLOW_ALL=true surreal db start
# Set to true
surreal db start --allow-all
# Error: only --allow-all needed to set to true
surreal db start --allow-all trueEnvironment variable | Command arg | For command(s) | Default | Allowed values | Details |
|---|---|---|---|---|---|
SURREAL_ALLOW_ORIGIN | allow-origin |
| All origins | A comma-separated list of origins | The origins allowed to make cross-origin (CORS) requests, such as https://app.example.com. When it is not set, every origin is allowed. When it lists origins and no *, a WebSocket connection to /rpcthat sends an Originheader is accepted only from a listed origin or with Sec-Fetch-Site: same-origin. |
SURREAL_ASYNC_EVENT_PROCESSING_INTERVAL | async-event-interval |
| 5s | A duration | The interval at which to process async events. |
SURREAL_AUTH_LEVEL | auth-level |
| root | root, namespace, ns, database, db | Authentication level to use when connecting. |
SURREAL_BIND | bind |
| 127.0.0.1:8000 | String to an address | The hostname or IP address(es) to listen for connections on. |
SURREAL_POSTGRES_BIND | postgres-bind |
| (disabled) | String to an address | The hostname or IP address to listen for Postgres wire protocol connections on. |
SURREAL_MYSQL_BIND | mysql-bind |
| (disabled) | String to an address | The hostname or IP address to listen for MySQL wire protocol connections on, for example 127.0.0.1:3306. The listener is disabled when this is not set. |
SURREAL_CAPS_ALLOW_ALL | allow-all |
| false | true, false | Allow all capabilities. |
SURREAL_CAPS_ALLOW_ARBITRARY_QUERY | allow-arbitrary-query |
| none | guest, record, system (comma-separated) | Allows arbitrary queries to be used by user groups except when specifically denied. Alternatively, you can provide a comma-separated list of user groups to allow specifically denied user groups to prevail over any other allowed user group. |
SURREAL_CAPS_ALLOW_EVAL_QUERY | allow-eval-query |
| none (denied for all subjects) | guest, record, system (comma-separated) | Allow eval::surqland eval::gqlfor listed subject groups. Not enabled by --allow-all. Still subject to arbitrary-query restrictions - --deny-arbitrary-queryblocks evalfor that subject even when eval is allowed here. For remote clients, set on the startprocess only. See Capabilities and remote connections . |
SURREAL_CAPS_ALLOW_EXPERIMENTAL | allow-experimental |
| none | surrealism, kvexport (comma-separated) | Allow execution of experimental features. For remote clients, set on the startprocess. On surreal db sql, affects embedded engines and REPL parse validation only. See experimental capabilities . kvexportturns on the POST /kvexportroute. From 3.3.0, ISO GQL is on by default and does not need this variable, and from 4.0 the same applies to buckets and files. From 4.0, the values gqland filesare refused as invalid names, and the server does not start. |
SURREAL_CAPS_ALLOW_FUNC | allow-funcs |
| all functions allowed | Empty, *, or comma-separated function paths | Allow execution of all functions except for functions that are specifically denied. Set to an empty value or *to allow all functions. Use a comma-separated list (for example, array,string::len,http::get) to allow specific function families or names. Values such as trueare not valid. The environment variable name is singular ( FUNC), matching the --allow-funcsflag. |
SURREAL_CAPS_ALLOW_GUESTS | allow-guests |
| false | true, false | Allow guest users to execute queries. |
SURREAL_CAPS_ALLOW_HTTP | allow-http |
| all routes allowed | Empty, or a comma-separated list of HTTP routes | Allow all HTTP routes except those specifically denied, or only the listed routes. Route names: health, export, kvexport, import, rpc, version, sync, sql, signin, signup, key, bucket, graphql, api, mcp, gql, postgres, mysql. |
SURREAL_CAPS_ALLOW_MCP | allow-mcp |
| all tools allowed | Empty, or a comma-separated list of MCP tool names | Allow all tools of the built-in MCP server except those specifically denied, or only the listed tools. |
SURREAL_CAPS_ALLOW_NET | allow-net |
| none | Comma-separated list of paths | Allow all or certain outbound network access. |
SURREAL_CAPS_ALLOW_RPC | allow-rpc |
| all methods allowed | Empty, or a comma-separated list of RPC methods | Allow all RPC methods except those specifically denied, or only the listed methods. |
SURREAL_CAPS_ALLOW_SCRIPT | allow-scripting |
| false | true, false | Allow execution of embedded scripting functions. |
SURREAL_CAPS_ALLOW_INSECURE_STORABLE_CLOSURES | allow-insecure-storable-closures |
| false | true, false | Takes a boolean. From 2.5.0, closures cannot be stored, which removes a potential attack surface; on 2.5.x and 2.6.x this capability allows them again. Removed in 3.0.0, where closures can never be stored and the flag is rejected. |
SURREAL_CAPS_DENY_ALL | deny-all |
| false | true, false | Deny all capabilities. |
SURREAL_CAPS_DENY_ARBITRARY_QUERY | deny-arbitrary-query |
| none | guest, record, system (comma-separated) | Deny arbitrary queries for the listed user groups, or for all of them when no value is given. Specifically allowed user groups prevail over a general denial. |
SURREAL_CAPS_DENY_EVAL_QUERY | deny-eval-query |
| none | guest, record, system (comma-separated) | Deny eval::surqland eval::gqlfor listed subject groups. Deny prevails over allow at the same specificity. For remote clients, set on the startprocess. |
SURREAL_CAPS_DENY_FUNC | deny-funcs |
| false | true, false, comma-separated list | Deny execution of all or certain functions. |
SURREAL_CAPS_DENY_GUESTS | deny-guests |
| true | true, false | Deny guest users from executing queries. |
SURREAL_CAPS_DENY_HTTP | deny-http |
| none | Empty, or a comma-separated list of HTTP routes | Deny all HTTP routes except those specifically allowed, or only the listed routes. Uses the same route names as SURREAL_CAPS_ALLOW_HTTP. |
SURREAL_CAPS_DENY_MCP | deny-mcp |
| none | Empty, or a comma-separated list of MCP tool names | Deny all tools of the built-in MCP server except those specifically allowed, or only the listed tools. |
SURREAL_CAPS_DENY_NET | deny-net |
| true | true, false, comma-separated list | Deny all or certain outbound access paths. |
SURREAL_CAPS_DENY_RPC | deny-rpc |
| none | Empty, or a comma-separated list of RPC methods | Deny all RPC methods except those specifically allowed, or only the listed methods. |
SURREAL_CAPS_DENY_SCRIPT | deny-scripting |
| true | true, false | Deny execution of embedded scripting functions. |
SURREAL_COOKIE_AUTH | cookie-auth |
| false | true, false | Issue the access token as an HttpOnlycookie through /signin/cookieand /signup/cookie, and accept the cookie from the origins in SURREAL_ALLOW_ORIGIN. When the record access method has WITH REFRESH, the refresh token is issued as a second HttpOnlycookie, and POST /refresh/cookierotates both. Requires SURREAL_ALLOW_ORIGINwith no *entry. See Cookie authentication . |
SURREAL_CHANGEFEED_GC_INTERVAL | changefeed-gc-interval |
| 30s | A duration | The interval at which to perform changefeed garbage collection. |
SURREAL_CLIENT_IP | client-ip |
| socket | none, socket, CF-Connecting-IP, Fly-Client-IP, True-Client-IP, X-Real-IP, X-Forwarded-For, Forwarded | The method of detecting the client's IP address. Forwardedparses the RFC 7239 Forwardedheader ( for=parameter). |
SURREAL_DATABASE | database |
| main | A string | The database selected when starting the REPL. |
SURREAL_DATABASE | database |
| none | A string | The database selected for the import or export. |
SURREAL_DEFAULT_DATABASE | default-database |
| main | A string | The default database to use when starting a SurrealDB instance. |
SURREAL_DEFAULT_NAMESPACE | default-namespace |
| main | A string | The default namespace to use when starting a SurrealDB instance. |
SURREAL_DURABLE_SESSIONS | durable-sessions |
| false | true, false | From 4.0.0 this variable has no effect: every attached HTTP RPC session is stored in the datastore, and the server still accepts the flag and the variable, and logs a deprecation warning. Before 4.0.0 it persists client-attached HTTP RPC sessions in the datastore so they survive restarts and can be resumed on any node sharing the storage, and is off by default. WebSocket sessions are not durable. The persisted copy includes authentication state and is stored unencrypted. See Durable HTTP RPC sessions . |
SURREAL_DURABLE_SESSION_GC_INTERVAL | durable-session-gc-interval |
| 1h (60s before 4.0.0) | A duration; 0disables the background sweep | How often expired attached HTTP RPC sessions are purged from the datastore. An expired session is refused whether or not it has been purged, so the sweep only reclaims storage. Before 4.0.0 it applies only when durable sessions are enabled. |
SURREAL_DURABLE_SESSION_TTL | durable-session-ttl |
| 24h | A duration of at least 1ms | Idle lifetime of an attached HTTP RPC session; each use refreshes the expiry (sliding TTL). From 4.0.0 a session expires between one and one and a half times this value after its last request, and applies to every attached HTTP RPC session. Before 4.0.0 it applies only when durable sessions are enabled. |
SURREAL_GRAPH_FOLD_INTERVAL | graph-fold-interval |
| 5s | A duration | The interval between background passes that fold a vertex's per-edge graph adjacency keys into packed blocks. A pass also starts early when a write queues fold work or a traversal meets a vertex with many unfolded keys. See also SURREAL_GRAPH_FOLD_BATCH. |
SURREAL_HIDE_WELCOME | hide-welcome |
| false | true, false | Whether to show the welcome message when starting the REPL. |
SURREAL_IMPORT_FILE | import-file |
| none | A file path | Path to a SurrealQL file that will be imported when starting the server. |
SURREAL_INDEX_BUILD_RESUME_INTERVAL | index-build-resume-interval |
| 30s | A duration; 0disables it | The interval at which a node looks for index builds that a node which stopped left unfinished, and resumes them. |
SURREAL_INDEX_COMPACTION_INTERVAL | index-compaction-interval |
| 5s | A duration | The interval at which to compact queued index updates. Writes to a full-text, count, or vector index enqueue pending updates that a background task folds into the index; this controls how often that task runs. One node in a cluster performs the work for the whole cluster. Lengthening the interval allows the pending backlog to grow, which increases the work each subsequent query must do to read through it. |
SURREAL_KEY | key |
| none | A string 16, 24, or 32 bytes long | Encryption key to use for on-disk encryption. Not currently in use. |
SURREAL_KVS_CA | kvs-ca |
| none | String to a path | Path to the CA file used when connecting to the remote KV store. |
SURREAL_KVS_CRT | kvs-crt |
| none | String to a path | Path to the certificate file used when connecting to the remote KV store. |
SURREAL_KVS_KEY | kvs-key |
| none | String to a path | Path to the private key file used when connecting to the remote KV store. |
SURREAL_LAZY_SURREALISM | lazy-surrealism |
| false | true, false | Whether to lazy-load Surrealism modules instead of eagerly compiling them at server startup. |
SURREAL_LOG | log |
| info | none, full, error, warn, info, debug, trace | The logging level for the database server. In a release build, traceand fullgive the same output as debug, because the TRACE level is compiled only into debug builds. |
SURREAL_LOG_FILE_ENABLED | log-file-enabled |
| false | true, false | Toggles file output. |
SURREAL_LOG_FILE_FORMAT | log-file-format |
| text | text, json | The format for log file output. |
SURREAL_LOG_FILE_LEVEL | log-file-level |
| none | none, full, error, warn, info, debug, trace | Override the logging level for file output. In a release build, traceand fullgive the same output as debug, because the TRACE level is compiled only into debug builds. |
SURREAL_LOG_FILE_NAME | log-file-name |
| surrealdb.log | String to a file | Filename for logs (default: |
SURREAL_LOG_FILE_PATH | log-file-path |
| logs | String to a path | Sets the directory for logs |
SURREAL_LOG_FILE_ROTATION | log-file-rotation |
| daily | daily, hourly, never | Sets the rotation duration for logs. |
SURREAL_LOG_FORMAT | log-format |
| text | text, json | Sets the format for logs. |
SURREAL_LOG_OTEL_LEVEL | log-otel-level |
| SURREAL_LOG logging level | none, full, error, warn, info, debug, trace | Override the logging level for OpenTelemetry. In a release build, traceand fullgive the same output as debug, because the TRACE level is compiled only into debug builds. |
SURREAL_LOG_SOCKET | log-socket |
| none | String to a host:port | Send logs to the specified host:port |
SURREAL_LOG_SOCKET_FORMAT | log-socket-format |
| text | text, json | Set the format of the logs to the socket. |
SURREAL_LOG_SOCKET_LEVEL | log-socket-level |
| SURREAL_LOG logging level | none, full, error, warn, info, debug, trace | Override the logging level for socket logs. In a release build, traceand fullgive the same output as debug, because the TRACE level is compiled only into debug builds. |
SURREAL_NAMESPACE | namespace |
| main | A string | The namespace to connect to via the REPL. |
SURREAL_NAMESPACE | namespace |
| none | A string | The namespace selected for the import/export operation. |
SURREAL_NO_BANNER | no-banner |
| false | true, false | Whether to hide the startup banner. |
SURREAL_NO_DEFAULTS | no-defaults | `start` | false | true, false | Whether to disable default namespace and database creation. Conflicts with SURREAL_DEFAULT_DATABASE and SURREAL_DEFAULT_NAMESPACE, which set a default value for namespace and database for a new instance. |
SURREAL_NO_IDENTIFICATION_HEADERS | no-identification-headers |
| false | true, false | Whether to suppress the server name and version headers. |
SURREAL_NODE_MEMBERSHIP_CHECK_INTERVAL | node-membership-check-interval |
| 15s | A duration | The interval at which to process and archive inactive nodes. |
SURREAL_NODE_MEMBERSHIP_CLEANUP_INTERVAL | node-membership-cleanup-interval |
| 300s | A duration | The interval at which to process and cleanup archived nodes. |
SURREAL_NODE_MEMBERSHIP_REFRESH_INTERVAL | node-membership-refresh-interval |
| 3s | A duration | The interval at which to refresh node registration information. The /readyendpoint reports the node unhealthy when its cluster heartbeat is older than three times this interval (9s by default). The multiple is fixed and cannot be configured. From SurrealDB 4.0, on a datastore that several nodes write, such as TiKV, a value above 10s stops the node from starting. |
SURREAL_PASS | pass |
| none | A string | Database authentication password to use when connecting. For start, the password of the initial root user, which cannot be empty or only whitespace. |
SURREAL_PATH | path |
| memory | A string | Database path used for storing data. As a required argument (albeit with a default), it is not passed in via |
SURREAL_PLANNER_STRATEGY | planner-strategy |
| None (before 4.0.0, best-effort) | best-effort|compute-only|all-read-only | Deprecated, and has no effect from 4.0.0 as queries run on a single execution engine. The server still accepts the three values so that an existing configuration keeps starting, logs a deprecation warning and ignores them, and refuses to start on any other value. Remove it from your configuration. Before 4.0.0 it chose how far to use the query planner introduced in 3.0: the default used the new planner for read-only statements and fell back to the earlier compute planner on paths it did not implement, and compute-only skipped the new planner entirely. |
SURREAL_QUERY_TIMEOUT | query-timeout |
| none | A duration | The maximum duration that a batch of statements can run for. From 3.3.0 it is also a hard wall-clock limit on each HTTP /sql, /gqland /graphqlrequest and on each RPC method call. An HTTP /sqlor /gqlrequest that exceeds it is answered with 504 Gateway Timeout, and a /graphqlrequest with a GraphQL error. The begin, commitand cancelRPC methods are exempt, but the calls made inside the transaction they control are still limited individually. |
SURREAL_RECLAIM_INTERVAL | reclaim-interval |
| 60s | A duration | How often the background reaper scans for tombstoned namespace, database, and index data to physically delete after a REMOVEstatement. On the 2.x line it is available from 2.7.0 and covers namespaces and databases only. |
SURREAL_RECLAIM_GRACE | reclaim-grace |
| 10m | A duration | Minimum age a removed namespace, database, or index must reach before its data is reclaimed. The effective grace is the maximum of this value and --tikv-gc-lifetimeon TiKV backends. Not available on 2.x. |
SURREAL_SLOW_QUERY_LOG_THRESHOLD | slow-log-threshold |
| none | A duration | A duration specifying the minimum execution time after which a log is made to indicate a slow query |
SURREAL_SLOW_QUERY_LOG_PARAM_ALLOW | slow-log-param-allow |
| none | Comma-separated strings | A comma-separated list of parameter names whose values are listed in slow query logs. No parameter value is logged unless its name is listed here. See Logging . |
SURREAL_SLOW_QUERY_LOG_PARAM_DENY | slow-log-param-deny |
| none | Comma-separated strings | A comma-separated list of parameter names whose values are left out of slow query logs, even when SURREAL_SLOW_QUERY_LOG_PARAM_ALLOWalso names them. |
SURREAL_STRICT | strict |
| false | true, false | Whether strict mode is enabled on this database instance. Ignored since SurrealDB 3.0 after which strictness is defined per database instead of instance. |
SURREAL_STARTUP_OPERATION_TIMEOUT | startup-operation-timeout |
| 60s | A duration | How long each built-in startup datastore operation may keep retrying before the server gives up. It is a per-operation budget rather than a total for startup, and it covers initialising the default namespace and database, initialising the root credentials, and registering this node in the cluster. Raise it where the storage backend is slow to accept the first writes. |
SURREAL_TEMPORARY_DIRECTORY | temporary-directory |
| A surrealdbfolder in the system temporary directory | String to a directory | Sets the directory for storing temporary database files, including the files that queries spill to when they pass their memory budget. Before 4.0.0 there was no default and the directory was used only by queries with TEMPFILES. A value that is not a directory is refused at startup. See Memory limits and spilling to disk . |
SURREAL_TIKV_GC_INTERVAL | tikv-gc-interval |
| 10m | A duration | The interval at which the TiKV MVCC garbage collector runs. Only used with a TiKV datastore. |
SURREAL_TIKV_GC_LIFETIME | tikv-gc-lifetime |
| 10m | A duration | How far behind the current timestamp the TiKV garbage collection safepoint may sit. Only used with a TiKV datastore. The effective SURREAL_RECLAIM_GRACEis never shorter than this value. |
SURREAL_TIKV_LOCK_CLEANUP_INTERVAL | tikv-lock-cleanup-interval |
| 60s | A duration | The interval at which stale TiKV transaction locks are resolved. Only used with a TiKV datastore. |
SURREAL_TOKEN | token |
| none | A string | Authentication token in JWT format to use when connecting. |
SURREAL_TRANSACTION_TIMEOUT | transaction-timeout |
| none | A duration | The maximum duration that any single transaction can run for. |
SURREAL_UNAUTHENTICATED | unauthenticated |
| false | true, false | Whether to allow unauthenticated access. |
SURREAL_USER | user |
| none | A string | Database authentication username to use when connecting. For start, the username of the initial root user, which cannot be empty or only whitespace. |
SURREAL_WEB_CRT | web-crt |
| none | String to a path | Path to the certificate file for encrypted client connections. |
SURREAL_WEB_KEY | web-key |
| none | String to a path | Path to the private key file for encrypted client connections. |
Authentication rate limiting environment variables
Available since: v3.3.0
These variables throttle authentication attempts on the HTTP /signin and /signup endpoints, per client address. Both endpoints draw on one shared budget. A request to any other endpoint that carries HTTP Basic credentials (Authorization: Basic ...) is counted as a sign-in attempt and draws on the same budget. The limiter is off by default, and setting any of the burst, rate, or tracked-client values to 0 also turns it off.
An attempt that exceeds the budget is answered with 429 Too Many Requests and a Retry-After header giving the seconds to wait.
The limiter keys on the address resolved by --client-ip, so it needs a strategy that yields one address per client. With --client-ip socket behind a proxy, every request resolves to the proxy's address and shares a single budget, which throttles all authentication collectively. With --client-ip none no address is available and the limiter does nothing. A header strategy is only as trustworthy as the proxy setting the header: a request arriving without it yields no address and is admitted unchecked, so a header strategy protects only a deployment where every request to these endpoints passes through that proxy.
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_HTTP_AUTH_RATE_LIMIT_ENABLED | false | true, false | Whether to rate limit authentication attempts on the HTTP /signinand /signupendpoints per client address. Only trueand falseare accepted; any other value is ignored and the default applies. |
SURREAL_HTTP_AUTH_RATE_LIMIT_BURST | 60 | A u32 | How many authentication attempts a single client address may make before being throttled. Set to 0to disable the limiter. |
SURREAL_HTTP_AUTH_RATE_LIMIT_PER_MINUTE | 60 | A u32 | The sustained rate, in attempts per minute, at which a client address's budget refills. The default of 60 is one attempt per second. Set to 0to disable the limiter. |
SURREAL_HTTP_AUTH_RATE_LIMIT_MAX_TRACKED_CLIENTS | 16384 | A usize | How many client addresses the limiter tracks at once. Unauthenticated callers write to this store, so it is a bounded cache: at capacity a new address evicts an existing entry rather than the store growing or the limiter switching off. An evicted address starts again from a full burst, so the sustained rate binds an address only while it stays tracked. Size this above the number of distinct addresses the instance authenticates. Set to 0to disable the limiter. |
Storage backend environment variables
These environment variables are used to configure the storage backend for SurrealDB.
Some defaults below depend on system memory. That is the memory available to the SurrealDB process: the host's memory, lowered to the tightest memory limit of the cgroup the process runs in, whether that limit comes from a container or from a systemd unit's MemoryMax. Before SurrealDB 4.0, only a limit at the root of the process's cgroup hierarchy was read, which covers containers but not a systemd unit, so a server capped by systemd sized its caches from the whole host.
SurrealKV environment variables
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_SURREALKV_BLOCK_CACHE_CAPACITY | Dynamically calculated via greater of ((system memory / 2) - 1 GiB) and 16MiB | A usize | The capacity of the block cache in bytes. The cache holds recently read data blocks in memory. From 4.0 a compaction does not add the blocks it reads to the cache, and it removes the cached blocks of the tables it merged, so the cache holds blocks of live tables only. |
SURREAL_SURREALKV_BLOCK_SIZE | 65_536 (64 KiB) | A usize | The block size in bytes. |
SURREAL_SURREALKV_ENABLE_VLOG | true | true, false | Whether to enable value log separation. |
SURREAL_SURREALKV_GROUPED_COMMIT_MAX_BATCH_SIZE | 4096 | A usize | The maximum number of transactions in a single grouped commit batch. This prevents unbounded memory growth while still allowing large batches for efficiency. Larger batches improve throughput but increase memory usage and commit latency. From 4.0 the setting has no effect, because SurrealKV groups the syncs of concurrent commits itself, and the server logs a warning and ignores it. |
SURREAL_SURREALKV_GROUPED_COMMIT_TIMEOUT | 5ms | A duration in nanoseconds | The maximum wait time in nanoseconds before forcing a grouped commit. Ensures that transactions do not wait indefinitely under low concurrency and balances commit latency against write throughput. From 4.0 the setting has no effect, because SurrealKV groups the syncs of concurrent commits itself, and the server logs a warning and ignores it. |
SURREAL_SURREALKV_GROUPED_COMMIT_WAIT_THRESHOLD | 12 | A usize | Threshold for deciding whether to wait for more transactions. If the current batch size is greater or equal to this threshold (and below SURREAL_SURREALKV_GROUPED_COMMIT_MAX_BATCH_SIZE), then the coordinator will wait up to SURREAL_SURREALKV_GROUPED_COMMIT_TIMEOUT to collect more transactions. Smaller batches are flushed immediately to preserve low latency. From 4.0 the setting has no effect, because SurrealKV groups the syncs of concurrent commits itself, and the server logs a warning and ignores it. |
SURREAL_SURREALKV_MAX_MEMTABLE_SIZE | Depends on system memory: 64 MiB below 1 GiB, 128 MiB below 4 GiB, 256 MiB below 16 GiB, 1 GiB below 64 GiB, and 4 GiB otherwise | A usize | The most memory a memtable holds before it is flushed to disk. The memtable holds recent writes. The limit counts the values the memtable holds as well as the memory area that indexes them, so a large load flushes to disk while it runs. From 4.0 it bounds the memory the memtable holds, not the size of a transaction: a commit too large for the memtable is written directly to a level-0 table. Before 4.0 a transaction larger than this fails, so raise it for large transactions. |
SURREAL_SURREALKV_VERSIONED_INDEX | false | true, false | Whether to enable versioned index. Only applies when versioning is enabled. From 4.0 the setting has no effect, because SurrealKV 1.0 reads versions without a separate index, and the server logs a warning and ignores it. |
SURREAL_SURREALKV_VLOG_MAX_FILE_SIZE | 64 MiB (systems under 4 GiB), 128 MiB (up to 16 GiB), 256 MiB (up to 64 GiB), 512 MiB (others) | A usize | The maximum size of a value log file in bytes. |
SURREAL_SURREALKV_VLOG_THRESHOLD | 4096 (4 KiB) | A usize | The value log threshold in bytes. Values larger than this are stored in the value log. |
TiKV environment variables
These variables apply when SurrealDB is started with a tikv:// endpoint for local Community experimentation. From SurrealDB 4.0, only the separate surreal-tikv build accepts a tikv:// endpoint, and it reads the same variables. They are not the configuration surface for production multi-node HA. Prefer a managed cluster on SurrealDB Cloud Scale or a self-hosted cluster with SurrealDB Enterprise. See Run a multi-node cluster.
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_TIKV_API_VERSION | 1 | A u8 | Which TiKV cluster API version to use. |
SURREAL_TIKV_ASYNC_COMMIT | true | true, false | Whether to use asynchronous transactions. |
SURREAL_TIKV_KEYSPACE | none | A string | A string specifying the keyspace identifier for data isolation. |
SURREAL_TIKV_DELR_MAX_KEYS | 1,000,000 | A u32 | The most keys that one range delete in a TiKV transaction may remove. A larger range fails with an error rather than growing the transaction without bound. |
SURREAL_TIKV_GC_ENABLED | true | true, false | Whether the background TiKV garbage collection runs. When false, the stale lock cleanup is skipped as well. The interval and lifetime are set with SURREAL_TIKV_GC_INTERVALand SURREAL_TIKV_GC_LIFETIME, described under Command environment variables . |
SURREAL_TIKV_GRPC_MAX_DECODING_MESSAGE_SIZE | 4,194,304 (4 MiB) | A usize | Sets the maximum size of a gRPC message that SurrealDB receives from TiKV, which limits how much one read can return. A single record or a batch of records larger than this fails with decoded message length too large. Raise it together with SURREAL_TIKV_GRPC_MAX_ENCODING_MESSAGE_SIZE, so that a record that can be written can also be read back. |
SURREAL_TIKV_GRPC_MAX_ENCODING_MESSAGE_SIZE | 4,194,304 (4 MiB) | A usize | Sets the maximum size of a gRPC message that SurrealDB sends to TiKV, which limits the size of a single write. A record larger than this fails with an h2 protocol error. TiKV refuses a single write above its own entry limit of 8 MiB whatever this is set to, with The transaction is too large. |
SURREAL_TIKV_HEALTH_PROBE | true | true, false | Whether the server checks that the TiKV cluster answers when it connects at startup, so that an unreachable cluster fails the start rather than the first query. |
SURREAL_TIKV_ONE_PHASE_COMMIT | true | true, false | Whether to use one-phase transaction commit. |
SURREAL_TIKV_REQUEST_TIMEOUT | 10 | A usize | The duration in seconds for requests before they time out. |
SURREAL_TIKV_SHUTDOWN_GRACE | 30 | Seconds (integer) | How long a shutdown waits for running transactions to finish before it continues. |
SURREAL_TIKV_SHUTDOWN_GC_TIMEOUT | 10 | Seconds (integer) | The longest that the last garbage collection pass at shutdown may take, so that a slow pass does not hold up the exit. |
SURREAL_TIKV_TLS_CA_PATH | none | A file path | Path to the CA certificate used to verify the TiKV and PD servers. Setting all three SURREAL_TIKV_TLS_*variables switches the connection to mutual TLS (mTLS). |
SURREAL_TIKV_TLS_CERT_PATH | none | A file path | Path to the client certificate that SurrealDB presents during mTLS. It must be set together with the CA and key paths. |
SURREAL_TIKV_TLS_KEY_PATH | none | A file path | Path to the private key that matches the client certificate. It must be set together with the CA and certificate paths. If only some of the three paths are set, SurrealDB refuses to connect and reports which are missing. |
RocksDB environment variables
RocksDB support was removed in SurrealDB 4.0. These variables apply to 3.x and earlier only. See Moving a RocksDB database to SurrealKV.
Many RocksDB environment variables pertain to memory use. The default configuration results in the following rough estimates of RocksDB memory use on different instances:
| Instance memory size | Estimate |
|---|---|
| 512 MiB | ~ 80MiB |
| 1 GiB | ~ 80MiB |
| 2 GiB | ~ 640MiB |
| 4 GiB | ~ 1.25GiB |
| 8 GiB | ~ 3.25GiB |
| 24 GiB | ~ 12GiB |
| 128 GiB | ~ 67GiB |
The available environment variables for configuring a RocksDB instance are:
Environment variable | Default | Allowed values | Notes |
|---|---|---|---|
SURREAL_ROCKSDB_BACKGROUND_FLUSH | true | false, true | Whether to enable background WAL file flushing. 2.x only: from 3.0.0, set a duration on SURREAL_DATASTORE_SYNC_DATAinstead. |
SURREAL_ROCKSDB_BACKGROUND_FLUSH_INTERVAL | 200 (milliseconds) | A usize | The interval in milliseconds between background flushes. 2.x only: from 3.0.0, set a duration on SURREAL_DATASTORE_SYNC_DATAinstead. |
SURREAL_ROCKSDB_BLOB_COMPACTION_READAHEAD_SIZE | 0 | A usize | Readahead size for blob compaction/GC. |
SURREAL_ROCKSDB_BLOB_COMPRESSION_TYPE | snappy | none, snappy, lz4, zstd | Compression type used for blob files. |
SURREAL_ROCKSDB_BLOB_FILE_SIZE | 268,435,456 (256 MiB) | A usize | The target blob file size for RocksDB. |
SURREAL_ROCKSDB_BLOB_GC_AGE_CUTOFF | 0.5 | Float between 0 and 1 | Fractional age cutoff for blob GC. |
SURREAL_ROCKSDB_BLOB_GC_FORCE_THRESHOLD | 0.5 | Float between 0 and 1 | Discardable ratio threshold to force GC. |
SURREAL_ROCKSDB_BLOCK_CACHE_SIZE | Dynamically calculated via greater of ((system memory / 2) - 1 GiB) and 16MiB | A usize | RocksDB block cache size in bytes |
SURREAL_ROCKSDB_BLOCK_SIZE | 65,536 (64 KiB) | A usize | The size of each uncompressed data block in bytes. |
SURREAL_ROCKSDB_COMPACTION_READAHEAD_SIZE | 4 MiB (systems under 4 GiB), 8 MiB (up to 16 GiB), 16 MiB (others) | A usize | The readahead buffer size used during compaction. |
SURREAL_ROCKSDB_COMPACTION_STYLE | level | level, universal | Use to specify the database compaction style. |
SURREAL_ROCKSDB_COMPACT_ON_SHUTDOWN | false | true, false | Whether a graceful shutdown runs a full compaction of the database after flushing the memtables, as ALTER SYSTEM COMPACTdoes. On a large database this can take minutes or hours, which can be longer than the shutdown grace period of a container orchestrator. |
SURREAL_ROCKSDB_DELETION_FACTORY_DELETE_COUNT | 50 | A usize | The number of deletions to track in the window. |
SURREAL_ROCKSDB_DELETION_FACTORY_RATIO | 0.5 | A float | The ratio of deletions to track in the window. |
SURREAL_ROCKSDB_DELETION_FACTORY_WINDOW_SIZE | 1000 | A usize | The size of the window used to track deletions. |
SURREAL_ROCKSDB_ENABLE_BLOB_FILES | true | true, false | Whether to enable separate key and value file storage. |
SURREAL_ROCKSDB_ENABLE_BLOB_GC | true | true, false | Whether to enable blob garbage collection for RocksDB. |
SURREAL_ROCKSDB_ENABLE_PIPELINED_WRITES | true | true, false | Whether to use separate queues for WAL writes and memtable writes. |
SURREAL_ROCKSDB_FILE_COMPACTION_TRIGGER | 4 | A usize | The number of files needed to trigger level 0 compaction. |
SURREAL_ROCKSDB_FILE_READS_FOR_AUTO_READAHEAD | 2 | A u64 | The number of sequential reads an iterator makes on one SST file before RocksDB starts to prefetch. Set to 0to prefetch from the first read. |
SURREAL_ROCKSDB_GROUPED_COMMIT_MAX_BATCH_SIZE | 4096 | A usize | The maximum number of transactions in a single grouped commit batch. Used to prevent unbounded memory growth while still allowing large batches for efficiency. Larger batches improve throughput but increase memory usage and commit latency. |
SURREAL_ROCKSDB_GROUPED_COMMIT_TIMEOUT | 5ms | A duration | The maximum wait time in nanosecond before forcing a grouped commit. Used to ensure that transactions do not wait indefinitely when concurrency is low, and to balance between transaction latency and write throughput. |
SURREAL_ROCKSDB_GROUPED_COMMIT_WAIT_THRESHOLD | 12 | A usize | Threshold for deciding whether to wait for more transactions. If the current batch size is greater or equal to this threshold (and below ROCKSDB_GROUPED_COMMIT_MAX_BATCH_SIZE), then the coordinator will wait up to ROCKSDB_GROUPED_COMMIT_TIMEOUT to collect more transactions. Smaller batches are flushed immediately to preserve low latency. |
SURREAL_ROCKSDB_INITIAL_AUTO_READAHEAD_SIZE | 8,192 (8 KiB) | A usize | The size of the first prefetch. Each following read doubles it, up to SURREAL_ROCKSDB_MAX_AUTO_READAHEAD_SIZE. |
SURREAL_ROCKSDB_JOBS_COUNT | Number of CPUs * 2 | A usize | The maximum number of threads to use for flushing and compaction. |
SURREAL_ROCKSDB_KEEP_LOG_FILE_NUM | 10 | A usize | The maximum number of information log files to keep. |
SURREAL_ROCKSDB_LEVEL0_SLOWDOWN_WRITES_TRIGGER | 8 | An i32 | The number of level-0 files at which RocksDB starts to slow down writes. The RocksDB default is 20. |
SURREAL_ROCKSDB_LEVEL0_STOP_WRITES_TRIGGER | 12 | An i32 | The number of level-0 files at which RocksDB stops writes until compaction reduces the count. Keep it above SURREAL_ROCKSDB_LEVEL0_SLOWDOWN_WRITES_TRIGGER. The RocksDB default is 36. |
SURREAL_ROCKSDB_MAX_AUTO_READAHEAD_SIZE | 262,144 (256 KiB) | A usize | The largest prefetch an iterator grows to. A larger value can make long range scans faster, but uses more memory for each iterator, so many concurrent scans multiply the cost. |
SURREAL_ROCKSDB_MAX_CONCURRENT_SUBCOMPACTIONS | 4 | A usize | The maximum number threads which will perform compactions. |
SURREAL_ROCKSDB_MAX_OPEN_FILES | 1024 | A usize | The maximum number of open files which can be opened by RocksDB. |
SURREAL_ROCKSDB_MAX_WRITE_BUFFER_NUMBER | 2 (systems under 4 GiB), 4 (up to 16 GiB), 8 (up to 64 GiB), 32 (others) | A usize | The maximum number of write buffers which can be used. |
SURREAL_ROCKSDB_MEMTABLE_PREFIX_BLOOM_RATIO | 0.1 | An f64 | The size of the prefix bloom filter in each memtable, as a ratio of the write buffer size. RocksDB caps it at 0.25. Set to 0to disable it. Only used when SURREAL_ROCKSDB_PREFIX_EXTRACTOR_ENABLEDis true. |
SURREAL_ROCKSDB_MIN_BLOB_SIZE | 4096 | A usize | The minimum size in bytes of a value for it to be stored in blob files. |
SURREAL_ROCKSDB_MIN_WRITE_BUFFER_NUMBER_TO_MERGE | 2 | A usize | The minimum number of write buffers to merge before writing to disk. |
SURREAL_ROCKSDB_PERIODIC_COMPACTION_SECONDS | 3600 | A u64 | The interval in seconds after which RocksDB rewrites an SST file that no other compaction has touched. This removes old versions and tombstones from data that is rarely written. Set to 0to disable. |
SURREAL_ROCKSDB_PREFIX_EXTRACTOR_ENABLED | true | true, false | Whether SST bloom filters are built on table and key-type prefixes, so that a scan can skip SST files that hold nothing from the table it reads. |
SURREAL_ROCKSDB_RUNTIME_RESERVE | 2 | A usize | The number of runtime worker threads kept free for asynchronous work while other transactions wait on a storage call. A larger value keeps more threads free under load, but lowers the number of storage calls that can run at once. See SURREAL_RUNTIME_WORKER_THREADS. |
SURREAL_ROCKSDB_SCAN_VERIFY_CHECKSUMS | true | true, false | Whether scans and counts verify the checksum of each block when it is first read from disk. Disabling it makes cold scans faster, and is only safe on trusted storage. |
SURREAL_ROCKSDB_SHUTDOWN_WAIT_FOR_COMPACT_SECONDS | 30 | A u64 | How long a graceful shutdown waits in seconds for a compaction that started after the final flush, so that the next start does not have to repeat it. Set to 0to wait without a limit. |
SURREAL_ROCKSDB_SST_MAX_ALLOWED_SPACE_USAGE | 0 | A usize | The maximum allowed space usage for SST files in bytes. The default of 0 means unlimited and disables space monitoring. When this limit is reached, the datastore enters read-and-deletion-only mode, where only read and delete operations are allowed. This allows gradual space recovery through data deletion. |
SURREAL_ROCKSDB_STORAGE_LOG_LEVEL | warn | none, full, error, warn, info, debug, trace | The information log level of the RocksDB library. |
SURREAL_ROCKSDB_TARGET_FILE_SIZE_BASE | 67,108,864 (64 MiB) | The target file size for compaction in bytes. | |
SURREAL_ROCKSDB_TARGET_FILE_SIZE_MULTIPLIER | 2 | A usize | The target file size multiplier for each compaction level. |
SURREAL_ROCKSDB_THREAD_COUNT | Number of CPUs on machine | A usize | The number of threads to start for flushing and compaction. |
SURREAL_ROCKSDB_UNIVERSAL_COMPRESSION_SIZE_PERCENT | -1 | An i32 | The percentage of output files to compress. -1compresses all of them. Only used when SURREAL_ROCKSDB_COMPACTION_STYLEis universal. |
SURREAL_ROCKSDB_UNIVERSAL_MAX_MERGE_WIDTH | 4,294,967,295 (no limit) | A u32 | The largest number of files in a single merge. Only used when SURREAL_ROCKSDB_COMPACTION_STYLEis universal. |
SURREAL_ROCKSDB_UNIVERSAL_MAX_SIZE_AMPLIFICATION_PERCENT | 200 | A u32 | The largest acceptable storage amplification, as a percentage of the size of the live data. Only used when SURREAL_ROCKSDB_COMPACTION_STYLEis universal. |
SURREAL_ROCKSDB_UNIVERSAL_MIN_MERGE_WIDTH | 2 | A u32 | The smallest number of files in a single merge. Only used when SURREAL_ROCKSDB_COMPACTION_STYLEis universal. |
SURREAL_ROCKSDB_UNIVERSAL_SIZE_RATIO | 1 | An i32 | How much larger, as a percentage, a file can be than the files before it and still be picked for the same merge. Only used when SURREAL_ROCKSDB_COMPACTION_STYLEis universal. |
SURREAL_ROCKSDB_UNIVERSAL_STOP_STYLE | total | similar_size, total | How RocksDB decides that a merge has collected enough files. Only used when SURREAL_ROCKSDB_COMPACTION_STYLEis universal. |
SURREAL_ROCKSDB_WAL_SIZE_LIMIT | 0 | A usize | The write-ahead-log size limit in MiB. |
SURREAL_ROCKSDB_WHOLE_KEY_FILTERING | true | true, false | Whether SST bloom filters also hold whole keys as well as prefixes. Whole keys make point lookups faster, at the cost of larger filters. Disabling it can suit a workload that mostly scans. Only used when SURREAL_ROCKSDB_PREFIX_EXTRACTOR_ENABLEDis true. |
SURREAL_ROCKSDB_WRITE_BUFFER_SIZE | 32 MiB (systems under 1 GiB), 64 MiB (up to 16 GiB), 128 MiB (others) | A usize | The amount of data each write buffer can build up in memory. |
SURREAL_SYNC_DATA | true | true, false | Whether to sync writes to disk before acknowledgement. 2.x only: replaced in 3.0.0 by SURREAL_DATASTORE_SYNC_DATA. |
FoundationDB environment variables
FoundationDB support was removed in SurrealDB 3.0.0. These variables apply to 2.x only.
Environment variable | Default value | Notes |
|---|---|---|
SURREAL_FOUNDATIONDB_TRANSACTION_MAX_RETRY_DELAY | 500 | The maximum delay between transaction retries in milliseconds. |
SURREAL_FOUNDATIONDB_TRANSACTION_RETRY_LIMIT | 5 | The maximum number of times a transaction can be retried. |
SURREAL_FOUNDATIONDB_TRANSACTION_TIMEOUT | 5000 | The maximum transaction timeout in milliseconds. |
SurrealDB Cloud environment variables
Instances on SurrealDB Cloud are not started with a CLI command or environment variables. Instead, they can be set from SurrealDB Studio or with surreal cloud.