Settings

ArcadeDB allows changing settings at JVM (server or embedded) and per database level.

Server/Embedded (JVM) Level Database Level

Those settings are valid for all the databases open in the same Server or JVM when run embedded. If defined, they override the default value (look at the table below to see the default values). They are used only if a database does not override them. Such settings are not saved, so you need to set them everytime.

Database level settings are stored in the database and override the Server/Embedded (JVM) settings if present. You can change these settings via SQL or API when run embedded.

JVM startup (server/embedded only)

All the settings modified at JVM startup are not persistent and need to be set everytime you’re running ArcadeDB server or your embedded application. If you’re updating a setting at JVM level, prefix the setting name with arcadedb. by using this syntax:

$ java ... -Darcadedb.<name>=<value> ...

Where <name> is the name of the setting and <value> the value you want to override. Example to change the server mode from development (default) to production:

$ java ... -Darcadedb.server.mode=production ...

Example to increase the default page size for buckets to 1 MB:

$ java ... -Darcadedb.bucketDefaultPageSize=1048576 ...

Alternatively, these settings can be set via the environment variable ARCADEDB_SETTINGS, which the launcher scripts (bin/server.sh, bin/console.sh and friends) put on the JVM command line:

ARCADEDB_SETTINGS="-Darcadedb.server.rootPassword=playwithdata" bin/server.sh

JAVA_OPTS is passed through as well, but it is meant for JVM flags: keeping settings in ARCADEDB_SETTINGS means overriding one variable never discards the other.

Boolean values

A setting of type Boolean accepts only true or false (in any casing, surrounding spaces are ignored). Anything else — yes, 1, on, or a misspelling such as ture — is refused: the setting keeps its default and a warning naming the setting and the rejected value is logged at startup. This holds however the value is provided: a JVM system property, an environment variable, ARCADEDB_SETTINGS, the server configuration file, or an admin command. (The server configuration file is checked this way since v26.10.1.)

The point is that a typo can never quietly mean false. For a setting that guards something — for example ha.tls.mutualAuth or ha.peerAllowlist.enabled, both of which default to true — silently reading an unrecognised value as false would have turned the protection off while it looked enabled. If a setting is not taking effect, check the server log for that warning.

Settings with a fixed list of values

Some settings accept only a given set of words — server.mode is development, test or production, for instance. Since v26.10.1 a value outside the list is refused wherever it is written, including the server configuration file, and the setting keeps its previous value with a warning naming what was allowed. Casing does not matter: Production is accepted and understood the same as production.

Setting names

A setting name is case-insensitive, and the arcadedb. prefix is optional in the server configuration file: server.mode, Server.Mode and arcadedb.server.mode all name the same setting. (Since v26.10.1. Before that, a name written in a different case was accepted and then ignored, so the setting silently kept its default — with nothing in the log to say so, and, for settings that log what they do at startup, with every appearance of having been applied.)

A name in the server configuration file that matches no setting — a typo, or a leftover from an older version — is ignored and reported with a warning naming it, so it no longer disappears in silence.

Server-level settings

A setting documented as server level can be written in the server configuration file, with SET SERVER SETTING, or as a -D JVM property, and all three take effect. (Before v26.10.1 a number of them were only ever read from -D or an environment variable: a value written in the configuration file was accepted and then ignored, with nothing in the log to say so. This affected, among others, server.mode and studio.enabled, the HA snapshot and peer-allowlist settings, and the ports and limits of the Bolt, Postgres, Redis and gRPC protocols.)

A setting that accepts only a fixed set of values — server.mode, ha.quorum, ha.serverRole and the others whose description lists their values — refuses anything outside that set, whichever channel writes it: the configuration file, a -D property, SET SERVER SETTING, ALTER DATABASE …​ SETTING, the gRPC settings call or the set_server_setting MCP tool. The setting keeps the value it had and the refusal names the values it accepts.

(Since v26.10.1.) Before this, the administrative channels stored an unaccepted value without complaint. A typo such as SET SERVER SETTING arcadedb.server.mode prodction was answered with 200 and stored as written; every reader compares the value against production, found it different, and kept the development behaviour — so a server you believed was in production mode was not, and nothing said so.

If you have scripts that write one of these settings, check the values they send before upgrading: a value that was silently ignored before now returns an error.

SQL (Database Level)

All the changes executed via SQL Alter Database command are relative to the current database only and are persistent. Here is an example to increase the default page size for buckets to 1 MB:

ALTER DATABASE `arcadedb.bucketDefaultPageSize` 1048576

The current settings can be listed from SQL using:

SELECT expand(settings) FROM schema:database

Programmatically (Server/Embedded and Database levels)

You can access to the database configuration with database.getConfiguration() to read and write per database settings. Example to increase the default page size for all the buckets to 1 MB on the current database:

database.getConfiguration().setValue(GlobalConfiguration.BUCKET_DEFAULT_PAGE_SIZE, 1048576);

To change a setting at Server/Embedded (JVM) level, set the value in the GlobalConfiguration enum. Example to increase the default page size for buckets to 1 MB for all the databases open in the current JVM (server/embedded):

GlobalConfiguration.BUCKET_DEFAULT_PAGE_SIZE.setValue(1048576);

Available settings by scope (in alphabetic order):

The tables that follow contains all the available settings in ArcadeDB separated by scope:

  • JVM, as the settings applied at the JVM level, so to both clients and servers

  • SERVER, as the settings that only apply to the ArcadeDB Server. If you’re embedding a server in your Java application you can use these settings

  • DATABASE are all the settings that can be saved in the database configuration and are restored once the database is open

JVM

Name Description Type Default Value

dumpConfigAtStartup

Dumps the configuration at startup

Boolean

false

dumpMetricsEvery

Dumps the metrics at startup, shutdown and every configurable amount of time (in seconds)

Long

0

opencypher.idBucketBits

Number of bits reserved for the bucketId when packing a RID into the numeric value returned by the Cypher id() function (and SQL’s .asCypherRID() method). Out of the 63 usable bits (the sign bit is kept clear so id(n) is never negative), this many go to the bucketId and the rest to the record position. The default of 16 allows up to 65536 buckets and ~1.4e14 positions per bucket. Increase it for databases with many buckets, decrease it for buckets holding a very high number of records. Must be between 1 and 31. Changing it alters the id() output, so encode and decode must use the same value

Integer

16

profile

Specify the preferred profile among: default, high-performance, low-ram, low-cpu

String

default

queryAdmissionHeapWatermark

Percentage of queryMaxHeapRAM above which the query admission gate (see queryMaxConcurrent) stops starting new queries and lets them wait in its queue until the running ones give heap back. A running query keeps growing after it started, so this is headroom, not a guarantee: the heap budget still refuses the query that would exceed it. When no query admitted by the gate is running, the next one starts whatever the heap, so a budget held by other work (for example queries run through the embedded API) cannot stall the queue for good. Ignored when the gate or the heap budget is disabled. 0 or a negative value admits on the number of running queries alone. The profiler counts as queryAdmissionHeapDeferrals the times the head of the queue had a free slot but found the heap above the watermark (since v26.11.1)

Integer

80

queryMaxConcurrent

Maximum number of requests of remote clients that may run at once in the JVM, across every database (see Concurrent Requests for how the queue works and how to size it). It counts every HTTP request that runs work in a database (query, command, batch load, vector and full-text search, time series, PromQL and Grafana), and the requests received over Postgres, BOLT, Redis, gRPC, Gremlin Server, MCP and MongoDB. A request that arrives when this many are running, or when the heap the running queries hold reserved is above queryAdmissionHeapWatermark, waits in a queue and starts in arrival order (FIFO) as soon as both allow it, instead of running at once and risking a refusal from the heap budget (queryMaxHeapRAM). The wait happens before anything of the request runs, never in the middle of it, and a query started from inside a running one (a function, a script) shares its slot. A request that waits longer than queryQueueTimeout, or that finds queryQueueMaxSize requests already waiting, fails with QueryAdmissionException, which every protocol answers as retryable: HTTP 503, Postgres SQLSTATE 40001, a BOLT transient error, Redis TRYAGAIN, gRPC ABORTED, MongoDB ExceededTimeLimit (262). Nothing of it ran, so it can be retried as it is. Waiting requests park the thread that received them, so keep queryQueueMaxSize below server.httpWorkerThreads to leave HTTP threads for the other requests. The MongoDB protocol runs its requests on threads shared by other connections, so it never waits: a request that cannot start at once is refused. Never held behind the queries: beginning and rolling back a transaction (HTTP sessions, gRPC), the Grafana health probe, Redis PING, the MCP tools that only report on the server, the gRPC admin service. Not gated: the embedded API, which the server’s own work (security, schema, replication, triggers) also uses, Gremlin Server sessions and the gRPC client-streaming loads. A request holds its slot for as long as it runs, so with long analytical queries next to short ones, size the limit for both: a handful of long queries holding every slot makes the short ones wait and, past the timeout, be refused. A transaction that took explicit locks (LOCK TYPE, LOCK BUCKET) keeps them while one of its requests waits in the queue, which lengthens the wait of the writers that need them; a request waiting for an explicit lock gives its slot back first, so the lock holder can always be admitted. A BOLT result stream keeps its slot until it is read to the end or discarded. A follower forwarding a request to the leader gives its slot back while it waits. The gate is reported by the profiler (queryAdmissionRunning, queryAdmissionQueued, queryAdmissionAdmitted, queryAdmissionAdmittedAfterWaiting, queryAdmissionRefused, queryAdmissionHeapDeferrals, queryAdmissionWaitTime) and in Studio’s Executor Pools card as "Query Admission Gate". Left at the default it is twice the number of cores, at least 4; 0 or a negative value disables the gate: every request runs at once (since v26.11.1)

Integer

(2 x cores, min 4)

queryMaxHeapRAM

Maximum heap (in MB) the in-memory buffers of all the queries running in the JVM may hold at once, across every database: the rows an ORDER BY sorts, the keys a DISTINCT or a UNION remembers, the groups a GROUP BY keeps, and in OpenCypher also the values collect() gathers, the rows a Cartesian product or a hash join buffers and the eager read ahead of a write. Every buffer reserves its estimated size from this budget as it grows and gives it back once its rows are served, when its query closes, or - for a result set the application abandoned without closing it - once the garbage collector reclaims it. Where queryMaxHeapElementsAllowedPerOp stops one runaway query, this budget stops many large queries running together from exhausting the heap although each one stays under that limit. A query whose buffers would take the reservations past the budget fails with QueryHeapBudgetExceededException, which is transient: the same query can succeed once the others release what they hold, and HTTP answers it with 503 (the other protocols classify it as retryable). A query that alone needs more than the whole budget fails with a plain CommandExecutionException instead, since no retry can help it. The first 256KB a query buffers are not reserved, so small queries never contend on the budget. A GROUP BY computed by a parallel scan reserves about one copy of its groups plus a small partial per worker, whatever the number of cores: a worker merges its groups into one shared set once it holds its share of the budget, and a GROUP BY of many keys aggregates the keys a worker does not hold in one shared set partitioned by key (see queryParallelScan) (since v26.11.1). The reservations in use, their peak and the refusals are reported by the profiler as queryHeapReserved, queryHeapReservedPeak, queryHeapBudget and queryHeapRefusals. A scan of a type with large records reads ahead less as the budget fills (see queryBatchMaxBytes), which slows it: the profiler counts those batches as queryHeapScanShrinks, and PROFILE marks the scan step with [read-ahead reduced in N batches by memory pressure], so a slow scan can be traced to a low budget (since v26.11.1). The budget counts estimated sizes, not the heap itself: the estimate counts a record a buffer holds at its full size, so it errs on the high side when the page cache already holds the same pages, but leave some headroom rather than sizing it to the last megabyte of free heap. Left at the default it is half of the JVM maximum heap; 0 or a negative value disables the budget (since v26.10.1)

Long

(heap/2)

queryQueueMaxSize

Maximum number of queries that may wait in the queue of the query admission gate (see queryMaxConcurrent) at once. A query that finds the queue full fails at once with QueryAdmissionException (HTTP 503) without having run. Each waiting query parks the HTTP worker thread that received it, so this bounds how many of those threads the queue can take away from the other requests. The low-ram profile sets it to 8. 0 or a negative value disables the queue: a query that cannot start at once is refused (since v26.11.1)

Integer

256

queryQueueTimeout

Maximum time in milliseconds a query waits in the queue of the query admission gate (see queryMaxConcurrent) before it fails with QueryAdmissionException (HTTP 503) without having run. 0 or a negative value does not wait: a query that cannot start at once is refused (since v26.11.1)

Long

30000

sparseVectorScoringWindow

