# Configuration reference

> Every HotKV configuration directive with its hotkv.conf name, hotkv.toml key, type, default and whether CONFIG SET can change it.

URL: https://docs.hotkv.com/reference/configuration/


This page lists every setting an operator can give HotKV. For how to lay out a
configuration file and which settings matter first, see
[Configuration](https://docs.hotkv.com/operate/configuration/index.md).

## How settings are given

HotKV reads one configuration file, named on the command line. The extension
picks the format:

- **`hotkv.conf`**: one `directive value` per line, the format Redis uses.
  Values with spaces go in double or single quotes. `include <file>` reads
  another file in place of the line; a pattern such as `include conf.d/*.conf`
  reads every matching file in name order.
- **`hotkv.toml`**: the same settings as TOML tables and keys. The tables below
  give the TOML location of each directive. A few directives have no TOML key
  (marked "not available"); give those on the command line.

```sh
hotkv /etc/hotkv/hotkv.conf
hotkv -c /etc/hotkv/hotkv.toml
```

Any `hotkv.conf` directive can also be given on the command line as
`--directive value`, and the command line wins over the file:

```sh
hotkv /etc/hotkv/hotkv.conf --port 6380 --maxmemory 2gb --appendonly yes
```

A directive given alone on the command line means `yes` (`--appendonly`),
except `--save` alone, which turns automatic snapshots off. Settings with a
dot in their name (`replication.enabled`, `encryption.provider`, and the other
dotted sections) only work in the configuration file.

### Values

- **yes/no**: `yes` or `no` in `hotkv.conf`; `true` or `false` in TOML.
- **Memory sizes**: whole bytes, or a whole number with a unit: `k` (1000),
  `kb` (1024), `m`, `mb`, `g`, `gb`, in any case. `1.5gb` and `-1` are not
  sizes. In TOML, `maxmemory`, `hll_sparse_max_bytes`,
  `[persistence.aof] auto_rewrite_min_size` and the `[replication]` sizes take
  either a string (`maxmemory = "2gb"`) or a number of bytes; other sizes take
  a number of bytes.
- **Integers**: whole numbers only. `10abc`, `1.5` and leading zeros are
  refused.

### Mistakes and Redis settings

- A line in `hotkv.conf` that names no setting stops the start, with the file
  and line in the log. Set
  [`ignore-unknown-directives yes`](#ignore-unknown-directives) to log and
  skip such lines instead.
- A value a setting does not take is logged, and the setting keeps its
  default. On the command line an unknown setting or a bad value stops the
  start.
- Redis and Valkey settings HotKV has no use for (for example `io-threads`,
  `activedefrag`, the `lazyfree-*` settings and `unixsocket`) are accepted
  with a warning and have no effect, so an existing `redis.conf` starts as it
  is. Three Redis settings are acted on and are listed below:
  [`maxmemory-clients`](#maxmemory-clients),
  [`replica-full-sync-buffer-limit`](#replica-full-sync-buffer-limit) and
  [`tracking-table-max-keys`](#tracking-table-max-keys).
- A few Redis settings stop the start because ignoring them would be unsafe:
  `rename-command` (deny the command with an [ACL rule](https://docs.hotkv.com/operate/acl/index.md)
  instead), `user` (put users in the [`aclfile`](#aclfile)), `loadmodule`
  (HotKV does not load modules) and `sentinel`. `replicaof` / `slaveof` stop
  the start only on a cluster node, where replicas are made with
  [`CLUSTER REPLICATE`](https://docs.hotkv.com/commands/cluster-replicate/index.md); on a standalone node
  they make it a replica (see [Replication](#replication) below).

> **Caution**
> HotKV does not warn about misspelled keys in `hotkv.toml`, or about
> misspelled dotted keys (`replication.*`, `encryption.*`, ...) in `hotkv.conf`:
> they are ignored. Check `CONFIG GET` or the startup log after a change.

### Changing settings at runtime

The **CONFIG SET** column says whether [`CONFIG SET`](https://docs.hotkv.com/commands/config-set/index.md)
can change a directive on a running server:

- **Yes**: takes effect at once.
- **No**: read at startup only. Change the file and restart.
- **Protected**: refused unless
  [`enable-protected-configs`](#enable-protected-configs) allows it, because
  these directives name files the server writes.

[`CONFIG GET`](https://docs.hotkv.com/commands/config-get/index.md) reads the current values, and
[`CONFIG REWRITE`](https://docs.hotkv.com/commands/config-rewrite/index.md) writes the running values back
into the configuration file, keeping its comments and layout. When TLS is in
use, changing a `tls-*` certificate, key or cipher setting reloads TLS for new
connections without a restart.

## Network

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `bind` (TOML `[network] bind`; type addresses) | `127.0.0.1` | Yes | Addresses to listen on for plain-text clients, separated by spaces (up to 16). `*` means every IPv4 address, `::*` every IPv6 address, and a leading `-` marks an address that is skipped when it is not available on this host. |
| `port` (TOML `[network] port`; type integer, 0 to 65535) | `6379` | Yes | TCP port for plain-text clients. `0` disables the plain-text listener (for a TLS-only server, set [`tls-port`](#tls-port)). |
| `tcp-backlog` (TOML `[network] tcp_backlog`; type integer) | `511` | No | Length of the queue of connections waiting to be accepted. |
| `tcp-keepalive` (TOML `[network] tcp_keepalive`; type seconds) | `300` | Yes | Idle time before TCP keepalive probes are sent on client connections. `0` turns keepalive off. |

## TLS

See [TLS](https://docs.hotkv.com/operate/tls/index.md) for a walkthrough.

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `tls-port` (TOML `[tls] port`; type integer, 0 to 65535) | `0` | Yes | TCP port for TLS clients. `0` disables TLS for clients. TLS needs [`tls-cert-file`](#tls-cert-file) and [`tls-key-file`](#tls-key-file) as well. |
| `tls-bind` (TOML `[tls] bind`; type addresses) | `(empty: same as bind)` | No | Addresses for the TLS listener, in the same form as [`bind`](#bind). |
| `tls-cert-file` (TOML `[tls] cert_file`; type path) | `(empty)` | Yes | PEM certificate the server presents to clients (and to other nodes when it has no client certificate of its own). |
| `tls-key-file` (TOML `[tls] key_file`; type path) | `(empty)` | Yes | PEM private key for `tls-cert-file`. |
| `tls-key-file-pass` (TOML `[tls] key_file_pass`; type string) | `(empty)` | Yes | Passphrase for an encrypted `tls-key-file`. `CONFIG GET` shows it as `(hidden)`. |
| `tls-ca-cert-file` (TOML `[tls] ca_cert_file`; type path) | `(empty)` | Yes | PEM bundle of CA certificates used to verify client certificates and, for node links, the other node's certificate. |
| `tls-ca-cert-dir` (TOML `[tls] ca_cert_dir`; type path) | `(empty)` | Yes | Directory of CA certificates, used like `tls-ca-cert-file`. |
| `tls-auth-clients` (TOML `[tls] auth_clients`; type yes, no, optional) | `yes` | Yes | Whether TLS clients must present a certificate: `yes` requires one, `optional` verifies one when sent, `no` never asks. |
| `tls-auth-clients-user` (TOML `[tls] auth_clients_user`; type off, CN, URI) | `off` | Yes | Log a client in without a password as the ACL user named by its certificate: `CN` uses the common name, `URI` the first URI subject alternative name that is an enabled user. A name that is no enabled user leaves the client the default user. `off` turns this off. Applies to connections made after a change. |
| `tls-auto-reload-interval` (TOML `[tls] auto_reload_interval`; type seconds) | `0` | Yes | How often the node looks at its certificate, key, CA and DH parameter files, and reloads TLS when one changed, so a renewal only has to replace the files. `0` turns it off. See [Cluster over TLS](https://docs.hotkv.com/clustering/tls/index.md#7-renew-certificates). |
| `tls-protocols` (TOML `[tls] protocols`; type string) | `(empty)` | Yes | TLS versions to allow, for example `"TLSv1.2 TLSv1.3"`. Empty uses the TLS library's defaults. |
| `tls-ciphers` (TOML `[tls] ciphers`; type string) | `(empty)` | Yes | Cipher list for TLS 1.2 and earlier, in OpenSSL format. |
| `tls-ciphersuites` (TOML `[tls] ciphersuites`; type string) | `(empty)` | Yes | Cipher suites for TLS 1.3, in OpenSSL format. |
| `tls-dh-params-file` (TOML `[tls] dh_params_file`; type path) | `(empty)` | Yes | Diffie-Hellman parameters file for DHE ciphers. |
| `tls-prefer-server-ciphers` (TOML `[tls] prefer_server_ciphers`; type yes/no) | `yes` | Yes | Prefer the server's cipher order over the client's. |
| `tls-session-caching` (TOML `[tls] session_caching`; type yes/no) | `yes` | Yes | Cache TLS sessions so returning clients can resume them. |
| `tls-session-cache-size` (TOML `[tls] session_cache_size`; type integer) | `20480` | Yes | Number of TLS sessions to cache. `0` means no limit. |
| `tls-session-cache-timeout` (TOML `[tls] session_cache_timeout`; type seconds) | `300` | Yes | How long a cached TLS session can be resumed. |
| `tls-cluster` (TOML `[tls] cluster`; type yes/no) | `no` | Yes | Use mutual TLS on the cluster bus. Both ends present a certificate and verify the other against the CA; plain-text bus connections are refused. With it on, a node goes by its TLS port in the cluster and the bus port is that port plus 10000. See [Cluster over TLS](https://docs.hotkv.com/clustering/tls/index.md). |
| `tls-replication` (TOML `[tls] replication`; type yes/no) | `no` | No | Use mutual TLS on replication links, verified the same way as `tls-cluster`. |
| `tls-client-cert-file` (TOML `[tls] client_cert_file`; type path) | `(empty: uses tls-cert-file)` | Yes | Certificate this node presents on the cluster bus and replication links it opens. |
| `tls-client-key-file` (TOML `[tls] client_key_file`; type path) | `(empty: uses tls-key-file)` | Yes | Private key for `tls-client-cert-file`. |
| `tls-client-key-file-pass` (TOML `[tls] client_key_file_pass`; type string) | `(empty)` | Yes | Passphrase for an encrypted `tls-client-key-file`. `CONFIG GET` shows it as `(hidden)`. |
| `tls-expected-peer-name` (TOML `[tls] expected_peer_name`; type names, apart by spaces) | `(empty)` | Yes | Names, one of which the certificate of another node must carry (as a DNS name, or as the common name when it has none) on the links this node opens and the cluster bus connections it accepts. Empty checks only the CA's signature. Applies from the next connection. |

## General

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `daemonize` (TOML `[general] daemonize`; type yes/no) | `no` | No | Run in the background as a daemon. |
| `pidfile` (TOML `[general] pidfile`; type path) | `(empty)` | No | File to write the process ID to. A daemonized server writes one to a default path when this is empty. |
| `loglevel` (TOML `[general] loglevel`; type debug, verbose, notice, warning) | `notice` | Yes | How much the server logs. |
| `logfile` (TOML `[general] logfile`; type path) | `(empty: standard output)` | No | Log file. A relative path is inside [`dir`](#dir). |
| `databases` (TOML `[general] databases`; type integer, 1 to 128) | `16` | No | Number of databases (`SELECT 0` to `databases - 1`). A cluster node uses [`cluster-databases`](#cluster-databases) instead. |
| `shutdown-timeout` (TOML not available; type seconds) | `10` | Yes | How long a primary that is shutting down (`SHUTDOWN`, SIGTERM or SIGINT) holds its clients' writes and waits for every replica to acknowledge them before it exits. `0` does not wait. |
| `shutdown-on-sigterm` (TOML not available; type default, save, nosave, now, force, safe, failover) | `default` | Yes | The `SHUTDOWN` options a SIGTERM shuts the server down with, one or more words. `default` is the plain `SHUTDOWN`. |
| `shutdown-on-sigint` (TOML not available; type default, save, nosave, now, force, safe, failover) | `default` | Yes | The `SHUTDOWN` options a SIGINT shuts the server down with, in the same words as `shutdown-on-sigterm`. |
| `compat-redis-version` (TOML `[advanced] compat_redis_version`; type <major>.<minor>[.<patch>]) | `8.4.0` | Yes | The Redis version that `INFO` (`redis_version`), `HELLO` and scripts report. `redis-cli` 8.4 and later moves slots with `CLUSTER MIGRATION` when every node reports 8.4.0 or more. |
| `threads` (TOML `[threading] threads`; type integer) | `0 (one per CPU core)` | No | Number of worker threads that serve clients. |
| `ignore-unknown-directives` (TOML not available; type yes/no) | `no` | No | A HotKV setting. With `yes`, a line in `hotkv.conf` that names no known setting is logged and skipped instead of stopping the start. |

## Snapshots and AOF

See [Persistence](https://docs.hotkv.com/persistence/index.md) for how snapshots and the AOF work together.

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `save` (TOML `[[persistence.save]] seconds, changes`; type seconds changes pairs) | `3600 1 300 100 60 10000` | Yes | Snapshot save points: a background snapshot is taken when at least `changes` writes happened within `seconds`. Each `save` line adds points; `save ""` turns automatic snapshots off. In TOML, `save = []` turns them off. |
| `dbfilename` (TOML `[persistence] dbfilename`; type path) | `dump.hkv` | Protected | Snapshot file name, inside `dir`. |
| `dir` (TOML `[persistence] dir`; type path) | `./` | Protected | Working directory for snapshots, the AOF, and other files the server writes. |
| `stop-writes-on-bgsave-error` (TOML `[persistence] stop_writes_on_bgsave_error`; type yes/no) | `yes` | Yes | With save points configured, refuse writes with a `MISCONF` error after a background snapshot fails, until one succeeds. |
| `appendonly` (TOML `[persistence] appendonly`; type yes/no) | `no` | Yes | Log every write to the append-only file (AOF). Turning it on at runtime first writes the whole data set to the AOF. |
| `appendfilename` (TOML `[persistence] appendfilename`; type path) | `appendonly.hkv` | Protected | AOF file name, inside `dir`. |
| `appenddirname` (TOML `[persistence] appenddirname`; type path) | `appendonlydir` | No | Directory, inside `dir`, where Redis 7 and later keep their AOF. HotKV reads it when it has no AOF of its own yet, to start from Redis data. |
| `appendfsync` (TOML `[persistence] appendfsync`; type always, everysec, no) | `everysec` | Yes | When the AOF is flushed to disk: after every write, once a second, or when the operating system decides. |
| `no-appendfsync-on-rewrite` (TOML `[persistence.aof] no_appendfsync_on_rewrite`; type yes/no) | `no` | Yes | Skip AOF fsyncs while an AOF rewrite is running. |
| `auto-aof-rewrite-percentage` (TOML `[persistence.aof] auto_rewrite_percentage`; type integer) | `100` | Yes | Rewrite the AOF automatically once it has grown by this percentage since the last rewrite. `0` turns automatic rewrites off. |
| `auto-aof-rewrite-min-size` (TOML `[persistence.aof] auto_rewrite_min_size`; type memory size) | `64mb` | Yes | Smallest AOF size at which an automatic rewrite can start. |

## Replication

A standalone replica is set up with `replicaof <host> <port>` (the primary's
client port), or with `replication.enabled yes`, `replication.role replica`
and `replication.primary-addr`; in a cluster, with
[`CLUSTER REPLICATE`](https://docs.hotkv.com/commands/cluster-replicate/index.md). The Redis names
(`repl-*`, `masterauth`, `min-replicas-to-write`) are accepted too and win over
their `replication.*` counterparts when set. See
[Replication](https://docs.hotkv.com/operate/replication/index.md). The cluster and replication settings with
guidance are also on [Cluster configuration](https://docs.hotkv.com/clustering/configuration/index.md).

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `replicaof` (TOML not available; type host port; alias `slaveof`) | `(empty)` | No | Start this standalone node as a replica of the node at that host and client port. Not allowed on a cluster node, where replicas are made with `CLUSTER REPLICATE`. Change it at runtime with `REPLICAOF`, not `CONFIG SET`. `CONFIG GET` shows the primary as `host port`, and an empty string on a primary. |
| `replication.enabled` (TOML `[replication] enabled`; type yes/no) | `no` | No | Turn on replication for this node. |
| `replication.role` (TOML `[replication] role`; type primary, replica) | `primary` | No | Role of this node. |
| `replication.primary-addr` (TOML `[replication] primary_addr`; type host:port) | `(empty)` | No | On a replica, the primary's address as `host:port`: its client port, or its replication port when `replication.dedicated-port` is on. |
| `replication.dedicated-port` (TOML `[replication] dedicated_port`; type yes/no) | `no` | No | Also listen for replicas on the replication port (`replication.port`; a cluster node's client port plus 20000), and have this node's replicas connect there. Without it replicas connect to the primary's client port. |
| `replication.bind` (TOML `[replication] bind`; type string) | `0.0.0.0` | No | Address the replication port binds to. Used only with `replication.dedicated-port`. |
| `replication.port` (TOML `[replication] port`; type integer) | `6389` | No | The replication port, used only with `replication.dedicated-port`. In cluster mode the replication port is always the client port plus 20000 and this setting does not change it. |
| `replication.password` (TOML `[replication] password`; type string) | `(empty: masterauth, then requirepass)` | No | Shared secret the primary and replicas prove to each other. |
| `replication.sync-timeout` (TOML `[replication] sync_timeout`; type milliseconds; alias `replication.sync-timeout-ms`) | `5000` | No | Timeout for the replication handshake and sync steps. Also accepted as `replication.sync-timeout-ms`. |
| `replication.heartbeat-interval` (TOML `[replication] heartbeat_interval`; type milliseconds; alias `replication.heartbeat-interval-ms`) | `1000` | No | Interval between heartbeats on a replication link. Also accepted as `replication.heartbeat-interval-ms`. [`repl-ping-replica-period`](#repl-ping-replica-period) wins when set. |
| `replication.backlog-size` (TOML `[replication] backlog_size`; type memory size) | `64mb` | No | Bytes of recent writes kept so a replica that reconnects can catch up without a full sync. The backlog counts toward [`maxmemory`](https://docs.hotkv.com/reference/configuration/index.md#maxmemory) as it fills. When `maxmemory` is set at start and no size is given, the default is a sixteenth of `maxmemory` if that is less than 64mb. [`repl-backlog-size`](#repl-backlog-size) wins when set. |
| `replication.full-sync-buffer-limit` (TOML `[replication] full_sync_buffer_limit`; type memory size) | `1gb` | No | Bytes of writes buffered for a replica while its full sync is under way and the writes made meanwhile are being sent to it. `0` uses [`replication.replica-buffer-limit`](#replication.replica-buffer-limit). |
| `replication.apply-threads` (TOML `[replication] apply_threads`; type integer, or auto) | `auto` | No | How much parallelism a replica uses to apply the writes of its primary. `auto` follows the server's `threads` setting. `0` turns it off. |
| `replication.replica-buffer-limit` (TOML `[replication] replica_buffer_limit`; type memory size) | `256mb` | No | Bytes of writes buffered for a replica that has not received them yet. `0` means no limit. The replica class of [`client-output-buffer-limit`](https://docs.hotkv.com/reference/configuration/index.md#client-output-buffer-limit) wins when given. |
| `replica-read-only` (TOML `[replication] read_only`; type yes/no; alias `slave-read-only`) | `yes` | Yes | Refuse writes from clients on a replica. |
| `repl-backlog-size` (TOML not available; type memory size) | `(not set: replication.backlog-size)` | Yes | Redis name for the replication backlog size, at least 16kb. When set it overrides `replication.backlog-size`, and the default above does not apply. `CONFIG SET` resizes the backlog at once. The backlog counts toward [`maxmemory`](https://docs.hotkv.com/reference/configuration/index.md#maxmemory) up to this size. |
| `replica-full-sync-buffer-limit` (TOML not available; type memory size) | `0 (keep none)` | Yes | Used by the target of a Redis 8 style atomic slot migration (`CLUSTER MIGRATION IMPORT`): how many bytes of the writes the source makes while it copies the slots the target keeps for itself, instead of the source holding them until the copy is out. A write that crosses the limit is kept whole. See [Scaling a cluster](https://docs.hotkv.com/clustering/scaling/index.md#memory-on-the-target). It does not change how a replica syncs from its primary: that is [`replication.full-sync-buffer-limit`](#replication.full-sync-buffer-limit). |
| `repl-timeout` (TOML not available; type seconds) | `(not set: five heartbeats, at least 1 s)` | Yes | How long a replication link may stay silent before it is treated as dead. |
| `repl-ping-replica-period` (TOML not available; type seconds; alias `repl-ping-slave-period`) | `(not set: replication.heartbeat-interval)` | Yes | Redis name for the heartbeat interval. When set it overrides `replication.heartbeat-interval`. |
| `repl-diskless-load` (TOML not available; type disabled, on-empty-db, swapdb, flushdb, flush-before-load) | `disabled` | Yes | Accepted and reported for compatibility. A full sync always replaces the replica's data as it arrives, whatever this says. |
| `masterauth` (TOML not available; type string; alias `primaryauth`) | `(empty)` | Yes | The password a replica logs in with (`AUTH`) at its primary's client port, and the replication secret when `replication.password` is not set. `CONFIG GET` shows it as `(hidden)`. |
| `masteruser` (TOML not available; type string; alias `primaryuser`) | `(empty)` | Yes | The ACL user a replica logs in as with `masterauth` at its primary's client port. That user must be allowed `PSYNC`. |
| `min-replicas-to-write` (TOML not available; type integer; alias `min-slaves-to-write`) | `0` | Yes | A primary refuses writes with `NOREPLICAS` while fewer than this many replicas have acknowledged within `min-replicas-max-lag` seconds. `0` turns it off. |
| `min-replicas-max-lag` (TOML not available; type seconds; alias `min-slaves-max-lag`) | `10` | Yes | How recently a replica must have acknowledged to count for `min-replicas-to-write`. `0` turns the rule off. |
| `repl-backlog-ttl` (TOML not available; type seconds) | `3600` | Yes | How long a primary with no replica keeps its replication backlog before dropping it. `0` keeps it. A replica that comes later gets a full sync. |
| `propagation-error-behavior` (TOML not available; type ignore, panic, panic-on-replicas) | `ignore` | Yes | What happens when a write that came from the primary (or the AOF) fails on this node. It is always logged. `panic` stops the process, `panic-on-replicas` stops a replica only. |

## Cluster

See [Clustering](https://docs.hotkv.com/clustering/index.md) and
[Cluster configuration](https://docs.hotkv.com/clustering/configuration/index.md).

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `cluster-enabled` (TOML `[cluster] enabled`; type yes/no) | `no` | No | Run as a cluster node. |
| `cluster-config-file` (TOML `[cluster] config_file`; type path) | `nodes.conf` | No | File where the node keeps its view of the cluster. The node writes it; do not edit it. |
| `cluster-port` (TOML `[cluster] port`; type integer) | `0 (port + 10000)` | No | Port of the cluster bus. |
| `cluster-node-timeout` (TOML `[cluster] node_timeout`; type milliseconds) | `15000` | Yes | How long a node may be unreachable before it is flagged as failing. |
| `cluster-announce-ip` (TOML `[cluster] announce_ip`; type IP address or name) | `(empty)` | Yes | The address this node gives the other nodes (and clients, unless `cluster-announce-client-ipv4` is set), when it differs from the one they see (NAT, containers). An IP address, or a name the other nodes resolve. Empty gives back the first `bind` address. |
| `cluster-announce-port` (TOML `[cluster] announce_port`; type integer) | `0 (the client port)` | Yes | Client port this node announces. |
| `cluster-announce-tls-port` (TOML `[cluster] announce_tls_port`; type integer) | `0 (the TLS port)` | Yes | TLS client port this node announces. |
| `cluster-announce-bus-port` (TOML `[cluster] announce_bus_port`; type integer) | `0 (the bus port)` | Yes | Cluster bus port this node announces. |
| `cluster-announce-client-ipv4` (TOML `[cluster] announce_client_ipv4`; type IPv4 address) | `(empty)` | Yes | The address clients connected over IPv4 are given for this node in `CLUSTER` replies and redirects, in place of its own. Nodes keep using the real address among themselves. For a NAT or a load balancer. |
| `cluster-announce-client-ipv6` (TOML `[cluster] announce_client_ipv6`; type IPv6 address) | `(empty)` | Yes | The same as `cluster-announce-client-ipv4`, for clients connected over IPv6. |
| `cluster-announce-client-port` (TOML `[cluster] announce_client_port`; type integer) | `0 (the client port)` | Yes | The plain client port clients are given for this node. `0` is the port it listens on. |
| `cluster-announce-client-tls-port` (TOML `[cluster] announce_client_tls_port`; type integer) | `0 (the TLS port)` | Yes | The TLS client port clients are given for this node. `0` is the TLS port it listens on. |
| `availability-zone` (TOML `[general] availability_zone`; type string) | `(empty)` | Yes | A name for where this node runs, given to clients by `HELLO` and `INFO` and, in a cluster, to the other nodes for `CLUSTER SLOTS` and `CLUSTER SHARDS`. Works on any node, cluster or not. At most 255 characters. |
| `cluster-announce-hostname` (TOML `[cluster] announce_hostname`; type string) | `(empty)` | Yes | Host name clients may be given for this node (see `cluster-preferred-endpoint-type`). Letters, digits, `-` and `.`, shorter than 256 characters. |
| `cluster-announce-human-nodename` (TOML `[cluster] announce_human_nodename`; type string) | `(empty)` | Yes | Friendly node name shown in other nodes' logs. |
| `cluster-preferred-endpoint-type` (TOML `[cluster] preferred_endpoint_type`; type ip, hostname, unknown-endpoint) | `ip` | Yes | What clients are given as a node's endpoint in redirects and `CLUSTER SLOTS` / `CLUSTER SHARDS`. |
| `cluster-require-full-coverage` (TOML `[cluster] require_full_coverage`; type yes/no) | `yes` | Yes | Stop serving when any hash slot is not covered by a node. |
| `cluster-allow-reads-when-down` (TOML `[cluster] allow_reads_when_down`; type yes/no) | `no` | Yes | Keep serving reads while the cluster is down. |
| `cluster-allow-pubsubshard-when-down` (TOML `[cluster] allow_pubsubshard_when_down`; type yes/no) | `yes` | Yes | Keep serving sharded pub/sub while the cluster is down. |
| `cluster-allow-replica-migration` (TOML `[cluster] allow_replica_migration`; type yes/no) | `yes` | Yes | Let spare replicas move to primaries that have none. |
| `cluster-migration-barrier` (TOML `[cluster] migration_barrier`; type integer) | `1` | Yes | Replicas a primary keeps before one of them may migrate to an orphaned primary. |
| `cluster-replica-validity-factor` (TOML `[cluster] replica_validity_factor`; type integer; alias `cluster-slave-validity-factor`) | `10` | Yes | A replica whose data is older than this limit does not try to fail over: the node timeout times this factor, plus the replication heartbeat period ([`repl-ping-replica-period`](#repl-ping-replica-period), 10 seconds unless set). `0` turns off the age check only; a replica that never finished a sync never fails over by itself. |
| `cluster-replica-no-failover` (TOML `[cluster] replica_no_failover`; type yes/no; alias `cluster-slave-no-failover`) | `no` | Yes | Never start an automatic failover from this replica. `CLUSTER FAILOVER` still works. |
| `cluster-link-sendbuf-limit` (TOML `[cluster] link_sendbuf_limit`; type memory size) | `256mb` | Yes | Unsent bytes a cluster bus link may hold before it is dropped. `0` means no limit. |
| `cluster-blacklist-ttl` (TOML `[cluster] blacklist_ttl`; type seconds) | `60` | Yes | How long a node removed with `CLUSTER FORGET` stays out: what other nodes say about it is ignored, so every node can be told to forget it. `0` keeps it out for no time. |
| `cluster-config-save-behavior` (TOML `[cluster] config_save_behavior`; type sync, best-effort) | `sync` | Yes | What a node does when it cannot write its cluster config file: `sync` exits, `best-effort` keeps serving, tries again and sends no failover vote meanwhile. |
| `cluster-bus-port-protected-mode` (TOML `[cluster] bus_port_protected_mode`; type yes/no) | `no` | Yes | With `yes` a cluster node refuses to start, and refuses `CONFIG SET tls-cluster no`, without `tls-cluster`, since only TLS tells a node who is at the other end of a bus link. With `no` it starts and logs a warning. See [Cluster over TLS](https://docs.hotkv.com/clustering/tls/index.md#bus-protection). |
| `cluster-manual-failover-timeout` (TOML `[cluster] manual_failover_timeout`; type milliseconds) | `5000` | Yes | Time `CLUSTER FAILOVER` has to win its election. The primary holds writes for the same time. A `CLUSTER MIGRATESLOTS` holds writes for at most twice this. |
| `cluster-slot-migration-log-max-len` (TOML `[cluster] slot_migration_log_max_len`; type integer) | `1000` | Yes | Finished atomic slot migrations `CLUSTER GETSLOTMIGRATIONS` keeps. |
| `slot-migration-max-failover-repl-bytes` (TOML `[cluster] slot_migration_max_failover_repl_bytes`; type bytes, or -1) | `0` | Yes | For `CLUSTER MIGRATESLOTS`: how much a source may still have to send to the target when it pauses writes to hand the slots over. `-1` allows any amount. |
| `cluster-slot-migration-handoff-max-lag-bytes` (TOML `[cluster] slot_migration_handoff_max_lag_bytes`; type memory size) | `1mb` | Yes | For `CLUSTER MIGRATION`: the source pauses writes once the target is within this many bytes of the stream. |
| `cluster-slot-migration-write-pause-timeout` (TOML `[cluster] slot_migration_write_pause_timeout`; type milliseconds) | `10000` | Yes | For `CLUSTER MIGRATION`: how long the source holds client writes waiting for the target to take the slots. Past it the task fails. |
| `cluster-slot-migration-sync-buffer-drain-timeout` (TOML `[cluster] slot_migration_sync_buffer_drain_timeout`; type milliseconds) | `60000` | Yes | For `CLUSTER MIGRATION`: how long a source waits, once asked to pause, for the target to catch up enough. Past it the task fails. Shown by `CONFIG GET` only by its exact name. |
| `cluster-slot-migration-max-archived-tasks` (TOML `[cluster] slot_migration_max_archived_tasks`; type integer) | `32` | Yes | Finished tasks `CLUSTER MIGRATION STATUS` keeps. Shown by `CONFIG GET` only by its exact name. |
| `cluster-slot-stats-enabled` (TOML `[cluster] slot_stats_enabled`; type no, yes, or cpu net mem) | `no` | Yes | What `CLUSTER SLOT-STATS` counts besides keys: `yes` for all, or any of `cpu`, `net`, `mem`. Memory counting cannot be turned on at runtime. |
| `cluster-databases` (TOML `[cluster] databases`; type integer, 1 to 128) | `1` | No | Number of databases of a cluster node (`databases` is the number for a standalone server). With `1`, `SELECT` of another database, `MOVE` and `COPY ... DB` are refused. Fixed at startup. |

## Security and ACL

See [Security](https://docs.hotkv.com/security/index.md) and [ACL](https://docs.hotkv.com/operate/acl/index.md).

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `protected-mode` (TOML `[network] protected_mode`; type yes/no) | `yes` | Yes | While the default user has no password, serve only clients on the loopback interface; others get a `DENIED` error. |
| `requirepass` (TOML `[security] requirepass`; type string) | `(empty)` | Yes | Password of the `default` user. `CONFIG GET` shows it as `(hidden)`. |
| `aclfile` (TOML `[security] aclfile`; type path) | `(empty)` | No | ACL file to load users from and save them to with `ACL LOAD` / `ACL SAVE`. Empty disables the file. |
| `acl-pubsub-default` (TOML `[security] acl_pubsub_default`; type resetchannels, allchannels) | `resetchannels` | Yes | Channels a new ACL user may use: none until granted (`resetchannels`) or all (`allchannels`). |
| `acllog-max-len` (TOML `[security] acllog_max_len`; type integer) | `128` | Yes | Entries kept by `ACL LOG`. |
| `enable-protected-configs` (TOML `[security] enable_protected_configs`; type no, yes, local) | `no` | No | Whether `CONFIG SET` may change `dir`, `dbfilename` and `appendfilename`: never, always, or only from a loopback connection. |
| `enable-debug-command` (TOML `[security] enable_debug_command`; type no, yes, local) | `no` | No | Whether the `DEBUG` command can be used: never, always, or only from a loopback connection. |

## Memory

See [Memory and eviction](https://docs.hotkv.com/operate/memory-and-eviction/index.md).

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `maxmemory` (TOML `[memory] maxmemory`; type memory size) | `0 (no limit)` | Yes | Memory limit for data. When it is reached, `maxmemory-policy` decides what happens. |
| `maxmemory-policy` (TOML `[memory] maxmemory_policy`; type noeviction, allkeys-lru, allkeys-lfu, allkeys-random, volatile-lru, volatile-lfu, volatile-random, volatile-ttl) | `noeviction` | Yes | What to do at `maxmemory`: refuse writes with an `OOM` error (`noeviction`) or evict keys. |
| `maxmemory-clients` (TOML not available; type bytes, or a percentage of maxmemory such as 10%) | `0 (no limit)` | Yes | The most memory all clients may hold together: their pending input, queued transactions, watched keys, subscriptions, unsent replies and the prefixes of `CLIENT TRACKING ... BCAST`. Past it the clients that hold the most are closed, one after the other, until the rest fit. A percentage is a share of [`maxmemory`](#maxmemory) and means no limit while `maxmemory` is `0`. A limit under 128kb is raised to 128kb. [`CLIENT NO-EVICT`](https://docs.hotkv.com/commands/client-no-evict/index.md) exempts a client. See [Client memory](https://docs.hotkv.com/operate/memory-and-eviction/index.md#client-memory). |
| `maxmemory-samples` (TOML `[memory] maxmemory_samples`; type integer, 1 to 64) | `5` | Yes | Keys sampled per eviction. More samples evict more precisely at more CPU cost. |
| `lfu-log-factor` (TOML `[memory] lfu_log_factor`; type integer) | `10` | Yes | How slowly a key's access frequency counter rises under the LFU policies. |
| `lfu-decay-time` (TOML `[memory] lfu_decay_time`; type minutes) | `1` | Yes | Minutes for a key's LFU counter to drop by one. `0` means it never decays. |
| `compression-enabled` (TOML `[compression] enabled`; type yes/no) | `no` | Yes | Compress string values transparently. |
| `compression-threshold` (TOML `[compression] threshold`; type bytes) | `512` | Yes | Smallest string value that is compressed. |
| `close-on-oom` (TOML `[advanced] close_on_oom`; type yes/no) | `no` | Yes | Accepted and reported, but has no effect in this release. |

## Clients

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `maxclients` (TOML `[network] maxclients`; type integer, 1 to 1000000) | `10000` | Yes | Most clients connected at once. |
| `timeout` (TOML `[network] timeout`; type seconds) | `0` | Yes | Accepted and reported, but idle client connections are not closed in this release. |
| `client-query-buffer-limit` (TOML not available; type memory size, at least 1mb) | `1gb` | Yes | A client whose input waiting to run grows past this is disconnected. A client that has not authenticated yet is held to 1 MB. |
| `proto-max-bulk-len` (TOML not available; type memory size, 1mb to 4294967295 bytes) | `512mb` | Yes | Longest string a client may send, and longest string a command may build (`APPEND`, `SETRANGE`, bit offsets). |
| `tracking-table-max-keys` (TOML not available; type integer) | `1000000` | Yes | The most keys the server remembers for clients that use [`CLIENT TRACKING`](https://docs.hotkv.com/commands/client-tracking/index.md). `0` means no limit. Past it the server forgets keys and tells the clients that had read them, as if the keys had changed. A change by `CONFIG SET` applies at once. See [Client-side caching](https://docs.hotkv.com/develop/client-side-caching/index.md#how-many-keys-the-server-remembers). |
| `client-output-buffer-limit` (TOML not available; type class hard soft seconds) | `normal 0 0 0 replica 256mb 64mb 60 pubsub 32mb 8mb 60` | Yes | Per client class (`normal`, `replica`, `pubsub`): a client whose unsent output reaches `hard` bytes, or stays above `soft` for `seconds`, is disconnected. `0` means no limit. |

## Data type encodings

These settings exist so that tools and tests written for Redis find them.
HotKV stores values its own way, so apart from the stream node sizes and
`hll-sparse-max-bytes` they only decide what
[`OBJECT ENCODING`](https://docs.hotkv.com/commands/object-encoding/index.md) reports.

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `hash-max-listpack-entries` (TOML `[encoding] hash_max_listpack_entries`; type integer; alias `hash-max-ziplist-entries`) | `512` | Yes | Size limit Redis uses to choose a compact encoding. HotKV stores values its own way; this only decides what `OBJECT ENCODING` reports. |
| `hash-max-listpack-value` (TOML `[encoding] hash_max_listpack_value`; type memory size; alias `hash-max-ziplist-value`) | `64` | Yes | Size limit Redis uses to choose a compact encoding. HotKV stores values its own way; this only decides what `OBJECT ENCODING` reports. |
| `set-max-intset-entries` (TOML `[encoding] set_max_intset_entries`; type integer) | `512` | Yes | Size limit Redis uses to choose a compact encoding. HotKV stores values its own way; this only decides what `OBJECT ENCODING` reports. |
| `set-max-listpack-entries` (TOML `[encoding] set_max_listpack_entries`; type integer) | `128` | Yes | Size limit Redis uses to choose a compact encoding. HotKV stores values its own way; this only decides what `OBJECT ENCODING` reports. |
| `set-max-listpack-value` (TOML `[encoding] set_max_listpack_value`; type integer) | `64` | Yes | Size limit Redis uses to choose a compact encoding. HotKV stores values its own way; this only decides what `OBJECT ENCODING` reports. |
| `zset-max-listpack-entries` (TOML `[encoding] zset_max_listpack_entries`; type integer; alias `zset-max-ziplist-entries`) | `128` | Yes | Size limit Redis uses to choose a compact encoding. HotKV stores values its own way; this only decides what `OBJECT ENCODING` reports. |
| `zset-max-listpack-value` (TOML `[encoding] zset_max_listpack_value`; type memory size; alias `zset-max-ziplist-value`) | `64` | Yes | Size limit Redis uses to choose a compact encoding. HotKV stores values its own way; this only decides what `OBJECT ENCODING` reports. |
| `list-max-listpack-size` (TOML `[encoding] list_max_listpack_size`; type integer; alias `list-max-ziplist-size`) | `-2` | Yes | Positive: elements per node; `-1` to `-5`: 4 KB to 64 KB per node. Decides what `OBJECT ENCODING` reports for lists. |
| `list-compress-depth` (TOML `[encoding] list_compress_depth`; type integer) | `0` | Yes | Accepted and reported for compatibility; it does not change how lists are stored. |
| `stream-node-max-bytes` (TOML `[encoding] stream_node_max_bytes`; type memory size) | `4kb` | Yes | Size of a stream node. Approximate (`~`) trims of `XADD` and `XTRIM` remove whole nodes. |
| `stream-node-max-entries` (TOML `[encoding] stream_node_max_entries`; type integer) | `100` | Yes | Entries per stream node, used with `stream-node-max-bytes`. |
| `hll-sparse-max-bytes` (TOML `[memory] hll_sparse_max_bytes`; type memory size) | `3000` | Yes | Size past which a HyperLogLog switches from the sparse to the dense (12 KB) representation. |

## Slow log, latency and monitoring

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `slowlog-log-slower-than` (TOML `[slowlog] log_slower_than`; type microseconds; alias `commandlog-execution-slower-than`) | `10000` | Yes | Commands that run longer than this are recorded in the slow log. `0` records every command, a negative value none. |
| `slowlog-max-len` (TOML `[slowlog] max_len`; type integer; alias `commandlog-slow-execution-max-len`) | `128` | Yes | Entries kept in the slow log. |
| `latency-monitor-threshold` (TOML `[latency] monitor_threshold`; type milliseconds) | `0` | Yes | Latency spikes of at least this many milliseconds are recorded for the `LATENCY` command. `0` turns the monitor off. |
| `latency-tracking` (TOML `[latency] tracking`; type yes/no) | `yes` | Yes | Track each command's latency distribution for `INFO latencystats` and `LATENCY HISTOGRAM`. |
| `latency-tracking-info-percentiles` (TOML `[latency] info_percentiles`; type numbers 0 to 100) | `50 99 99.9` | Yes | Percentiles `INFO latencystats` reports. |
| `hotkey-tracking` (TOML `[hotkeys] tracking`; type yes/no) | `no` | Yes | Track the most accessed keys for the `HOTKEYS` command. |
| `hotkey-max-tracked` (TOML `[hotkeys] max_tracked`; type integer) | `10000` | Yes | Accepted and reported, but has no effect in this release. |
| `metrics-port` (TOML `[metrics] port`; type integer) | `0 (off)` | No | Port of the Prometheus `/metrics` endpoint, which listens on 127.0.0.1 only. |

## Lua scripts and functions

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `busy-reply-threshold` (TOML `[scripting] busy_reply_threshold`; type milliseconds; alias `lua-time-limit`) | `5000` | Yes | Once a script or function has run this long, other clients get a `BUSY` error until it ends or is killed with `SCRIPT KILL` / `FUNCTION KILL`. |

## Keyspace notifications

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `notify-keyspace-events` (TOML `[notifications] keyspace_events`; type flags) | `(empty)` | Yes | Which keyspace notifications to publish, as class letters (`K`, `E`, `g`, `$`, `l`, `s`, `h`, `z`, `x`, `e`, `t`, `m`, `d`, `n`, `A`). Empty turns notifications off. See [keyspace notifications](https://docs.hotkv.com/develop/keyspace-notifications/index.md). |

## Background tasks

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `hz` (TOML `[advanced] hz`; type integer) | `10` | Yes | Frequency of the server's background tasks, such as expiring keys. `CONFIG SET` keeps it between 1 and 500. |
| `active-expire-effort` (TOML `[advanced] active_expire_effort`; type integer, 1 to 10) | `1` | Yes | How much effort the background sweep spends removing expired keys. |

## License

On-Premise installations read their license from this file. You can also
install a license at runtime with [`LICENSE.SET`](https://docs.hotkv.com/commands/license-set/index.md).

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `license-path` (TOML `[enterprise] license_path`; type path) | `(empty)` | No | Path of the On-Premise license file. See [`LICENSE.INFO`](https://docs.hotkv.com/commands/license-info/index.md). |

## Encryption at rest

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `encryption.enabled` (TOML `[encryption] enabled`; type yes/no) | `no` | No | Encrypt snapshots and the AOF on disk. |
| `encryption.provider` (TOML `[encryption] provider`; type local, aws-kms, azure-keyvault, vault, gcp-kms) | `local` | No | Where the encryption key comes from. |
| `encryption.key-file` (TOML `[encryption] key_path`; type path) | `(empty)` | No | Key file for the `local` provider. |
| `encryption.kms-key-id` (TOML `[encryption] kms_key_id`; type string) | `(empty)` | No | AWS KMS key ARN for `aws-kms`. |
| `encryption.vault-path` (TOML `[encryption] vault_path`; type string) | `(empty)` | No | HashiCorp Vault secret path for `vault`. |
| `encryption.azure-vault-url` (TOML `[encryption] azure_vault_url`; type string) | `(empty)` | No | Azure Key Vault URL for `azure-keyvault`. |
| `encryption.azure-key-name` (TOML `[encryption] azure_key_name`; type string) | `(empty)` | No | Azure Key Vault key name for `azure-keyvault`. |
| `encryption.gcp-project` (TOML `[encryption] gcp_project`; type string) | `(empty)` | No | Google Cloud project for `gcp-kms`. |
| `encryption.gcp-location` (TOML `[encryption] gcp_location`; type string) | `global` | No | Cloud KMS location for `gcp-kms`. |
| `encryption.gcp-key-ring` (TOML `[encryption] gcp_key_ring`; type string) | `(empty)` | No | Cloud KMS key ring for `gcp-kms`. |
| `encryption.gcp-crypto-key` (TOML `[encryption] gcp_crypto_key`; type string) | `(empty)` | No | Cloud KMS key name for `gcp-kms`. |

> **Note**
> The `aws-kms`, `azure-keyvault`, `gcp-kms` and `vault` providers are only
> available in builds that include the matching cloud integration. When the
> provider cannot deliver a key at startup, the server logs an error.

## Audit log

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `audit.enabled` (TOML `[audit] enabled`; type yes/no) | `no` | No | Write a tamper-evident audit log of commands. |
| `audit.file` (TOML `[audit] file`; type path) | `audit.hkv.log` | No | Audit log file. |
| `audit.max-size` (TOML `[audit] max_size`; type bytes) | `104857600 (100 MB)` | No | Size at which the audit log is rotated. `0` means no size limit. |
| `audit.retention-days` (TOML `[audit] retention_days`; type integer) | `90` | No | Days rotated audit logs are kept. |
| `audit.export-format` (TOML `[audit] format`; type jsonl, csv, cef) | `jsonl` | No | Format of exported and shipped entries. |
| `audit.ship-url` (TOML `[audit] ship_url`; type string) | `(empty)` | No | HTTP endpoint new audit entries are posted to. Empty turns shipping off. |
| `audit.exclude-commands` (TOML `[audit] exclude_commands`; type list) | `(empty)` | No | Commands not to audit (comma-separated in `hotkv.conf`, an array in TOML). |
| `audit.exclude-patterns` (TOML `[audit] exclude_patterns`; type list) | `(empty)` | No | Key patterns not to audit (comma-separated in `hotkv.conf`, an array in TOML). |

## Roles and single sign-on

Logins through an LDAP directory or an OpenID Connect provider, with the
`enterprise-iam` license feature. How they work, and how to set them up, is in
[Roles and single sign-on](https://docs.hotkv.com/operate/iam/index.md). In `hotkv.toml` the settings are
under `[iam]`, `[iam.ldap]` and `[iam.oidc]`.

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `iam.auth-threads` (TOML `[iam] auth_threads`; type integer) | `2` | No | Threads that ask a directory or an identity provider whether a login is right, so a slow one never holds a thread that serves clients. |
| `iam.auth-queue` (TOML `[iam] auth_queue`; type integer) | `64` | No | Logins that may wait for one of those threads. More are told `BUSY`. |
| `iam.max-login-failures` (TOML `[iam] max_login_failures`; type integer) | `10` | No | Failed `IAM.AUTH` from one address in a minute, after which that address is turned away for the rest of the minute. `0` means no limit. |

### LDAP

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `iam.ldap.enabled` (TOML `[iam.ldap] enabled`; type yes/no) | `no` | No | Turn LDAP login on (`AUTH user password` for a name the ACL does not have, and `IAM.AUTH ldap`). |
| `iam.ldap.url` (TOML `[iam.ldap] url`; type string) | `(empty)` | No | `ldap://host[:389]` (upgraded to TLS with STARTTLS before any password is sent) or `ldaps://host[:636]`. |
| `iam.ldap.bind-dn` (TOML `[iam.ldap] bind_dn`; type string) | `(empty)` | No | The service account that searches for the user. Empty means an anonymous search, which many directories refuse. |
| `iam.ldap.bind-password` (TOML `[iam.ldap] bind_password`; type string) | `(empty)` | No | Password of `iam.ldap.bind-dn`. |
| `iam.ldap.search-base` (TOML `[iam.ldap] search_base`; type string) | `(empty)` | No | Where users are searched for, in the whole subtree below it. |
| `iam.ldap.user-filter` (TOML `[iam.ldap] user_filter`; type string) | `(uid={username})` | No | The search that finds one user. `{username}` is the login name, escaped. For Active Directory use `(sAMAccountName={username})`. |
| `iam.ldap.user-dn-template` (TOML `[iam.ldap] user_dn_template`; type string) | `(empty)` | No | Instead of a search, the DN of every user, such as `uid={username},ou=people,dc=example,dc=com` (`{username}` is escaped as a DN value). No service account is needed. |
| `iam.ldap.group-attribute` (TOML `[iam.ldap] group_attribute`; type string) | `memberOf` | No | The attribute of the user's entry that lists their groups (`memberOf` in Active Directory and OpenLDAP with the memberof overlay). Empty means none. |
| `iam.ldap.group-search-base` (TOML `[iam.ldap] group_search_base`; type string) | `(empty)` | No | For a directory with no group attribute: search below this base for the groups that list the user. Empty turns the group search off. |
| `iam.ldap.group-filter` (TOML `[iam.ldap] group_filter`; type string) | `(member={dn})` | No | The group search. `{dn}` is the user's DN, escaped. |
| `iam.ldap.group-name-attribute` (TOML `[iam.ldap] group_name_attribute`; type string) | `cn` | No | The attribute that names a group found by the group search. |
| `iam.ldap.start-tls` (TOML `[iam.ldap] start_tls`; type yes/no) | `yes` | No | Upgrade `ldap://` to TLS before any password is sent. `no` sends passwords in the clear. `ldaps://` is TLS from the first byte either way. |
| `iam.ldap.tls-verify` (TOML `[iam.ldap] tls_verify`; type yes/no) | `yes` | No | Check the directory's certificate against `iam.ldap.ca-file` and the host in the URL. |
| `iam.ldap.ca-file` (TOML `[iam.ldap] ca_file`; type path) | `(empty)` | No | Certificate authorities that vouch for the directory (PEM). Empty means the system's. |
| `iam.ldap.timeout-ms` (TOML `[iam.ldap] timeout_ms`; type milliseconds) | `5000` | No | Time allowed for a whole login: connecting, TLS and every reply. |
| `iam.ldap.cache-ttl` (TOML `[iam.ldap] cache_ttl`; type seconds) | `300` | No | How long a password the directory accepted is remembered. `0` means every login asks the directory. A changed password or group applies after at most this long. |

### OpenID Connect

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `iam.oidc.enabled` (TOML `[iam.oidc] enabled`; type yes/no) | `no` | No | Turn OpenID Connect login on (`IAM.AUTH oidc`). |
| `iam.oidc.issuer` (TOML `[iam.oidc] issuer`; type string) | `(empty)` | No | The `iss` a token must have, exactly as the provider writes it. |
| `iam.oidc.audience` (TOML `[iam.oidc] audience`; type string) | `(empty)` | No | The `aud` a token must name: this server's client ID at the provider. Required: without it OIDC login stays off. |
| `iam.oidc.jwks-uri` (TOML `[iam.oidc] jwks_uri`; type string) | `(empty)` | No | Where the provider publishes the keys its tokens are signed with. `https://` only. |
| `iam.oidc.jwks-file` (TOML `[iam.oidc] jwks_file`; type path) | `(empty)` | No | A file with the same key set, instead of `iam.oidc.jwks-uri`: for a provider you cannot reach, or keys you pin. |
| `iam.oidc.username-claim` (TOML `[iam.oidc] username_claim`; type string) | `sub` | No | The claim that names the user. `preferred_username` and `email` are common. |
| `iam.oidc.groups-claim` (TOML `[iam.oidc] groups_claim`; type string) | `groups` | No | The claim that lists the user's groups (a list, or one string). |
| `iam.oidc.leeway` (TOML `[iam.oidc] leeway`; type seconds) | `60` | No | How far a clock may be off, for the `exp` and `nbf` of a token. |
| `iam.oidc.jwks-cache-ttl` (TOML `[iam.oidc] jwks_cache_ttl`; type seconds) | `3600` | No | How long the provider's keys are kept before they are fetched again. A token signed with a key HotKV does not know fetches them at once, at most every ten seconds. |
| `iam.oidc.timeout-ms` (TOML `[iam.oidc] timeout_ms`; type milliseconds) | `5000` | No | Time allowed for fetching the provider's keys. |
| `iam.oidc.ca-file` (TOML `[iam.oidc] ca_file`; type path) | `(empty)` | No | Certificate authorities that vouch for the provider's HTTPS certificate (PEM). Empty means the system's. |

## Alerts

These settings configure webhook alerts, which you can also manage at runtime
with the `ALERTS` command. The last five keys can only be set in
`hotkv.toml`.

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `alerts.webhook-url` (TOML `[alerts] webhook_url`; type string) | `(empty)` | No | Webhook that receives alerts. Can also be set at runtime with `ALERTS SETURL`. |
| `alerts.enabled` (TOML `[alerts] enabled`; type yes/no) | `yes` | No | Master switch for sending alerts. Can also be changed with `ALERTS ON` / `ALERTS OFF`. |
| `alerts.min-severity` (TOML `[alerts] min_severity`; type info, warning, critical) | `info` | No | Lowest severity that is sent. |
| `alerts.slow-threshold-ms` (TOML `[alerts] slow_threshold_ms`; type milliseconds) | `100` | No | Commands slower than this raise a slow-command alert. |
| `alerts.on-failover` (TOML `[alerts] on_failover`; type yes/no) | `yes` | No | Alert on failover. |
| `alerts.on-audit-tamper` (TOML `[alerts] on_audit_tamper`; type yes/no) | `yes` | No | Alert when audit log tampering is detected. |
| `alerts.on-tenant-limit` (TOML `[alerts] on_tenant_limit`; type yes/no) | `yes` | No | Alert when a tenant reaches a limit. |
| `[alerts] provider` (TOML `[alerts] provider`; type auto, generic, slack, discord, telegram; hotkv.toml only) | `auto` | No | Payload format. `auto` picks one from the webhook host. |
| `[alerts] max_queue` (TOML `[alerts] max_queue`; type integer; hotkv.toml only) | `1024` | No | Alerts buffered for sending; more are dropped and counted. |
| `[alerts] dedup_window_ms` (TOML `[alerts] dedup_window_ms`; type milliseconds; hotkv.toml only) | `5000` | No | Alerts of the same type within this window are sent once. `0` turns this off. |
| `[alerts] rate_per_minute` (TOML `[alerts] rate_per_minute`; type integer; hotkv.toml only) | `60` | No | Most alerts sent per minute. `0` means no limit. |
| `[alerts] block_private_networks` (TOML `[alerts] block_private_networks`; type yes/no; hotkv.toml only) | `yes` | No | Refuse webhook URLs on private, loopback, link-local and cloud metadata addresses. |

## AI engines

Settings for the AI and data features (semantic and prompt caches, agent
memory, LLM statistics and budgets, the prompt registry, RAG pipelines, the
feature store, time series and rate limiters). See [AI features](https://docs.hotkv.com/ai-features/index.md).

A limit of `0` means automatic. Set a number to fix it.

> **Caution**
> The `*.enabled` keys do not switch commands off. Access to these commands is
> controlled by your license and by [ACL rules](https://docs.hotkv.com/operate/acl/index.md); to keep users
> away from a feature, deny its commands in their ACL.

| Directive | Default | CONFIG SET | Description |
| --- | --- | --- | --- |
| `scache.enabled` (TOML `[scache] enabled`; type yes/no) | `yes` | No | Apply the limits below to the semantic cache at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `scache.default-threshold` (TOML `[scache] default_threshold`; type number) | `0.92` | No | Accepted but has no effect in this release; give the threshold per namespace with `SCACHE.CREATE` or `SCACHE.THRESHOLD`. |
| `scache.max-namespaces` (TOML `[scache] max_namespaces`; type integer) | `0 (auto)` | No | Most namespaces in the semantic cache. |
| `scache.max-entries-per-namespace` (TOML `[scache] max_entries_per_namespace`; type integer) | `0 (auto)` | No | Most entries per namespace in the semantic cache. |
| `pcache.enabled` (TOML `[pcache] enabled`; type yes/no) | `yes` | No | Apply the limits below to the prompt cache at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `pcache.max-namespaces` (TOML `[pcache] max_namespaces`; type integer) | `0 (auto)` | No | Most namespaces in the prompt cache. |
| `pcache.max-entries-per-namespace` (TOML `[pcache] max_entries_per_namespace`; type integer) | `0 (auto)` | No | Most entries per namespace in the prompt cache. |
| `tool.enabled` (TOML `[tool] enabled`; type yes/no) | `yes` | No | Apply the limits below to the tool-call cache at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `tool.max-namespaces` (TOML `[tool] max_namespaces`; type integer) | `0 (auto)` | No | Most namespaces in the tool-call cache. |
| `tool.max-entries-per-namespace` (TOML `[tool] max_entries_per_namespace`; type integer) | `0 (auto)` | No | Most entries per namespace in the tool-call cache. |
| `ncache.enabled` (TOML `[ncache] enabled`; type yes/no) | `yes` | No | Apply the limits below to the negative cache at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `ncache.max-namespaces` (TOML `[ncache] max_namespaces`; type integer) | `0 (auto)` | No | Most namespaces in the negative cache. |
| `ncache.max-entries-per-namespace` (TOML `[ncache] max_entries_per_namespace`; type integer) | `0 (auto)` | No | Most entries per namespace in the negative cache. |
| `guard.enabled` (TOML `[guard] enabled`; type yes/no) | `yes` | No | Apply the limits below to the guard cache at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `guard.max-namespaces` (TOML `[guard] max_namespaces`; type integer) | `0 (auto)` | No | Most namespaces in the guard cache. |
| `guard.max-entries-per-namespace` (TOML `[guard] max_entries_per_namespace`; type integer) | `0 (auto)` | No | Most entries per namespace in the guard cache. |
| `rerank.enabled` (TOML `[rerank] enabled`; type yes/no) | `yes` | No | Apply the limits below to the rerank score cache at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `rerank.max-namespaces` (TOML `[rerank] max_namespaces`; type integer) | `0 (auto)` | No | Most namespaces in the rerank score cache. |
| `rerank.max-entries-per-namespace` (TOML `[rerank] max_entries_per_namespace`; type integer) | `0 (auto)` | No | Most entries per namespace in the rerank score cache. |
| `embed.enabled` (TOML `[embed] enabled`; type yes/no) | `yes` | No | Apply the limits below to the embedding dedup store at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `embed.max-namespaces` (TOML `[embed] max_namespaces`; type integer) | `0 (auto)` | No | Most namespaces in the embedding dedup store. |
| `embed.max-entries-per-namespace` (TOML `[embed] max_entries_per_namespace`; type integer) | `0 (auto)` | No | Most entries per namespace in the embedding dedup store. |
| `amem.enabled` (TOML `[agent_memory] enabled`; type yes/no) | `yes` | No | Apply the limits below to agent memory at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `amem.max-agents` (TOML `[agent_memory] max_agents`; type integer) | `0 (auto)` | No | Most agents agent memory holds. |
| `amem.max-conv-turns` (TOML `[agent_memory] max_conv_turns`; type integer) | `100` | No | Turns kept per conversation. |
| `amem.default-ttl` (TOML `[agent_memory] default_ttl`; type seconds) | `0` | No | Default lifetime of a conversation. `0` means none. |
| `amem-summary.enabled` (TOML `[amem_summary] enabled`; type yes/no) | `yes` | No | Apply the limits below to agent memory summaries at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `llmstats.enabled` (TOML `[llmstats] enabled`; type yes/no) | `yes` | No | Apply the limits below to LLM usage statistics at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `llmstats.max-buckets` (TOML `[llmstats] max_buckets`; type integer) | `0 (auto)` | No | Most `LLMSTATS` buckets. |
| `llmstats.price-overrides` (TOML `[llmstats] price_overrides`; type list) | `(empty)` | No | Model prices loaded at startup, one entry per model: `model:input:output[:cacheread[:cachewrite5m[:cachewrite1h]]]` in USD per million tokens (comma-separated in `hotkv.conf`, an array in TOML). Same as `LLMSTATS.PRICE SET` for each. |
| `llmbudget.enabled` (TOML `[llmbudget] enabled`; type yes/no) | `yes` | No | Apply the limits below to LLM budgets at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `llmbudget.max-budgets` (TOML `[llmbudget] max_budgets`; type integer) | `0 (auto)` | No | Most `LLMBUDGET` budgets. |
| `prompt.enabled` (TOML `[prompt] enabled`; type yes/no) | `yes` | No | Apply the limits below to the prompt registry at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `prompt.max-templates` (TOML `[prompt] max_templates`; type integer) | `0 (auto)` | No | Most prompt templates. |
| `prompt.max-versions` (TOML `[prompt] max_versions`; type integer) | `64` | No | Versions kept per template. |
| `rag.enabled` (TOML `[rag] enabled`; type yes/no) | `yes` | No | Apply the limits below to RAG pipelines at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `rag.max-pipelines` (TOML `[rag] max_pipelines`; type integer) | `0 (auto)` | No | Most RAG pipelines. |
| `rag.default-chunk-size` (TOML `[rag] default_chunk_size`; type integer) | `512` | No | Accepted but has no effect in this release; set the chunk size per pipeline with `RAG.CREATE`. |
| `rag.default-chunk-overlap` (TOML `[rag] default_chunk_overlap`; type integer) | `64` | No | Accepted but has no effect in this release; set the overlap per pipeline with `RAG.CREATE`. |
| `featurestore.enabled` (TOML `[featurestore] enabled`; type yes/no) | `yes` | No | Apply the limits below to the feature store at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `featurestore.max-groups` (TOML `[featurestore] max_groups`; type integer) | `0 (auto)` | No | Most feature groups. |
| `timeseries.enabled` (TOML `[timeseries] enabled`; type yes/no) | `yes` | No | Apply the limits below to time series at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `timeseries.max-series` (TOML `[timeseries] max_series`; type integer) | `0 (auto)` | No | Most time series. |
| `ratelimit.enabled` (TOML `[ratelimit] enabled`; type yes/no) | `yes` | No | Apply the limits below to rate limiters at startup. `no` does not turn the commands off (the license and ACLs control access); it leaves these limits unapplied. |
| `ratelimit.max-limiters` (TOML `[ratelimit] max_limiters`; type integer) | `0 (auto)` | No | Most `RATELIMIT` limiters. |
| `vsim-persist.enabled` (TOML `[vsim_persist] enabled`; type yes/no) | `no` | No | Allow saving and loading vector indexes as files with `VSIM.SAVE` and `VSIM.LOAD`. |
| `vsim-persist.dir` (TOML `[vsim_persist] dir`; type path) | `vsim_snapshots` | No | Directory for `VSIM.SAVE` files. |
| `tenancy.enabled` (TOML `[tenancy] enabled`; type yes/no) | `no` | No | Accepted but has no effect in this release; tenants are managed with the `TENANT.*` commands. |
| `tenancy.default-maxmemory` (TOML `[tenancy] default_maxmemory`; type memory size) | `0` | No | Accepted but has no effect in this release. |
| `tenancy.default-maxconn` (TOML `[tenancy] default_maxconn`; type integer) | `1000` | No | Accepted but has no effect in this release. |