Size, in RID positions, of the window the LSM_SPARSE_VECTOR top-K traversal scores at a time. Measured about 1.8x faster at the median and 2.4x at p99 than the document-at-a-time traversal on learned-sparse corpora. Scores can differ in the last bit, so the order among exact ties may change. 0 or a negative value selects the classic document-at-a-time Block-Max MaxScore traversal. Rounded up to a multiple of 64 and capped at 1048576. Re-read on every query. Since v26.10.1.

Integer

16384

test

Tells if it is running in test mode. This enables the calling of callbacks for testing purpose

Boolean

false

Available Plugins

The following plugins are available for ArcadeDB Server:

  • MongoDB (com.arcadedb.mongo.MongoDBProtocolPlugin) - Implements the MongoDB wire protocol

  • Postgres (com.arcadedb.postgres.PostgresProtocolPlugin) - Implements the Postgres wire protocol

  • Redis (com.arcadedb.redis.RedisProtocolPlugin) - Implements the Redis wire protocol

  • Http (com.arcadedb.server.http.HttpServerPlugin) - Implements the HTTP/REST API

  • gRPC (com.arcadedb.server.grpc.GrpcServerPlugin) - Implements the gRPC API. Bundled in the full distribution but not started until it is added to server.plugins (see gRPC settings)

SERVER

Name Description Type Default Value

backup.enabled

State of backup lock. Disable for increased performance of massive insertions.

Boolean

True

ha.addPeerProbeTimeout

Milliseconds to wait for a TCP connection to a peer’s Raft address before an add-peer request (POST /api/v1/cluster/peer, connect cluster, gRPC ConnectCluster) is refused as unreachable with HTTP 400 / gRPC INVALID_ARGUMENT. A successful probe is not proof of a healthy peer and changes nothing. 0 skips the probe. Since v26.10.1.

Long

2000

ha.appendBufferSize

AppendEntries batch byte limit for replication (e.g. '32MB').

String

32MB

ha.appendElementLimit

Maximum number of Raft log entries per AppendEntries batch. Bounds the per-batch in-memory footprint on the follower during catch-up resync, where many batches may queue before the state machine can apply them. Lowering this value reduces peak heap pressure on followers catching up from a far-behind state. The byte limit (ha.appendBufferSize) remains the dominant per-batch heap bound; this element count is the secondary cap that governs when entries are small enough that many fit under the byte limit. Must be a positive integer (>= 1).

Integer

64

ha.clientElectionRetryCount

Number of retries performed by RemoteDatabase after receiving HTTP 503 NeedRetryException during an election.

Integer

3

ha.clientElectionRetryDelayMs

Delay in ms between RemoteDatabase election retries. A longer Retry-After sent by the server takes precedence, up to network.retryAfterMaxWait (since v26.10.1).

Long

2000

ha.bootstrapFromLocalDatabase

When true (default), at first cluster formation peers exchange (fingerprint, lastTxId) per database; the highest-lastTxId peer is elected as bootstrap source via leadership transfer. Matching peers bootstrap locally with zero bytes transferred; mismatched peers reinstall the leader-shipped full snapshot.

Boolean

true

ha.bootstrapTimeoutMs

Maximum time in ms the bootstrap leader waits for every configured peer to report its bootstrap state before proceeding.

Long

120000

ha.clusterName

Cluster name. Useful in case of multiple clusters in the same network

String

arcadedb

ha.clusterToken

Shared secret for inter-node authentication. If empty, auto-generated at first startup and persisted under raft-storage/.

String

ha.clusterTokenPath

Path to a file containing the shared secret for inter-node authentication. Read only when ha.clusterToken is not set; the file content is trimmed of surrounding whitespace. Keeps the secret off the command line (e.g. a Kubernetes Secret mounted on tmpfs).

String

null

ha.divergedFollowerRecoveryDurationMs

How long in ms a follower must stay stuck at a stale term, without its applied index advancing, before it reformats its Raft storage and rejoins. Any advance of the applied index restarts the window. Floored at 2x ha.electionTimeoutMax. Since v26.10.1: this window used to be ha.staleFollowerRecoveryDurationMs (default 60000); a deployment that raised the old setting to delay the reformat must raise this one instead.

Long

20000

ha.electionTimeoutMin

Minimum Raft election timeout in ms. Increase for high-latency WAN clusters.

Integer

5000

ha.electionTimeoutMax

Maximum Raft election timeout in ms. Increase for high-latency WAN clusters. Must be above ha.electionTimeoutMin: a value at or below it is widened to twice the minimum (with a warning), because without a spread between the two the nodes of a cluster that lost its leader keep splitting the vote. To shorten the timeout, lower both. Since v26.10.1

Integer

10000

ha.enabled

True if HA is enabled for the current server

Boolean

false

ha.errorRetries

Number of automatic retries in case of IO errors with a specific server. 0 (default) is to retry against all the configured servers

Integer

0

ha.grpcAllowlistRefreshMs

Rate-limiting interval in ms for DNS re-resolution in the gRPC peer address allowlist filter.

Long

30000

ha.grpcFlowControlWindow

gRPC flow control window size in bytes for Raft AppendEntries traffic. Larger values help catch-up replication after partitions.

Long

4194304

ha.groupCommitBatchSize

Maximum number of Raft log entries to batch in a single group commit flush. Higher values improve throughput under concurrent load.

Integer

500

ha.groupCommitOfferTimeout

Timeout in ms waiting for space in the group-commit queue before throwing ReplicationQueueFullException.

Integer

100

ha.groupCommitQueueSize

Maximum pending transactions allowed in the Raft group-commit queue. When full, the server sheds load by throwing ReplicationQueueFullException (NeedRetryException).

Integer

10000

ha.grpcMaxConnectionAgeGraceMs

How long in ms the RPCs still running on a Raft gRPC connection that reached ha.grpcMaxConnectionAgeMs have to finish before the connection is closed. Read only when that setting is non-zero. 0 cancels them at the age boundary. Since v26.10.1.

Long

5000

ha.grpcMaxConnectionAgeMs

How long in ms an inbound Raft gRPC connection may live before the server closes it with a graceful GOAWAY, whether busy or idle. Bounds a connection that is never idle, such as a removed peer that keeps campaigning, at the price of recycling healthy replication streams once per period. gRPC applies a +/-10% jitter and a 1 second floor. Set it well above the Raft election timeout. 0 leaves connections unbounded in age. Since v26.10.1.

Long

0

ha.grpcMaxConnectionIdleMs

How long in ms an inbound Raft gRPC connection may carry no RPC before the server closes it with a graceful GOAWAY. Closes quiet connections, such as the socket of a peer removed from the allowlist; it never reaps an active replication stream. Values below 1 second are raised to 1 second. 0 leaves connections unbounded (the behavior before v26.10.1). Since v26.10.1.

Long

300000

ha.healthCheckInterval

Interval in ms for the Raft health monitor to check for CLOSED/EXCEPTION state and auto-recover. Since v26.9.1 the same tick also restarts in place a node whose Raft log writer failed (for example No space left on device) once the Raft storage volume has room again. 0 disables.

Long

3000

ha.idempotencyCacheMaxBodyBytes

Maximum size in bytes of a single response body eligible for caching in the HTTP idempotency cache. Larger responses are not cached, so a retry of that request executes again. See reference/http-api/http.adoc#http-request-replay

Long

1048576

ha.idempotencyCacheMaxBytes

Maximum total size in bytes of the cached response bodies in the HTTP idempotency cache. Oldest entries are evicted when exceeded.

Long

67108864

ha.idempotencyCacheMaxEntries

Maximum number of entries in the HTTP idempotency cache.

Integer

10000

ha.idempotencyCacheTtlMs

Time-to-live in ms for entries in the HTTP idempotency cache: how long a retry with the same X-Request-Id is replayed rather than executed again. See reference/http-api/http.adoc#http-request-replay

Long

60000

ha.jvmPauseCloseThresholdMs

JVM-pause length in ms above which Ratis closes this node’s Raft division (Ratis default: 60000). 0 or a negative value disables the close: a long pause still steps a leader down, and the ArcadeDB health monitor decides whether the node needs recovery. Set a positive value to restore the Ratis behavior. Since v26.10.1.

Long

0

ha.k8s

The server is running inside Kubernetes (enables auto-join on scale-up)

Boolean

false

ha.k8sSuffix

When running inside Kubernetes use this suffix to reach the other servers. Example: arcadedb.default.svc.cluster.local

String

ha.logPurgeGap

Number of Raft log entries retained after a snapshot as a buffer for slightly lagging followers. Lower values free disk faster but raise the chance a slow follower needs a full snapshot resync.

Integer

1024

ha.logPurgeUptoSnapshot

When true, deletes old Raft log segments after each snapshot to bound disk growth. Set to false to retain full log history for debugging/auditing.

Boolean

true

ha.logSegmentSize

Maximum Raft log segment size (e.g. '64MB', '128MB').

String

64MB

ha.logVerbose

Verbose HA logging: 0=off, 1=basic (elections), 2=detailed (replication), 3=trace (every state machine apply).

Integer

0

ha.membershipChangeTimeout

Time in ms an add-peer or remove-peer keeps re-issuing the Raft configuration change before reporting it as not committed. Bounds the whole request, not one attempt: an attempt that cannot finish in what is left of the budget is not started. A peer that answers a connection but never catches up (a legitimately large snapshot install, or a listener that is not a peer of this cluster) is what reaches the full budget; a peer that belongs to a different cluster is refused at once instead. Lower it below a load balancer’s idle timeout so you get the error rather than a dropped connection, remembering that an attempt whose network call hangs can take up to about 31s on its own. Read at server start.

Long

90000

ha.peerAllowlist.enabled

Reject inbound Raft gRPC connections whose remote address does not resolve to a cluster peer. The accepted hosts are those in ha.serverList (expanded with ha.k8sSuffix when ha.k8s is set), plus the current members of the cluster, which are picked up automatically so a node that joins at runtime is accepted; on Kubernetes the pods of the headless service named by ha.k8sSuffix are accepted too, so a StatefulSet scale-up completes without changing any setting. Loopback is always allowed. Not a substitute for mTLS on untrusted networks.

Boolean

true

ha.peerAllowlistStartupGraceMs

Startup grace window in ms during which the gRPC peer allowlist fails OPEN (accepts and logs a warning) for an unmatched address, as long as it has never resolved every host in ha.serverList at least once. Prevents a self-inflicted partition on Kubernetes, where a peer’s headless-service DNS record is only published once its pod is Ready, so a restarting peer connects before its own name resolves. Measured from filter creation; enforces normally once all peers resolve once or the window elapses. 0 disables fail-open.

Long

60000

ha.peerAllowlistStickyTtlMs

How long in ms the gRPC peer allowlist keeps the last successfully-resolved IPs of a peer host when a later DNS re-resolution of that host fails. Bridges transient DNS outages and pod-IP churn so a peer that resolved moments ago is not evicted by a momentary lookup failure. 0 disables stickiness.

Long

300000

ha.peerChannelResetDuration

Time in ms a follower must stay continuously unreachable before the leader resets that one follower’s replication gRPC channel, so the next send re-resolves DNS and reconnects. Recovers a leader appender stuck on a stale DNS result after a follower restarts with a new address (e.g. a Kubernetes pod-IP change). Retried once per interval, up to 5 attempts, then the leader gives up or escalates (see ha.peerChannelResetEscalation); the counter re-arms when the follower reconnects. Only the unreachable peer’s channel is touched. Requires ha.peerUnreachableThreshold > 0. Set to 0 to disable. See Replication-Channel Self-Healing.

Long

60000

ha.peerChannelResetEscalation

When the ha.peerChannelResetDuration retry budget is exhausted and the follower’s replication channel is still dead, transfer leadership to a healthy peer so the new leader builds a fresh appender to that follower. Without it the leader stays wedged until an operator restarts the process, because the reset streak only re-arms when the follower becomes reachable again. The target is chosen with the same rules as a manual step-down and is never the wedged follower; when no healthy target exists the leader logs for operator intervention instead. Each healthy peer escalates a given follower at most once per 30-minute cooldown, so leadership churn is bounded rather than perpetual. Set to false to only log. See Replication-Channel Self-Healing.

Boolean

true

ha.peerUnreachableThreshold

Time in ms since the last successful RPC to a follower before the leader reports it as unreachable in the resync narrative. Also the "unreachable" signal ha.peerChannelResetDuration depends on. Does not change Raft membership or quorum. Set to 0 to disable, which also disables the channel-reset recovery built on it.

Long

10000

ha.proxyBatchReadTimeout

Timeout in ms a follower waits for the leader to answer a batch load it relayed via POST /api/v1/batch, before answering the client HTTP 504. Separate from ha.proxyReadTimeout because a bulk load’s duration depends on the payload size, not a fixed control-plane budget.

Long

600000

ha.proxyCommandTimeout

Fallback timeout in ms a follower waits for the leader to answer a forwarded SQL/DDL write, used only when the database has no arcadedb.command.timeout of its own. (Since v26.10.1 the budget is read from the database’s configuration, not from the configuration passed to the call.)

Long

3600000

ha.proxyConnectTimeout

Connect timeout in ms for the leader proxy (replica-to-leader forwarding). Since 26.10.1 it also applies when the cluster uses SSL, where the connection previously had a fixed 5s timeout the setting could not change. Read when the connection is created, so a change needs a restart.

Long

5000

ha.proxyLongCommandTimeout

Milliseconds a follower waits for the leader to answer a forwarded restore backup, restore database or import database before answering the client HTTP 504. These commands legitimately run for minutes, so ha.proxyReadTimeout does not apply to them. 0 or a negative value does not disable it. Since v26.10.1.

Long

3600000

ha.proxyReadTimeout

Read timeout in ms for the leader proxy. Covers long-running queries forwarded from a replica.

Long

30000

ha.quorum

Write quorum: majority or all. The legacy values none, one, two, three are not supported

String

majority

ha.quorumTimeout

Timeout in ms waiting for the quorum acknowledgment

Long

10000

ha.raftPort

TCP/IP port for Raft gRPC communication. Used as the default when HA_SERVER_LIST entries do not specify an explicit port.

Integer

2434

ha.raftPersistStorage

If true, the Raft storage directory is preserved across restarts, enabling node rejoin by replaying its persisted log instead of a full snapshot resync. Defaults to true: wiping the Raft log on restart could permanently diverge a lagging follower after a full-cluster cold restart (WALVersionGapException) or silently re-form a fresh single-node cluster. Ensure ha.raftStorageDirectory lives on durable storage. A throwaway/test cluster can opt out with false.

Boolean

true

ha.raftStorageDirectory

Parent directory under which the per-node Raft storage sub-folders (raft-storage-<nodeName>) are created. When empty (the default), the server root path (arcadedb.server.rootPath) is used. Because ha.raftPersistStorage now defaults to true, this directory must live on durable storage (a persistent volume, not an ephemeral/tmpfs mount) so a restarted node can replay its log and rejoin without a full snapshot resync. Set this to a writable, statically-named path (e.g. a PVC mount) on Kubernetes StatefulSets with readOnlyRootFilesystem: true, where the dynamically-named raft-storage-* directory under the read-only server root cannot be created or mounted.

String

ha.ratisRestartMaxRetries

Maximum consecutive Ratis restart attempts by the health monitor before the server shuts down for cluster-level recovery. Also bounds, per incident, the in-place restarts that recover a failed Raft log writer (since v26.9.1).

Integer

10

ha.readConsistency

Default read consistency for replica reads: eventual, read_your_writes, linearizable.

String

read_your_writes

ha.replicationChunkMaxSize

Maximum channel chunk size for replicating messages between servers

Integer

16777216

ha.replicationLagWarning

Raft log index gap threshold for replication lag warnings. 0 to disable.

Long

1000

ha.schemaDelta

Ships a schema change to the followers as a delta against the schema they already hold, instead of the whole schema document on every DDL. On a large schema that is kilobytes instead of megabytes per Raft entry. The leader sends the whole document anyway after it becomes leader, for a compaction entry, an entry shipped in instalments, a change too large for a delta to pay off, and whenever any peer has not confirmed it can decode a delta, so a rolling upgrade needs no ordering. A rolling downgrade to a version older than v26.10.1 does: see Schema delta replication. While on, the leader keeps one parsed copy of the schema per replicated database in heap. Turning it off is safe at any time. (Since v26.10.1)

Boolean

true

ha.schemaIncrementalApply

A follower applying a DDL entry creates only the components for the files that entry added, instead of rebuilding every component in the database. The full rebuild costs time proportional to all the files per entry, which made building a large schema quadratic (a 1209-type schema took about 2h53m to replicate). Entries the incremental path cannot express (a file retired, a compacted index, a bloom filter, a new dictionary) fall back to the full rebuild on their own. Read per entry, so a change takes effect without a restart. Set to false only to rule out a suspected incremental-apply bug. (Since v26.10.1)

Boolean

true

ha.txSchemaCheck

Have every transaction a node replicates carry the Raft log index that node had applied when the transaction began, so the leader can refuse a transaction prepared before a schema change it has already applied. Without it a replica that has not yet applied a committed CREATE INDEX can ship a transaction whose record ends up missing from the new index on every node, with no error. The refusal is a retryable ConcurrentModificationException, so expect retries on replicas during DDL; callers that do not retry (the default for plain HTTP commands) see the error. The index is written only once every peer advertises the capability, so a mixed-version cluster is unprotected until the last node is upgraded. This setting controls only whether THIS node states an index. Since v26.10.1.

Boolean

true

ha.securityConvergenceReadinessTimeout

How long in ms /api/v1/ready (and the gRPC Ready RPC) keeps answering NOT READY on a node that may be enforcing stale users, groups or API tokens: one added to the cluster while running (POST /api/v1/cluster/peer, connect cluster, Kubernetes auto-join) that has not yet installed the cluster’s security documents, or one caught up by a snapshot install whose copies the leader has not yet confirmed. Requires server.readinessRequiresHA. When the window expires the node reports READY and logs once at SEVERE which documents never converged. 0 disables the wait. See Health probes. (Since v26.10.1)

Long

30000

ha.securityEntryCapabilityGate

Refuse a group or API-token change (HTTP 409 / gRPC FAILED_PRECONDITION, naming the peer) while any peer of the Raft configuration has not proved, via POST /api/v1/cluster/capabilities, that it can decode the log entry the change is replicated as. Protects a rolling upgrade: an older node would halt on the unknown entry. An unreachable peer counts as a no, so admin security changes are refused while any node is down. Turn it off only when you know every node runs v26.10.1 or later. Since v26.10.1.

Boolean

true

ha.securitySeedRetryTimeout

Time budget in ms a peer-admission call (POST /api/v1/cluster/peer, connect cluster) spends retrying, with exponential backoff, the security documents (server-users.jsonl, server-groups.json, server-api-tokens.json) it seeds to the newly joined peer. A snapshot install does not carry them. 0 leaves a single best-effort attempt. Since v26.10.1.

Long

3000

ha.serverList

Servers in the cluster, comma-separated. Each entry uses the readable object form [name@]host:{raft:2434,http:2480,https:2490,priority:10} (recommended) or the positional form [name@]host:raftPort:httpPort[:priority[:httpsPort]]. The httpPort is required for replica-to-leader HTTP forwarding. The optional name@ prefix gives the peer a human-readable name used in logs and Studio. The optional priority (default 0) prefers higher-valued nodes during elections. The optional httpsPort encrypts peer-to-peer transfers (e.g. snapshot download) when ssl.enabled is true; on a homogeneous cluster it is derived from this node’s local HTTPS port when omitted. Example: frankfurt@db1:{raft:2434,http:2480,https:2490,priority:10},london@db2:{raft:2434,http:2480,https:2490}

String

ha.serverRole

Node role in the cluster: any (default, eligible for leader election) or replica (never elected leader; Raft priority set to 0). Useful for witness/read-scale nodes.

String

any

ha.snapshotCompressionLevel

DEFLATE level the leader applies to the ZIP stream of a database snapshot shipped to a follower: 0 (stored) to 9 (smallest, slowest), or -1 for the Deflater default (level 6). A value outside -1..9 is ignored and the default is used. Only the serving side reads it. Since v26.11.1: default changed from -1 to 1

Integer

1

ha.snapshotDownloadTimeout

Read timeout in ms for downloading a database snapshot from the leader during follower resync.

Integer

300000

ha.snapshotGapTolerance

Maximum acceptable gap between the snapshot index and persisted applied index before triggering a snapshot download.

Long

10

ha.snapshotInstallBackupWaitMs

Milliseconds a snapshot install, or the apply of a replicated drop database, waits for a backup, export or import of the same database already running on this node before it replaces or drops the database files anyway (logging a warning). 0 does not wait. Since v26.10.1.

Long

60000

ha.snapshotInstallRetries

Maximum retry attempts for snapshot download from the leader during snapshot installation.

Integer

3

ha.snapshotInstallRetryBaseMs

Base delay in ms for exponential backoff between snapshot download retries. Actual delay is baseMs * 2^attempt.

Long

5000

ha.snapshotMaxConcurrent

Maximum number of concurrent snapshot downloads served by the leader. Requests over this limit receive HTTP 503.

Integer

2

ha.snapshotMaxEntrySize

Maximum uncompressed size in bytes for a single entry in a snapshot ZIP. Decompression-bomb guard. Set 0 or a negative value to keep the built-in default: the guard cannot be switched off. Configurable since v26.10.1

Long

10737418240

ha.snapshotThreshold

Number of Raft log entries after which the leader automatically takes a snapshot.

Long

100000

ha.snapshotWatchdogTimeout

Delay in ms before the snapshot-gap watchdog triggers a download. Floored at 4x ha.electionTimeoutMax.

Long

30000

ha.snapshotWriteTimeout

Timeout in ms for writing a snapshot to a follower. If the transfer stalls beyond this duration, the connection is force-closed.

Long

300000

ha.stalledReplicaResyncDurationMs

How long in ms a replica must stay continuously STALLED — its matchIndex not advancing while the leader keeps committing — before the leader forces it to resync. This is the leader-driven counterpart to a follower detecting its own lag: it covers the case where the follower cannot self-detect the stall because its own commit index never advances. A follower still at the never-appended sentinel (matchIndex=-1 while the leader holds committed entries) is treated as STALLED regardless of the numeric lag, so it is recovered even when the leader is only a few entries ahead and the lag stays below ha.replicationLagWarning. The same duration doubles as the grace period before a replica’s status flips from HEALTHY to STALLED, so a brief join or snapshot-install window is not misreported. Set to 0 to disable leader-driven recovery; the STALLED condition is still detected and logged.

Long

60000

ha.stopServerOnReplicationFailure

After a phase-2 replication failure, step-down is attempted first. If every step-down fails and this flag is true, the JVM exits so an orchestrator can restart. Default is false: the server keeps running and logs CRITICAL.

Boolean

false

ha.tls.enabled

Negotiate TLS on the Raft gRPC transport, which carries AppendEntries, RequestVote and the Ratis admin/client calls between the nodes of a cluster. When true, ha.tls.certChainFile, ha.tls.privateKeyFile and ha.tls.trustCertCollectionFile must all name a readable PEM file or the node refuses to start with a ConfigurationException naming the offending setting. Default is false so a development or test cluster still starts with no configuration at all; the peer-address allowlist (ha.peerAllowlist.enabled) is IP-based and is defeated by a spoofed source address or a compromised peer, so it is a best-effort default rather than a substitute for TLS on an untrusted network. TLS on the gRPC port does not replace the X-ArcadeDB-Cluster-Token check on the HTTP side channels (snapshot download, database verify), nor is it affected by ssl.enabled, which covers those side channels only. See mTLS for the Raft gRPC transport. Since v26.9.1

Boolean

false

ha.tls.certChainFile

PEM file holding this node’s Raft gRPC certificate followed by any intermediate CA certificates. The certificate must carry a subject alternative name matching the address the other nodes use to dial this node in ha.serverList (on Kubernetes, the pod’s stable headless-service DNS name, not the pod IP). Every node both accepts and initiates Raft connections, so with ha.tls.mutualAuth=true this one certificate is presented as the TLS server certificate AND as the client certificate: it needs BOTH the serverAuth and clientAuth extended key usages. A CA that issues single-purpose certificates otherwise produces a handshake failure the startup file checks cannot catch, because the file is perfectly readable and merely the wrong kind of certificate. Required when ha.tls.enabled is true. Since v26.9.1

String

ha.tls.privateKeyFile

PEM file holding the PKCS#8 private key that matches ha.tls.certChainFile — the PEM armor labels it simply PRIVATE KEY, whereas a PKCS#1 key is labeled RSA PRIVATE KEY and is not accepted. A WARNING is logged when the file is readable by the group or by others, since any local account that can read it can present this node’s identity to the cluster; it is a warning and not a refusal, because a mounted secret may arrive with permissions the node cannot change. Required when ha.tls.enabled is true. Since v26.9.1

String

ha.tls.trustCertCollectionFile

PEM file holding the cluster CA certificate(s) that sign every node certificate. A peer presenting a certificate this collection does not chain to is rejected during the TLS handshake, before any Raft message is read. Required when ha.tls.enabled is true — including with ha.tls.mutualAuth=false, since the dialing node still needs the cluster CA to validate the certificate presented by the node it dials. Since v26.9.1

String

ha.tls.mutualAuth

Require the dialing peer to present a client certificate signed by the CA collection in ha.tls.trustCertCollectionFile, binding peer identity to the certificate rather than to a source IP address. Set to false for server-only TLS, which encrypts the traffic but leaves the Raft port open to any client that trusts the cluster CA — the back door this setting exists to close, so the server logs a WARNING at startup when it is off. Turning it off does NOT make ha.tls.trustCertCollectionFile optional. Only meaningful when ha.tls.enabled is true. Since v26.9.1

Boolean

true

ha.writeBufferSize

Raft log write buffer size (e.g. '40MB'). Must be at least ha.appendBufferSize + 8 bytes; otherwise the server fails to start with ConfigurationException.

String

40MB

network.sameServerErrorRetry

Number of automatic retries in case of IO errors with a specific server. If replica servers are configured, look also at HA_ERROR_RETRY setting. 0 (default) = no retry

Integer

0

network.retryAfterMaxWait

Upper bound, in milliseconds, on how long the remote client honors the Retry-After a server sends with a request it refused before running it (a 503 from a node installing a snapshot): the transaction retry loop of RemoteDatabase.transaction() and the election retry loop wait at least that long before retrying, and the hint is capped at this value, so a misbehaving server cannot park the client. A random spread of up to a tenth of the hint is added on top, so the clients a node refused together do not all come back at once. The most a refused request can wait is therefore 1.1 times this value per retry: txRetries - 1 pauses for a transaction, ha.clientElectionRetryCount for a command. 0 ignores Retry-After, leaving only the retry backoff (since v26.10.1)

Long

30000

network.socketTimeout

TCP/IP Socket timeout (in ms)

Integer

30000

network.remoteFetchConnectTimeout

Connect timeout, in milliseconds, for an outbound fetch of a URL you supply - IMPORT DATABASE, RESTORE DATABASE and the openCypher LOAD CSV - applied to every hop of a redirect chain. 0 means no timeout at all, so a host that neither accepts nor refuses the connection blocks the calling thread indefinitely. Since v26.10.1

Integer

30000

network.remoteFetchReadTimeout

Read timeout, in milliseconds, for an outbound fetch of a URL you supply - IMPORT DATABASE, RESTORE DATABASE and the openCypher LOAD CSV. It bounds EACH read, not the whole transfer: a large remote source may legitimately take much longer than this to arrive, as long as it keeps sending. 0 means no timeout at all, so a source that stops sending and never closes the socket - a hung HTTP connection, or a proxy holding the socket open after the origin died - blocks the calling thread for as long as that socket lives. Raise it for a genuinely slow origin rather than disabling it; when it fires, the error names the URL, the wait and this setting. Since v26.10.1

Integer

30000

network.maxPreAuthConnections

Maximum number of connections a binary wire-protocol listener (Postgres, Redis, BOLT) may hold in the phase before authentication. Each accepted socket costs one thread and one file descriptor before the client has proved who it is, and network.socketTimeout only bounds how long each one may stay there, not how many there can be. Past this cap the listener closes further connections immediately rather than accepting and then timing them out. The cap is per listener, so a flood against one protocol cannot use up the budget that lets clients of another log in. 0 means unlimited. Since v26.9.1

Integer

500

network.socketKeepAlive

Enable TCP keepalive (SO_KEEPALIVE) on every wire-protocol socket. The Postgres and Redis executors drop the socket read timeout to infinite once a connection is authenticated, because an authenticated client legitimately holds an idle connection open, and those protocols carry no application-level heartbeat. With keepalive off, a peer that dies without a FIN/RST (host crash, silent partition) leaves the server thread blocked in a read forever, leaking a thread and a file descriptor per event. Keepalive lets the OS discover the dead peer and fail the read. Since v26.9.1

Boolean

true

network.socketKeepAliveIdle

Seconds an authenticated connection may sit idle before the OS sends the first TCP keepalive probe. Only applied where the JDK and the platform expose TCP_KEEPIDLE (Linux and macOS do); elsewhere the system-wide default applies, typically 2 hours. 0 leaves the system default in place. Since v26.9.1

Integer

120

network.socketKeepAliveInterval

Seconds between TCP keepalive probes once the first one has gone unanswered. 0 leaves the system default in place. Since v26.9.1

Integer

15

network.socketKeepAliveCount

Number of unanswered TCP keepalive probes after which the connection is declared dead. With the defaults a dead peer is detected about 3 minutes after the connection goes idle. 0 leaves the system default in place. Since v26.9.1

Integer

4

ssl.keyStore

Path where the SSL certificates are stored

String

null

ssl.keyStorePassword

Password to open the SSL key store

String

null

ssl.trustStore

Path to the SSL trust store

String

null

ssl.trustStorePassword

Password to open the SSL trust store

String

null

ssl.enabled

Use SSL for client connections

Boolean

false

postgres.debug

Enables the printing of Postgres protocol to the console. Default is false

Boolean

false

postgres.host

TCP/IP host name used for incoming connections for Postgres plugin. Default is '0.0.0.0'

String

0.0.0.0

postgres.port

TCP/IP port number used for incoming connections for Postgres plugin. Default is 5432

Integer

5432

postgres.ssl

TLS mode for Postgres wire protocol connections, using the shared SSL key/trust store settings (ssl.*): DISABLED (no TLS, default), OPTIONAL (TLS or plain text, the client chooses), REQUIRED (TLS only, plain text startup is refused). Since v26.10.1

String

DISABLED

postgres.queryMaxRows

Maximum number of rows the result of one statement may occupy server-side before the first row is sent to a Postgres client, on both the simple-query and the extended-query (Parse/Bind/Describe/Execute) protocol. The server has to see the whole result before it can announce the column set, and the portal fetch size only bounds what each Execute sends, not what the server holds. A statement exceeding the limit is refused with an error; narrow it with a WHERE or LIMIT clause or raise the limit. 0 means unlimited. Since v26.9.1

Integer

1000000

redis.defaultDatabase

Default database name for Redis protocol connections. If set, RAM commands (SET, GET, etc.) will use this database’s globalVariables. Empty means no default (requires SELECT command or key prefix)

String

redis.host

TCP/IP host name used for incoming connections for Redis plugin. Default is '0.0.0.0'

String

0.0.0.0

redis.port

TCP/IP port number used for incoming connections for Redis plugin. Default is 6379

Integer

6379

mongo.host

TCP/IP host name used for incoming connections for Mongo plugin. Default is '0.0.0.0'

String

0.0.0.0

mongo.port

TCP/IP port number used for incoming connections for Mongo plugin. Default is 27017

Integer

27017

server.databaseLoadAtStartup

Open all the available databases at server startup

Boolean

true

server.databaseDirectory

Directory containing the database

String

${arcadedb.server.rootPath}/databases

server.backupDirectory

Directory containing the backups

String

${arcadedb.server.rootPath}/backups

server.configDirectory

Directory the server reads and writes its configuration files in: server-configuration.json, the security files (server-users.jsonl, server-groups.json, server-api-tokens.json), backup.json, ai.json, mcp-config.json and gremlin-server.yaml. Set it as a -D system property or in ARCADEDB_SETTINGS, never in server-configuration.json, which lives inside it. Read once at startup; the directory is created if missing. arcadedb-log.properties is not read from here: logging is still configured with -Djava.util.logging.config.file. See Relocating the configuration directory. (Since v26.10.1)

String

${arcadedb.server.rootPath}/config

instance.id

Optional instance id (adb- followed by a lowercase UUID) to use instead of the one ArcadeDB generates and saves in the file .instance.id of the databases directory (older versions: instance.id of the configuration directory). Set it when no directory is writable or persistent. It identifies the instance to ArcadeData support and is never a credential. Empty means generated. See The instance id.

String

instance.derived

Computes the instance id from ha.clusterName and server.name instead of saving it, so a server with no persistent directory (a container without a volume, a Kubernetes StatefulSet pod) keeps the same id on every restart. The names must be unique per node and stable. Ignored when instance.id is set. See The instance id.

Boolean

false

support.url

Base URL of the ArcadeData customer portal used by the Support tab of Studio and by connect portal. HTTPS only (plain HTTP is accepted for localhost). Overrides the value registered in support.json. See Support.

String

https://portal.arcadedb.com

support.clientId

Client ID (workspace id) of the customer portal. Together with support.clientKey it registers the server without Studio (containers, Kubernetes secrets) and overrides support.json. Empty means not set.

String

support.clientKey

Client key (wsk_…​) of the customer portal. A credential: masked when settings are listed or dumped, never returned by any API and never logged. Empty means not set.

String

support.autoRegister

Registers the server as an installation of its workspace in the customer portal without anybody opening Studio: once shortly after the start of a server that holds a support key (support.clientKey or support.json), and then once a day. It sends the same redacted diagnostics Studio sends (never logs, never database contents) and only fills fields the portal has blank. Set it to false to register only from Studio or the console. See Support.

Boolean

true

server.logsDirectory

Directory where the server writes its log files. Useful on read-only root filesystems (e.g. Kubernetes readOnlyRootFilesystem pods) to relocate logs to a writable mount. The value is resolved very early at startup from, in order, the system property arcadedb.server.logsDirectory, the environment variable, then this setting, and supports ${…​} placeholders. The server.sh/server.bat scripts forward the ARCADEDB_LOG_DIR environment variable to this setting.

String

./log

server.defaultDatabases

The default databases created when the server starts. The format is (<database-name>[(<user-name>:<user-passwd>[:<user-group>])])[{import|restore:<URL>}][;]'. Pay attention on using `; to separate databases and , to separate credentials. The supported actions are import and restore. A failing import or restore now aborts server startup with an error (since v26.10.1; before, a failed import silently left the database created but empty). Only one WITH setting can be passed to import; a comma inside {…​} starts a new command, not a second setting. Example: Universe[albert:einstein:admin];Amiga[Jay:Miner,Jack:Tramiel]{import:/tmp/movies.tgz}

String

server.startupRestoreSlotWaitMs

Milliseconds the restore: command of server.defaultDatabases waits for a backup, restore or import of the same database, already running on this server, to finish before it refuses. A refusal stops the server boot. 0 or a negative value refuses immediately. See Create default database(s). (Since v26.10.1)

Long

60000

server.defaultDatabaseMode

The default mode to load pre-existing databases. The value must match a com.arcadedb.engine.PaginatedFile.MODE enum value: {READ_ONLY, READ_WRITE}Databases which are newly created will always be opened READ_WRITE.

String

READ_WRITE

server.httpIncomingHost

TCP/IP host name used for incoming HTTP connections

String

0.0.0.0

server.httpIncomingPort

TCP/IP port number used for incoming HTTP connections. Specify a single port or a range <from>-<to>. Default is 2480-2489 to accept a range of ports in case they are occupied.

String

2480-2489

server.httpsIncomingPort

TCP/IP port number used for incoming HTTPS connections. Specify a single port or a range <from>-<to>. Default is 2490-2499 to accept a range of ports in case they are occupied.

String

2490-2499

server.httpsIoThreads

Number of threads to use in the HTTP server

Integer

2 per core

server.httpSessionExpireTimeout

Timeout in seconds for a HTTP session (managing a transaction) to expire

Long

5

server.httpBodyContentMaxSize

Maximum size in bytes for HTTP request body content, measured on the wire. Set to -1 for unlimited size. A request that declares a Content-Encoding is additionally limited by server.httpBodyContentDecompressedMaxSize once decoded. Default is 100MB

Integer

100

server.httpBodyContentDecompressedMaxSize

Maximum size in bytes an HTTP request body may expand to once its Content-Encoding has been decoded. server.httpBodyContentMaxSize limits only the bytes that arrive, so on the endpoints that decode a body - the InfluxDB line protocol ingest (gzip) and the Prometheus remote_write and remote_read endpoints (Snappy) - it would otherwise act as a compression-ratio multiplier rather than a limit. A body that decodes past this value is refused with 413 before the decoded bytes are allocated. Set to -1 (the default) to use the same value as server.httpBodyContentMaxSize, including its own -1 meaning unlimited; set to 0 for unlimited. (Available since v26.10.1)

Long

-1

server.httpStreamingWriteTimeout

Budget in ms a single blocking write of a streamed HTTP response (/batch results, Accept: application/x-ndjson on /query and /command, Server-Sent Events of AI chat and long-running server commands) may make no progress. When a client stops reading, the connection is closed and the worker thread released. The timer is re-armed for each chunk of at most 64 KB, so a slow but reading client never trips it. 0 or a negative value leaves streamed writes unbounded. Since v26.10.1.

Integer

60000

server.httpStreamingKeepAliveInterval

Interval in ms after which a streamed answer (Accept: application/x-ndjson on /query, /command and /batch) that has had nothing to send writes a bare newline, which consumers skip. Keeps a client or proxy that bounds silence (the Java remote client does) from failing a healthy slow query. Keep it well below the smallest silence budget of clients and proxies. 0 or a negative value sends no keep-alive. Since v26.10.1.

Integer

5000

server.httpAuthSessionExpireTimeout

Timeout in seconds for a HTTP authentication session to expire. This timeout is computed from the latest request using the auth token. See Token-Based Authentication.

Long

1800

server.httpAuthSessionMax

Maximum number of concurrent HTTP authentication sessions the server keeps in memory. Once reached, a further POST /api/v1/login is answered 503 instead of growing the session map without bound; expired sessions are reclaimed before refusing. Set to 0 for unlimited (not recommended). (Available since v26.9.1)

Integer

10000

server.httpAuthSessionMaxPerUser

Maximum number of concurrent HTTP authentication sessions a single user may hold. Beyond it, that user’s oldest session is invalidated to make room for the new one, so a login loop recycles only its own sessions and never affects other users. Set to 0 for unlimited (not recommended). (Available since v26.9.1)

Integer

100

server.mode

Server mode between 'development', 'test' and 'production'

String

development

server.name

Server name

String

ArcadeDB_0

server.plugins

Server plugins to load, see available plugins. Format as comma separated list of: <pluginName>:<pluginFullClass>.

String

server.rootPassword

Password for root user to use at first startup of the server. Set this to avoid asking the password to the user

String

null

server.rootPasswordPath

Path to file with password for root user to use at first startup of the server. Set this to avoid asking the password to the user

String

null

server.rootPath

Root path in the file system where the server is looking for files. By default is the current directory

String

null

server.securityAlgorithm

Default encryption algorithm used for passwords hashing

String

PBKDF2WithHmacSHA256

server.reloadEvery

Time in milliseconds of checking if the server security files have been modified to be reloaded

Integer

5000

server.securitySaltCacheSize

Cache size of hashed salt passwords. The cache works as LRU. Use 0 to disable the cache

Integer

64

server.apiTokenRequireSecureTransport

When true, POST /api/v1/server/api-tokens refuses to mint an API token unless the request arrived over HTTPS, from a loopback peer, or through a reverse proxy listed in server.apiTokenTrustedProxies that reports https. A refused mint is answered 412. When false, an unprotected mint goes ahead and is logged at WARNING. The default is scheduled to change to true in 27.1.1; see Create an API token. (Since v26.10.1)

Boolean

false

server.apiTokenTrustedProxies

Comma-separated literal IP addresses or CIDR ranges (IPv4 and IPv6) of the reverse proxies allowed to vouch, through X-Forwarded-Proto or the RFC 7239 Forwarded header, that an API token mint reached them over HTTPS. Applies to the HTTP route and to the gRPC CreateApiToken RPC. Headers from any other peer are ignored. Hostnames are rejected, not resolved, and a list that does not parse is treated as empty and logged at SEVERE. List only an L7 proxy that sets or overwrites the header, never an L4 balancer that passes the client’s headers through. Empty trusts no proxy. (Since v26.10.1)

String

server.saltIterations

Number of iterations to generate the salt or user password. Changing this setting does not affect stored passwords

Integer

65536

server.eventBusQueueSize

Size of the queue used as a buffer for unserviced database change events.

Integer

1000

server.eventBusMaxPendingBytes

Maximum number of bytes of change-stream frames that may be outstanding towards a single WebSocket subscriber before it is evicted. Frames are sent asynchronously, so a subscriber that never reads accumulates them in the server’s send buffer: the producer-side queue is bounded but a slow consumer is charged to the server’s heap, not to its own. Past this cap the subscription is dropped and the channel closed, which is what the client would experience anyway. 0 disables the cap. Since v26.9.1

Long

16777216

server.wsMaxPendingControlBytes

Maximum number of bytes of WebSocket request-answer frames - a subscription acknowledgement/error, or an insert-session started/batchAck/committed/error - that may be outstanding towards a single /ws connection before it is closed. This bounds the answer side of the connection; server.eventBusMaxPendingBytes bounds only the change-stream push frames a client subscribed to. 0 disables the cap. Since v26.10.1

Long

16777216

server.wsInsertSessionExpireTimeout

Timeout in seconds for a /ws duplex insert session to expire, counted from the latest frame received on it. An expired session is rolled back and the client is told with an unsolicited error frame. Since v26.10.1.

Long

60

server.wsMaxControlFrameSize

Maximum size in bytes of a single text frame accepted on /ws before an insert session is started on that connection, and of every binary frame. A larger frame closes the connection with 1009 TOO_BIG as soon as it crosses the cap. 0 or a negative value restores the unbounded behavior. Since v26.10.1.

Long

65536

server.wsMaxInsertFrameSize

Maximum size in bytes of a single text frame accepted on a /ws connection while it has a duplex insert session open. Up to 64 frames may wait per connection, so the per-connection buffering to budget for is this value times 64. 0 or a negative value restores the unbounded behavior. Since v26.10.1.

Long

16777216

server.wsMaxInsertChunkRows

Maximum number of records a single /ws chunk frame may carry. A chunk over the cap is refused with an error frame naming the limit and the session stays open, so the client can split its batch and carry on. 0 or a negative value disables the cap. Since v26.10.1.

Integer

100000

server.healthCheck.enabled

Run the server health monitor: one background thread that samples free disk space on the filesystem holding the databases, available heap, and JVM pause times, and writes a WARNING to the server event log when one of them degrades. Each warning is rate limited - 24h for low disk, 30 minutes for heap and JVM pauses - so a server that stays degraded reports it periodically rather than on every 10-second sample. Read at server start. Since v26.10.1

Boolean

true

server.readinessRequiresHA

When true and HA is active, /api/v1/ready also requires the node to have joined the Raft group (a leader has been elected). Default false preserves current readiness behavior. See Health probes.

Boolean

false

server.readinessHAMaxLag

When server.readinessRequiresHA is true, the maximum number of Raft log entries a follower may lag behind the commit index (commitIndex - lastAppliedIndex) and still report Ready. Keeps /api/v1/ready returning 503 until a (re)joined follower has replayed the committed log, so a rolling restart does not drop the write quorum. See Health probes.

Long

100

server.logFormat

Console log format: text (default, human-readable) or json (one JSON object per line with correlation fields). Can be set from the server configuration file, SET SERVER SETTING or as a -D JVM property; an explicit -D wins over the configuration file. See Structured logging. (Honoured outside -D since v26.10.1)

String

text

server.logIncludeTrace

In text log mode, append [traceId=…​] to each line while a trace is active. Default false preserves current text output.

Boolean

false

server.grpcQueryMaxResultRows

Hard ceiling on the number of rows the gRPC unary ExecuteQuery materializes. A request limit at or below this cap is honored; a result that would exceed it fails the call with RESOURCE_EXHAUSTED (consistent with the StreamQuery MATERIALIZE_ALL path) rather than silently truncating, and a client cannot bypass it with a larger limit. Bounds heap usage and protects against limitless-query denial-of-service. The default is lower than server.grpcStreamMaxMaterializedRows because the unary response is built and returned as a single gRPC message (also bounded by the max message size), whereas StreamQuery emits incrementally. Set to -1 or 0 for unlimited (removes the DoS protection).

Integer

100000

server.grpcStreamMaxMaterializedRows

Maximum number of rows the gRPC StreamQuery MATERIALIZE_ALL retrieval mode buffers in memory before emitting. Exceeding the cap fails the call with RESOURCE_EXHAUSTED so clients fall back to CURSOR/PAGED streaming instead of running the server out of memory. Set to -1 or 0 for unlimited (removes the DoS protection).

Integer

1000000

server.grpcTimeSeriesMaxResultRows

Hard ceiling on the number of rows - or aggregation buckets - one gRPC TimeSeriesQuery answers with. A request limit at or below this cap is honored; a request limit above it is refused before the first message with RESOURCE_EXHAUSTED, so a client is never handed a partial series it cannot tell apart from a complete one. Separate from server.grpcQueryMaxResultRows because TimeSeriesQuery is a server-streaming RPC, so the single-message rationale that keeps the unary ceiling low does not apply to it. The default matches the HTTP twin POST /api/v1/ts/{database}/query (server.httpQueryMaxResultRows), so the same range is served over both protocols. Set to -1 or 0 for unlimited (the aggregated path materializes every bucket before emitting any, so this removes its DoS protection; the raw path stays lazy either way).

Integer

1000000

server.grpcStreamWriteTimeoutMs

Maximum time in milliseconds a gRPC StreamQuery worker waits for the client transport to become ready to accept the next batch before aborting the stream. Prevents a slow or abandoned client from pinning the worker thread (and the open ResultSet/transaction) indefinitely. Set to -1 to wait forever (removes the DoS protection).

Long

60000

serverMetrics

True to enable metrics

Boolean

true

serverMetrics.logging

True to enable metrics logging

Boolean

false

serverMetrics.prometheus.requireAuthentication

Require authentication on the /prometheus scrape endpoint exposed by the Prometheus metrics plugin (plugin-level key, read by the optional metrics module). Since v26.10.1 the endpoint reads this on every scrape, so a change through SET SERVER SETTING takes effect at once; before that it kept the value it was started with until the server was restarted.

Boolean

true

serverMetrics.otlp.enabled

Register an OTLP metrics registry alongside the /prometheus scrape, pushing metrics to serverMetrics.otlp.endpoint. Requires serverMetrics=true. Plugin-level key read by the optional metrics module. See Metrics depth.

Boolean

false

serverMetrics.otlp.endpoint

OTLP metrics export endpoint, used when serverMetrics.otlp.enabled=true. Metrics use OTLP/HTTP (port 4318, path /v1/metrics), not gRPC; a URL without a path gets /v1/metrics appended.

String

http://localhost:4318/v1/metrics

serverMetrics.otlp.step

How often metrics are pushed to serverMetrics.otlp.endpoint, in milliseconds. Also the window rates and maxima are measured over. Not positive keeps the default of one minute; a positive value below 1000 is raised to 1000. Read when the metrics plugin starts.

Long

60000

serverMetrics.serviceName

The OpenTelemetry service.name resource attribute reported by the tracing and OTLP metrics plugins. OTEL_SERVICE_NAME, then a service.name entry in OTEL_RESOURCE_ATTRIBUTES, take precedence. Read when the plugins start. Since v26.10.1.

String

arcadedb

serverMetrics.tracing.enabled

Enable OpenTelemetry distributed tracing (requires the optional tracing plugin on the classpath, shipped in the full distribution). Query/command spans include the statement text as the db.statement span attribute, which may contain sensitive data, so secure the OTLP collector endpoint. See Distributed tracing.

Boolean

false

serverMetrics.tracing.endpoint

OTLP trace export endpoint (gRPC).

String

http://localhost:4317

serverMetrics.tracing.samplingRate

Parent-based trace sampling ratio in [0.0,1.0]. 1.0 samples everything, 0.0 disables sampling.

Float

0.0

serverMetrics.tracing.excludedPaths

Comma-separated HTTP request paths that never produce a trace span, matched exactly (query string excluded, one trailing slash ignored, no wildcards). The default leaves out the readiness and health probes. The arcadedb.http.requests timer still counts them. An empty string traces every request. Read when the tracing plugin starts. Since v26.10.1.

String

/api/v1/ready,/api/v1/health

studio.enabled

Force-enable the Studio web tool even when the server runs in production mode. In development and test mode Studio is always served; in production mode it is disabled by default and this setting can re-enable it. See how-to/operations/server.adoc#production-mode-defaults

Boolean

false

DATABASE

Name Description Type Default Value

asyncOperationsQueueImpl

Queue implementation to use between 'standard' and 'fast'. 'standard' consumes less CPU than the 'fast' implementation, but it could be slower with high loads

String

standard

asyncOperationsQueueSize

Size of the total asynchronous operation queues (it is divided by the number of parallel threads in the pool)

Integer

1024

asyncBackPressure

When the asynchronous queue is full at a certain percentage, back pressure is applied

Integer

0

asyncTxBatchSize

Maximum number of operations to commit in batch by async thread

Integer

10240

asyncWorkerThreads

Number of asynchronous worker threads. By default it is cores minus 1, but at least 1

Integer

(machine dependent)

indexDefaultPageSize

Default page size in bytes for new plain LSM-tree indexes (not full-text, geo or vector ones) created without an explicit page size (SQL CREATE INDEX has no page-size clause). A transaction copies every page it changes, so smaller pages make small write transactions cheaper while larger ones make lookups slightly faster. Existing indexes keep their page size. Minimum is 8192. In a cluster, keep it identical on all the servers. Since v26.10.1

Integer

262144

bucketDefaultPageSize

Default page size in bytes for buckets. Default is 65536

Integer

65536

bucketReuseSpaceMode

Mode used to reuse space in pages. Use 'low' to have faster updates consuming more space on disk, medium for balance. Default is 'high'. Applies per database, so ALTER DATABASE on one database no longer affects the others (fixed in v26.10.1)

String

high

bucketWipeOutOnDelete

Wipe out record content on delete. If enabled, assures deleted records cannot be analyzed by parsing the raw files and backups will be more compressed, but it also makes deletes a little bit slower

Boolean

true

command.timeout

Default timeout for commands (in ms). On a cluster, a write a follower forwards to the leader carries the follower database’s budget, and the leader enforces that budget in place of its own setting. (Since v26.10.1: previously the leader enforced its own value, which could differ from the one the follower waited for.)

Long

0

command.warningsEvery

Reduce warnings in commands to print in console only every X occurrences. Use 0 to disable warnings with commands

Integer

100

commitLockTimeout

Timeout in ms to lock resources during commit. A bulk index build uses index.buildCommitLockTimeout instead for its own commits (since v26.10.1)

Long

5000

explicitLockTimeout

Timeout in ms to acquire the resources of an explicit LOCK. Separate from commitLockTimeout, which bounds the locking the engine does for you at commit time (honoured since v26.10.1)

Long

5000

cypher.algoMaxWorkingMemory

Maximum heap, in bytes, that a single algo.* procedure call may reserve for its dense working set: walk buffers, embedding matrices, nodeCount x nodeCount distance/similarity/neighbor matrices, terminal-pair tables, and (as of v26.9.1) the loaded graph itself (vertex list, RID index, adjacency list). A call over budget is refused before allocating, naming the offending component. Negative means no limit. Default auto-scales with the JVM max heap (1/8 of it, never below 64MB). Graph load coverage added in v26.9.1

Long

64MB (auto-scaled)

opencypher.planCache

Maximum number of OpenCypher execution plans to keep in cache (frequency-based eviction)

Integer

300

opencypher.statementCache

Maximum number of parsed OpenCypher statements to keep in cache. A statement must be hit twice to be protected from a burst of one-off query texts (for example queries that embed their values), so prefer parameters and raise this value if you generate many distinct queries. This is the setting that sizes Cypher statement caching; the cypher.statementCache that used to be listed here had no reader and was removed in v26.10.1

Integer

300

opencypher.loadCsv.allowFileUrls

Allow LOAD CSV to access local files via file:/// URLs and bare file paths. Disable for security in multi-tenant server deployments. In production server mode, this is automatically set to false if not explicitly configured. See how-to/operations/server.adoc#production-mode-defaults

Boolean

true

opencypher.loadCsv.importDirectory

Root directory for LOAD CSV file:/// URLs. When set, file paths are resolved relative to this directory and path traversal (../) is blocked. Empty string means no restriction

String

(empty)

dateFormat

Default date format using Java SimpleDateFormat syntax. Textual fields (month or day names, e.g. MMM, EEE) always use the English locale, whatever the JVM locale of the server, so every node of a cluster writes and reads the same value (v26.9.1)

String

yyyy-MM-dd

dateImplementation

Default date implementation to use on deserialization. By default java.time.LocalDate is used, but the following are supported: java.util.Calendar, java.util.Date, java.time.LocalDateTime

Class

java.time.LocalDate

dateTimeFormat

Default date time format using Java SimpleDateFormat syntax. Textual fields always use the English locale, see dateFormat

String

yyyy-MM-dd HH:mm:ss

dateTimeImplementation

Default datetime implementation to use on deserialization. By default java.time.LocalDateTime is used, but the following are supported: java.util.Date, java.util.Calendar, java.time.LocalDateTime, java.time.ZonedDateTime, java.time.Instant. java.util.Date and java.util.Calendar cannot carry sub-millisecond precision, so with them DATETIME_MICROS and DATETIME_NANOS values are returned as java.time.LocalDateTime

Class

class java.time.LocalDateTime

deleteTolerateBrokenChain

When true, a DELETE of a record whose multi-page chunk chain is structurally corrupted removes the record anyway, skipping the index cleanup it cannot read and leaving any unreachable chunks for CHECK DATABASE FIX to reclaim. When false (the default) such a delete is refused with a BrokenChunkChainException naming the record, so corruption is never removed silently. Genuine transaction conflicts are unaffected by this setting: they keep retrying either way. CHECK DATABASE FIX removes a corrupted record regardless of this setting

Boolean

false

freePageRAM

Percentage (0-100) of memory to free when Page RAM is full

Integer

50

gavCchMaxArcsPerEdge

Upper bound on the size of a Customizable Contraction Hierarchy (CCH) attached to a Graph Analytical View, as supergraph arcs (edges plus shortcuts) per edge of the routed graph. Road, logistics and utility networks need a small multiple of their edge count; graphs without small separators (social graphs, graphs with supernodes) need far more, and building them would exhaust the heap. A hierarchy that would exceed the bound is not built: the view reports it as UNSUITABLE and shortest-path queries keep answering through bidirectional Dijkstra. Graphs small enough to need fewer than 100,000 arcs are always accepted. Each arc costs about 52 bytes of heap (topology plus the directed metric) and 20 more once undirected (BOTH) queries are served too, so the worst case at the default is about 830 bytes, or 1.2 KB, per routed edge. See Shortest Paths with Contraction Hierarchies

Integer

16

gavPersistCsr

When true, a Graph Analytical View (GAV/CSR) that is READY (with no pending overlay changes) when the database closes cleanly writes its CSR to disk alongside a freshness certificate (the database’s last committed transaction id at build time). If nothing was committed to the database between that close and the next open, the certificate still matches and the persisted CSR is reused as-is instead of being rebuilt by a full graph scan. Any commit in between invalidates the certificate and falls back to the previous behavior: an async rebuild triggered on open. Set to false to disable persisting the CSR file (e.g. to avoid its disk footprint or the extra write at close). See Graph OLAP Engine. Since v26.9.1

Boolean

true

gavRestoreAwaitTimeout

Milliseconds database.open() blocks waiting for Graph Analytical Views (GAV/CSR) restored from persisted definitions to reach READY before returning. 0 (default) does not wait: when no persisted CSR plausibly applies, the full rebuild is still triggered immediately in the background, but open() returns before it completes and queries issued right after run unaccelerated until it does; when a persisted CSR does plausibly apply (see gavPersistCsr), nothing is even started at open() time as of v26.9.1 - it is deferred to whichever query touches the view first (see Lazy Restore), so the fast path costs nothing for a session that never queries it. A positive value here forces the wait either way, trading a slower open() for the restored/rebuilt view being usable by the query that triggered the reopen. See Graph OLAP Engine

Long

0

gavQueryRestoreAwaitTimeout

Milliseconds a query waits, while it is planned or starts, for a Graph Analytical View (GAV/CSR) whose deferred restore from disk is still in flight, so the first count push-down, MATCH, shortest path or other graph function after a reopen runs on the restored view instead of reading every record. Covers the SQL and OpenCypher planners and the SQL graph functions; the algo.* procedures have their own budget (gavAlgoRestoreAwaitTimeout). The wait ends early when the restore finishes, and a view that is only rebuilding after a commit is never waited for. 0 does not wait: the call takes the record path. The wait is not tied to the command timeout, so keep it small. Since v26.11.1.

Long

5000

gavAlgoRestoreAwaitTimeout

Milliseconds a whole-graph algorithm (algo.wcc, algo.pagerank, algo.bfs and the other algo.* procedures) waits for a Graph Analytical View whose deferred restore from disk is still in flight, so the first call after a reopen runs on the restored view instead of scanning every record. The wait ends early when the restore finishes or the command timeout expires. 0 does not wait. A command without its own timeout can block for the whole budget, so lower it if such commands must answer quickly. Separate from gavRestoreAwaitTimeout, which makes open() itself block. Since v26.10.1.

Long

60000

graph.edgeAppendMerge

At commit, when the only conflict on an edge-list page is concurrent in-chunk edge appends (which commute), re-apply the appends on top of the newer page version instead of failing the whole transaction with a retryable conflict. Removes the retry storm on super-node (hot vertex) edge insertion. See Super-Nodes.

Boolean

true

graph.edgeListInitialChunkSize

Size in bytes of the first chunk of a vertex’s edge list. Each further chunk doubles the previous one up to 8192, so the space a vertex allocates is the sum of that series - a smaller first chunk does not necessarily use less space, it just takes more chunks (each with its own header) to reach the same capacity. The best value follows the degree distribution: around 128 suits an average degree near 10, the default suits very sparse graphs, and above degree 100 the setting barely matters. Values below 32 are clamped. See Lightweight Edges.

Integer

64

graph.supernodeThreshold

Approximate number of edges (per vertex, per direction) after which the vertex’s edge list is promoted to the striped super-node layout, spreading further appends over multiple files so concurrent insertions on the same hot vertex do not contend. Forward-incompatible on first use: promotion writes a new record type, so once any vertex promotes the database can no longer be opened by older releases; promotion is one-way. Iteration order on promoted vertices is approximate (newest-generation-first) instead of strict reverse-insertion. 0 disables promotion entirely (databases stay fully readable by older releases). See Super-Nodes.

Integer

4096

graph.supernodeStripes

Number of stripes (separate edge-list files) a super-node’s edge list is spread over at promotion. The stripes are hosted in a per-type bucket pool of this many files, created once per type at its first promotion (types without super-nodes cost no files). Write parallelism saturates at the number of concurrent writers, so values beyond the CPU cores rarely help. Values below 2 disable promotion entirely. Recorded per vertex at promotion time. See Super-Nodes.

Integer

16

gremlin.engine

Gremlin engine to use. By default the native java engine is used. The auto setting uses the legacy groovy engine in case parameters are set, otherwise the native java one, and is not recommended for security-critical deployments. If you have compatibility issues with gremlin statements that use lambdas or in general, switch to the groovy one

String

java

gremlin.client.port

Port of the Gremlin Server the remote ArcadeGraph client connects to. 0 uses the port the server advertises, falling back to 8182. Set it when the port is reached through a mapping the server does not know about

Integer

0

gremlin.timeout

Default timeout for gremlin commands (in ms). Deprecated

Long

30000

index.buildCommitLockTimeout

Timeout in ms a bulk index build waits for the file locks of one of its commits, replacing commitLockTimeout for those commits only. A vector index build commits in chunks, and each of those commits is a step of a build that can cost tens of minutes, so losing one to the interactive timeout discarded the whole build - while the contender it was queued behind was an ordinary commit that would be done in milliseconds. This bounds only how long the build waits, never how long it holds a lock, so raising it cannot make any other transaction slower. 0 or less waits indefinitely. The effective value is clamped to be at least commitLockTimeout, so setting it lower has no effect. Since v26.10.1

Long

60000

indexCompactionMinPagesSchedule

Minimum number of mutable pages for an index to be schedule for automatic compaction. 0 = disabled

Integer

10

indexCompactionRAM

Maximum amount of RAM to use for index compaction, in MB

Long

300

initialPageCacheSize

Initial number of entries for page cache

Integer

65535

vectorIndex.graphBuildCacheSize

Maximum number of vectors to cache in memory during HNSW graph building. Higher values speed up construction but use more RAM. RAM usage = cacheSize × (dimensions × 4 + 64) bytes. 0 (the default) sizes it automatically: the cache holds the whole corpus when it fits vectorIndex.graphBuildCacheMaxHeapPercent, for indexes whose vectors live in the documents (no quantization, or PRODUCT) and, since v26.10.1, for inline-quantized ones (INT8/BINARY) as well. Setting an explicit value opts out of that auto-sizing

Integer

0

vectorIndex.graphBuildCacheMaxHeapPercent

Maximum share of the JVM heap the auto-sized graph-build cache may use. Only applies when vectorIndex.graphBuildCacheSize is left at 0. A corpus larger than this budget still builds: the cache evicts instead of holding everything. Since v26.10.1 it is measured against the -Xmx ceiling and then capped at 90% of the heap currently available, so the same corpus gets the same cache whether it was ingested into this JVM first or not, while an online rebuild holding the old graph resident still asks for less. Before v26.10.1 it was a share of the available heap only, and did not apply to INT8/BINARY indexes at all. Values above 90 are clamped to 90

Integer

25

vectorIndex.searchCacheSize

Maximum number of vectors kept in the per-index search cache. The cache is shared by every query on the index and survives across queries, so a working set that fits stays resident instead of being re-read from the documents (or from the quantized index pages) on every beam-search hop. RAM usage = cacheSize × (dimensions × 4 + 64) bytes. 0 (the default) sizes it automatically from the number of indexed vectors, capped by vectorIndex.searchCacheMaxHeapPercent. -1 disables the cache entirely

Integer

0

vectorIndex.searchCacheMaxHeapPercent

Upper bound, as a percentage of the JVM heap currently available rather than of -Xmx, on the RAM an automatically sized per-index search cache may use (see vectorIndex.searchCacheSize). Ignored when the cache size is set explicitly. Values above 90 are clamped to 90

Integer

25

vectorIndex.deltaCacheSize

Maximum number of vectors written since the last graph rebuild that keep a copy in memory. Every write is appended to a delta buffer so the vector is searchable before it reaches the HNSW graph, and only a rebuild drains that buffer - so an ingest that outruns the rebuilds used to grow a second full copy of the corpus in RAM, which is what made a 4.2M x 768-dimension bulk load run out of memory at -Xmx16g. The vector is written to disk before it is buffered, so entries past this cap keep only their identity and the vector is read back from disk when a query needs it. RAM usage = deltaCacheSize × (dimensions × 4 + 64) bytes. 0 (the default) sizes it automatically from vectorIndex.deltaCacheMaxHeapPercent. -1 keeps every buffered vector in memory, which is the behaviour before v26.10.1 and is unbounded. Reported by the index statistics as deltaResidentVectors and deltaResidentVectorsCapacity. Since v26.10.1

Integer

0

vectorIndex.deltaCacheMaxHeapPercent

Share of the -Xmx ceiling the automatically sized delta buffer cache may use, then capped at 90% of the heap currently available - the same measure vectorIndex.graphBuildCacheMaxHeapPercent uses, so a rebuild holding the old graph and an ingest filling the buffer are judged against the same free heap. Ignored when vectorIndex.deltaCacheSize is set explicitly. This is a margin rather than a reservation: neither cache reserves heap from the other, and what keeps them in check is that memory one of them keeps lowers the next reading for both. Values above 90 are clamped to 90. Since v26.10.1

Integer

10

vectorIndex.locationCacheSize

Maximum number of vector locations to cache in memory per vector index. Set to -1 for unlimited. Each entry uses ~56 bytes. Recommended: 100000 for datasets with 1M+ vectors

Integer

-1

vectorIndex.prefilterMaxSelectivity

Maximum fraction of an index’s live vectors that a query’s RID allow-list may cover and still resolve the allow-list to its ordinals and score them directly, instead of paying for a Bits-filtered HNSW graph walk that gets more expensive, not less, as the allow-list narrows (a filter is only checked once a node is popped from the search beam, so a very selective filter can make the walk expand trying to fill k instead of shrinking). Applies to plain k-NN search and to groupBy search; see vectorIndex.prefilterApproximateMaxSelectivity for the separate threshold the PQ-approximate (zero-disk-I/O) search path uses. Set to 0 to always use the graph walk. Since v26.9.1

Float

0.2

vectorIndex.prefilterApproximateMaxSelectivity

The vectorIndex.prefilterMaxSelectivity threshold, but for PQ-approximate (zero-disk-I/O) vector search. Kept as a separate, lower setting because PQ scores a candidate from in-memory codes roughly an order of magnitude cheaper than the exact path’s page/document read, so its graph walk stays the cheaper option down to a narrower allow-list than the exact path’s. Set to 0 to always use the graph walk. Since v26.9.1

Float

0.05

vectorIndex.mutationsBeforeRebuild

Number of mutations (inserts/updates/deletes) before rebuilding the HNSW graph index. Higher values reduce rebuild cost but may return slightly stale results. Recommended: 50-200 for read-heavy, 200-500 for write-heavy workloads

Integer

100

vectorIndex.rebuildGraphRatio

Fraction of the current graph size that must accumulate as pending mutations before the HNSW graph is rebuilt, on top of the absolute vectorIndex.mutationsBeforeRebuild floor. A rebuild always reindexes the whole graph, so a fixed count makes it cost O(index size) for every few new vectors and turns bulk ingestion quadratic; scaling the threshold with the graph amortizes rebuilds instead. Vectors waiting for the next rebuild stay exactly searchable in memory meanwhile, so a higher ratio trades a slightly longer per-query scan of those vectors for far less rebuild CPU. Set to 0 to use only the absolute threshold

Float

0.2

vectorIndex.maxPendingMutations

Ceiling on the threshold computed from vectorIndex.rebuildGraphRatio. Set to 0 for no ceiling. Being a fixed count, it stops scaling once the ratio-derived threshold reaches it (at the defaults, from 250,000 vectors upward), so past that point the same absolute per-query scan cost lands on an index of any size. vectorIndex.maxDeltaScanRatio is the size-independent bound and is the setting to reach for when query latency, rather than rebuild frequency, is what needs protecting. Note that this bounds how often a rebuild is triggered, not how many vectors wait for one: writes keep arriving between rebuilds regardless. What bounds the memory those waiting vectors occupy is vectorIndex.deltaCacheSize, since v26.10.1

Integer

50000

vectorIndex.maxDeltaScanRatio

How much work a query may spend scanning vectors written since the last graph rebuild, as a multiple of the work its graph search already does, before a rebuild is triggered to absorb them. Those vectors are answered by a straight scan, so that part of a query grows with how many are waiting while the graph search it supplements grows only with the logarithm of the index size: at the default vectorIndex.maxPendingMutations the scan has been measured at four fifths of query time. The count-based settings cannot bound it, so this one is measured rather than assumed - ArcadeDB records how many nodes its graph searches actually visit and compares the waiting vectors against that. 1.0 lets the scan cost about as much as the search. Lower it for latency-sensitive read-heavy workloads, raise it to rebuild less often, set 0 to disable. A rebuild is only triggered once the scans have also cost as much as the rebuild will, so the extra rebuild CPU this can introduce is bounded by the query CPU it removes. Because it is evaluated when queries run, a write-only workload never triggers it. Reported by the index statistics as deltaScanBudget, deltaScanWorkSinceRebuild and deltaScanWorkTarget. Since v26.9.1

Float

1.0

vectorIndex.inactivityRebuildTimeoutMs

Inactivity timeout in milliseconds before flushing buffered vectors and rebuilding the HNSW graph. When mutations exist but haven’t reached the rebuild threshold, a timer starts after the last mutation. On a graph under 1,000 vectors the rebuild is cheap and fires for any pending mutation count; on a larger graph it only fires once pending mutations reach at least 10% of the effective rebuild threshold, so a single stray insert does not force a full graph rebuild. The size compared against is the number of vectors the index holds, not the part of the graph the session has loaded, so an ingest-then-idle process that never queries is gated the same way. Since v26.10.1 the timer does not fire while a bulk load is open on the database (GraphBatch, and therefore GraphImporter and the HTTP batch endpoint): a loader that pauses for an index compaction or a garbage collection looks idle to this timer, and the rebuild it used to start covered only the part of the dataset loaded so far and was made obsolete by the rest of the load. The rebuild is now scheduled once, when the load finishes. Set to 0 to disable. Recommended: 10000-30000 for low-volume ingestion

Integer

15000

vectorIndex.rebuildMaxHeapPercent

Share of the currently available heap that an online vector graph rebuild’s estimated peak footprint may occupy before the rebuild is deferred instead of attempted. An online rebuild keeps the old graph resident so searches keep working and pays for a full new build’s working set on top of it; with no gate it simply attempts the rebuild and dies with an OutOfMemoryError when it does not fit. Since v26.10.1 what keeping the old graph resident costs is measured rather than assumed, so a graph served from pages - the shape after a reopen - is not charged as a second copy of itself in memory, and the available heap it is judged against counts the page read cache as reclaimable: a rebuild that fits only by giving some of it up evicts exactly that shortfall first (oldest pages, across every open database, since the cache is shared) and is still deferred if the cache cannot hand those bytes over. A deferred cycle is not lost: pending vectors stay exactly searchable through the in-memory delta buffer, so the cost is a longer delta scan per query rather than wrong or missing results, and the deferral is logged and counted as rebuildsDeferredForMemory in the index statistics. Applies to online rebuilds only - a first build, a rebuild on close, REBUILD INDEX and COMPACT INDEX are never declined. Since v26.11.1, when the rebuild does not fit beside the in-memory graph, the graph is first swapped for its persisted on-disk copy (searches read it from pages until the new graph is published, counted as residentGraphDemotions) and the rebuild is deferred only if it still does not fit. Values above 90 are clamped to 90. Set to 0 to disable the gate. Since v26.9.1

Integer

90

vectorIndex.rebuildDeferralCooldownMs

Minimum time in milliseconds before another online vector graph rebuild may be attempted after one was deferred for lack of heap (see vectorIndex.rebuildMaxHeapPercent). A deferral does not consume the pending mutations that triggered it - only a successful build does - so without a cooldown the next search re-triggers it immediately, and since a search checks on every query a large heap-constrained index would spawn a rebuild thread, take the JVM-wide rebuild permit and log a warning once per query. A rebuild that completes clears the cooldown. Set to 0 to retry on the next trigger. Since v26.9.1

Integer

30000

maxPageRAM

Maximum amount of pages (in MB) to keep in RAM. When unset it is a quarter of the maximum JVM heap (4096 MB under -Xmx16g). A value above 80% of the heap is reduced to half of it

Long

25% of the max heap

pageFlushQueue

Size of the asynchronous page flush queue

Integer

512

pageSnapshotEnabled

When true (the default), a full backup, an HA database verify and an HA snapshot ship read a point-in-time image served from a page-level copy-on-write shadow, so writers keep running at full speed for the duration. When false, or when the shadow exceeds pageSnapshotMaxSize, they fall back to freezing the data files instead, which throttles every writer until the operation finishes

Boolean

true

pageSnapshotMaxRAM

Memory budget in MB for the copy-on-write shadow of a single point-in-time window. The shadow only holds the pages modified while the window is open, once each, so a short backup on a moderately busy database often never touches the disk at all. Beyond this budget the shadow spills to a scratch file (see pageSnapshotSpillPath)

Long

64

pageSnapshotMaxSize

Hard limit in MB (memory plus spill file) on a single copy-on-write shadow before the window is abandoned and its consumer falls back to freezing the data files. The default -1 sizes the limit automatically when the window opens: the smaller of the size the page files occupy at that instant - which the shadow provably cannot exceed - and half the space free on the spill volume, but never less than pageSnapshotMaxRAM, since that part of the budget never touches the disk. Set a positive value to pin an absolute limit in MB, or 0 for no limit

Long

-1

pageSnapshotSpillPath

Directory for the scratch file a copy-on-write shadow spills into once pageSnapshotMaxRAM is exhausted. Empty (the default) uses the database directory, where the shadow competes for space with the very files it is protecting. The file is pure scratch: created on demand, deleted when the window closes, and never read by recovery

String

polyglotCommand.timeout

Default timeout for polyglot commands (in ms)

Long

10000

queryMaxHeapElementsAllowedPerOp

Maximum number of elements (records) allowed in a single query for memory-intensive operations (eg. ORDER BY in heap). If exceeded, the query fails with an OCommandExecutionException. Negative number means no limit. In OpenCypher it also bounds the rows a Cartesian product or a hash join of disconnected patterns buffers, ORDER BY, DISTINCT, UNION, the groups of an aggregation, collect() and the eager read ahead of a write (since v26.10.1). This setting is intended as a safety measure against excessive resource consumption from a single query (eg. prevent OutOfMemory). A GROUP BY computed by a parallel scan checks the limit on each thread and on the final groups, so its peak memory can reach the limit times the number of threads. A SQL time series aggregation (ts.timeBucket() with GROUP BY) that returns more buckets than this fails instead of exhausting the heap, as the HTTP, gRPC and Grafana time series endpoints already did (since v26.10.1). It also bounds the index the delete of a vertex keeps in heap to find the incoming edges of unidirectional edge types: past it, each delete scans the types instead. This limit bounds one operation of one query; queryMaxHeapRAM bounds the heap the buffers of all the running queries hold together

Long

500000

parallelScanAbandonedTimeout

Milliseconds a parallel scan waits for a result set that is neither read nor closed before giving up: the scan then frees its threads and the next read of that result set fails instead of silently returning fewer rows. A query whose LIMIT is reached releases its scan at once, without waiting for this timeout, and a result set left open never stalls other queries: they only run less in parallel until it is closed. Raise it for clients that keep cursors open with long pauses. 0 disables the timeout

Long

600000

queryIndexMaxSelectivity

Share of a type’s records above which an index search gives way to a full scan of the type, when the scan runs on one thread. Before loading any record, the matching index entries are read alone: when more of them match than this share of the records the type holds, the rows come from a scan filtered by the same condition, otherwise the matching records are loaded in physical order rather than in key order. A scan split across W workers of a parallel scan gives way sooner, at this share divided by (1 + W) / 2, because the index entries are read by one thread whatever the parallelism: with the default, 60% of the type for a sequential scan, 24% on 4 workers, 6% on 18. Applies, in SQL and OpenCypher, only where the order the rows arrive in cannot show in the result - the statement aggregates them or sorts them with an ORDER BY the index does not serve - and where the scan answers the same rows. 0 disables it (since v26.10.1)

Float

0.6

queryParallelScan

When true, a full scan of a type is read by several threads, for more throughput on multi-core machines: with or without a WHERE clause, and with count, sum, avg, min, max and their GROUP BY computed on those threads too, in SQL and in OpenCypher, as is a plain SELECT DISTINCT of fields over a type of at least 10,000 records (since v26.10.1). Rows and groups come back in the same order as a sequential scan, but the sum or average of floating-point values may differ in the last digits from one run to the next, as the threads add in no fixed order. A GROUP BY of many keys, where every thread would otherwise build its own group for nearly every key, switches to a key exchange once a thread has created a few thousand groups: from then on the rows of the keys that thread does not hold are aggregated in one set of groups shared by the threads and partitioned by key, so each of those keys is held and aggregated once rather than once per thread. This roughly halves the memory such a query reserves from queryMaxHeapRAM and makes it faster, and it changes nothing for a GROUP BY of few keys. EXPLAIN/PROFILE reports it on the aggregation step as N groups by key exchange (since v26.11.1). Used only outside an explicit transaction

Boolean

true

queryParallelScanMinBuckets

Minimum number of buckets a type needs for its full scans to run in parallel. A type with fewer buckets is scanned sequentially, unless one of its buckets is large enough to be split in page ranges (see queryParallelScanPagesPerUnit)

Integer

2

queryParallelScanPagesPerUnit

Minimum number of pages of the unit of work a parallel scan cuts a bucket in: a bucket of at least twice as many pages is read by several threads, each on a range of its pages, so a type with a single bucket (the default) is scanned in parallel too. 0 disables the split: each bucket is then read by one thread (since v26.10.1)

Integer

32

queryParallelScanMaxBatchBytes

Maximum bytes of record content one batch of a parallel scan holds in memory. The parallel scan reads records on its worker threads and hands them over in batches of up to 256 rows; with large records this bound closes a batch earlier. 0 or a negative value removes the bound (row count only) (since v26.10.1)

Long

16777216

queryBatchMaxBytes

Maximum bytes a scan of a bucket reads ahead of the query in one batch. A scan prefetches up to 1,024 records per bucket; with records that span several pages (a vertex with a big nested document) that is a lot of memory no query budget accounts for, and many concurrent queries could exhaust the heap. The batch ends once the bytes it copied out of the pages reach this size, whatever the record count (records that fit their own page are views of the cached page and are not counted). The limit also shrinks as running queries take the heap budget (see queryMaxHeapRAM): a scan reads ahead at most a sixty-fourth of what is left of it, down to one record at a time. The shares of the pool and of the budget are read once per batch and are not reservations, so the worst case is the number of scans running times the buckets each reads times the smaller of this setting and a sixty-fourth of what is left of the budget. A batch always holds at least one record. The low-ram profile sets it to 200KB. A scan that read under this pressure is slower for it, and says so: PROFILE marks its step with [read-ahead reduced in N batches by memory pressure] and the profiler counts it as queryHeapScanShrinks. 0 or a negative value removes the bound and the shrinking (since v26.11.1)

Long

1048576

queryScanReadAheadMaxRAM

Maximum memory (in MB) the scans of all the queries running in the JVM may hold read ahead at once, across every bucket of every database. queryBatchMaxBytes bounds the batch of one scan; this limit bounds the sum of all of them, so many concurrent scans cannot hold that many times the bound. Each scan starts with its full batch and reads less as the pool fills (a thirty-second of what is left of it), down to one record at a time. The limit is soft: a batch always holds at least one record, and its bytes are reserved after it is read, so scans that start together can each read a full batch before any of them reserves (the pool can overshoot by about the number of scans times queryBatchMaxBytes), and a single record larger than queryBatchMaxBytes is still read whole. The bytes go back to the pool when a batch is handed over, and, for a scan the application abandoned, when the garbage collector reclaims it. The pool is reported by the profiler as scanReadAheadReserved, scanReadAheadReservedPeak and scanReadAheadLimit. 0 or a negative value disables the pool. The low-ram profile sets it to 16 (since v26.11.1)

Long

200

schemaBulkDDLScript

Runs a SQL script of two or more statements that are ALL schema definition DDL (CREATE TYPE, CREATE PROPERTY, CREATE INDEX on a type the script creates, …​) as one schema session, so the schema file is written once for the whole script instead of once per statement and, under HA, the batch is replicated as one Raft entry. The database write lock is held for the whole script instead of once per statement; under HA a leader commit waits for the session at most ha.quorumTimeout before proceeding, so keep such scripts short. There is no rollback: if a statement fails, the ones before it stay applied and are published. A script that mixes in other statements (DML, REBUILD, TRUNCATE, REFRESH, COMPACT INDEX, materialized views, repartitioning, an index on a type that already existed) runs one session per statement regardless. Set to false to always use one session per statement. See reference/sql/sql-script.adoc#sql-script-ddl-batching and reference/storage.adoc#schema-change-cost. (Since v26.10.1)

Boolean

true

sql.letSubqueryCacheSize

Maximum number of distinct outer values whose result a per-record LET subquery (SELECT …​ LET $x = (SELECT …​)) remembers within one execution of the query. When many rows feed the subquery the same values (rows sharing one parent, office or category), it runs once per distinct value instead of once per row. The subquery is keyed on the outer values it actually reads, including a single field read as $parent.$current.<field>. Subqueries calling non-deterministic or user-defined functions, or that are not read-only, are never cached, and any change to the database drops the cache. Results larger than 1000 rows are not cached. 0 disables the cache (since v26.10.1)

Integer

128

sql.maxExpressionDepth

Maximum nesting depth of parentheses, brackets, braces (map and JSON literals) and CASE expressions allowed in a single SQL statement (since v26.10.1 also brackets, braces and CASE). A query past the limit is refused at parse time, which stops a deeply nested expression from tying up a worker thread for a very long time. Raise it for one database with ALTER DATABASE when a legitimately deep query needs it (the per-database value is actually read since v26.10.1; before that only the server-wide value had any effect)

Integer

200

cypher.maxExpressionDepth

The same limit for OpenCypher, covering nested parentheses, list and map literals, function arguments, pattern parentheses, CALL/EXISTS/COUNT/COLLECT subqueries (all counted together), and the length of a chain of AND/OR terms (per-database since v26.10.1, see sql.maxExpressionDepth)

Integer

200

cypher.maxClauses

Maximum number of clauses (MATCH, WITH, CREATE, …​) in one OpenCypher query or subquery body. A longer chain is refused at parse time, because it would otherwise exhaust the thread stack while the query runs. Each UNION branch counts on its own. A value below 1 falls back to the default (since v26.10.1)

Integer

500

sqlStatementCache

Maximum number of parsed statements to keep in cache. A statement must be hit twice to be protected from a burst of one-off query texts (for example queries that embed their values), so prefer parameters and raise this value if you generate many distinct queries

Integer

300

timeSeriesDecodedBlockCacheRAM

Memory budget, in MB and per shard, for keeping decoded TimeSeries data in memory so that reading the same compacted block twice decodes it once. This is what makes a repeated query - a dashboard polling the latest point of a host, for example - answer without re-reading and re-decoding the block it already read. Since the budget is per shard, the worst case for one type is this value times its SHARDS, and it is only reached by queries that actually touch that many distinct blocks. A shard sizes its cache when it is opened, so changing this on a running database applies to shards opened afterwards; reopen the database to apply it everywhere. Set to 0 to disable caching. Left at the default it scales with the JVM maximum heap (heap/512, never below 4MB)

Long

(auto)

txRetries

Number of retries in case of MVCC exception

Integer

3

txRetryDelay

Cap, in milliseconds, on the random wait before the next transaction retry: an exponential backoff with full jitter, drawn from 1 to min(txRetryDelay, txRetryDelayBase * 2^attempt). Helpful in case of high concurrency on the same pages (multi-thread insertion over the same bucket). Applied by the embedded transaction(), by COMMIT RETRY and, since v26.10.1, by the remote RemoteDatabase.transaction() too. Since v26.11.1 it is also applied between the replays of an asynchronous batch commit that hit a conflict. 0 disables the delay

Integer

100

txRetryDelayBase

Starting size, in milliseconds, of the transaction retry backoff window, doubled on each further attempt up to txRetryDelay

Integer

2

txStaleReadCheck

Refuses, with a retryable ConcurrentModificationException, a property write on a record read in the current transaction when another transaction committed a change to that record in between, so a value computed from the older read can never overwrite the concurrent change (a lost update under READ_COMMITTED). Adding or removing edges on a vertex is never refused. Only direct property assignment and removal is checked, not an in-place change to a list, map or embedded document got from the record. SQL UPDATE and Cypher SET/MERGE/REMOVE already compute their values from the latest data and are not affected. Set to false to restore the previous last-writer-wins behavior (since v26.10.1)

Boolean

true

txWAL

Uses the WAL

Boolean

true

txWalFiles

Number of concurrent files to use for tx log. 0 or a negative value = available cores, which is also the default

Integer

(machine dependent)

txWalFlush

Flushes the WAL on disk at commit time. It can be 0 = no flush, 1 = flush without metadata and 2 = full flush (fsync). In production server mode, this is automatically set to 1 if not explicitly configured. See concepts/transactions.adoc#wal-flush-durability

Integer

0

typeDefaultBuckets

Default number of buckets to create per type

Integer

1

Available Plugins

Name server.plugins-String

Gremlin

GremlinServer:com.arcadedb.server.gremlin.GremlinServerPlugin

gRPC

gRPC:com.arcadedb.server.grpc.GrpcServerPlugin

MongoDB

MongoDB:com.arcadedb.mongo.MongoDBProtocolPlugin

Postgres

Postgres:com.arcadedb.postgres.PostgresProtocolPlugin

Prometheus

Prometheus:com.arcadedb.metrics.prometheus.PrometheusMetricsPlugin

Redis

Redis:com.arcadedb.redis.RedisProtocolPlugin

gRPC

The gRPC server is implemented by the GrpcServerPlugin, which is bundled in the full distribution but not started by default. To enable it, register the plugin in server.plugins (see available plugins):

-Darcadedb.server.plugins=gRPC:com.arcadedb.server.grpc.GrpcServerPlugin

Once enabled, the server listens on port 50051 by default. Since v26.11.1 every grpc. setting below is a registered server setting, so it can be supplied in the server configuration file, as an environment variable or as a JVM system property (-Darcadedb.grpc.). Before that, only grpc.port was, and the others worked as system properties only: a grpc.tls.enabled written in the configuration file was ignored and the endpoint stayed in cleartext. An invalid grpc.mode now makes the server refuse to start instead of starting no listener. The server.plugins setting itself is a standard server setting and can be supplied the same ways.

Name Description Type Default Value

grpc.enabled

Start the gRPC server when the plugin is registered. Set to false to keep the plugin loaded but the listener stopped

Boolean

true

grpc.port

Port for the standard gRPC server. A registered server setting since v26.9.1 (so it is also resolved from environment variables and listed in the settings API), because HA reads it to advertise a peer’s gRPC endpoint - see the grpc field of arcadedb.ha.serverList

Integer

50051

grpc.host

Host/interface to bind to: every local address the name resolves to. Applies to the standard server only; the xDS server (mode xds or both) has no host setting and listens on every interface. Before 26.11.1 the setting was read but never applied

String

0.0.0.0

grpc.mode

Server mode: standard, xds, or both

String

standard

grpc.xds.port

Port for the xDS server (used when grpc.mode is xds or both)

Integer

50052

grpc.tls.enabled

Enable TLS for the gRPC server. Only true or false are accepted: any other value (for example yes) makes the server refuse to start instead of running without TLS

Boolean

false

grpc.tls.cert

Path to the TLS certificate chain file (required when grpc.tls.enabled=true)

String

(none)

grpc.tls.key

Path to the TLS private key file (required when grpc.tls.enabled=true)

String

(none)

grpc.maxMessageSize

Maximum inbound message size, in MB

Integer

100

grpc.reflection.enabled

Enable the gRPC server reflection service (used by tools such as grpcurl)

Boolean

true

grpc.health.enabled

Enable the standard gRPC health-checking service

Boolean

true

grpc.compression.enabled

Advertise support for message compression

Boolean

true

grpc.compression.force

Force compression on all outbound messages

Boolean

false

grpc.compression.type

Compression algorithm used when grpc.compression.force=true

String

gzip

In addition to the plugin-level keys above, the gRPC service honors four registered SERVER settings that bound result materialization and protect against limitless or slow clients pinning worker threads and exhausting heap: server.grpcQueryMaxResultRows, server.grpcTimeSeriesMaxResultRows, server.grpcStreamMaxMaterializedRows, and server.grpcStreamWriteTimeoutMs (see the SERVER settings table). Unlike the grpc.* keys, these are standard server settings and can be supplied as JVM system properties or environment variables.