CLI Reference
Reference for the `memkv` command-line tool, with every subcommand, flag, default, and exit code.
The memkv binary contains every operator command: drive setup, the server,
the bundled documentation, the admin client, offline drive maintenance,
benchmarks, and network checks.
memkv [GLOBAL OPTIONS] <COMMAND> [ARGS]
Commands:
setup Initialize drives and generate config (outputs YAML to stdout)
start Start the server
doc Serve the bundled MemKV documentation over HTTP
admin Query the admin HTTP endpoint of one or more running MemKV servers
drive Offline drive maintenance (server stopped); see the `drive` section
bench Benchmark the data path of a running server over the network
net Check the RDMA fabric: negotiated parameters, connectivity, PFC countersOn macOS, memkv has only the start command, with the flags --config,
--license, --log-level, and --log-file. The other commands need Linux
features such as raw NVMe access, RDMA, and hugepages.
Global
| Flag | Description |
|---|---|
--version | Print the build version and exit. |
--help | Print top-level help. Works after any subcommand too. |
memkv <command> --help prints the help for one command.
setup
Formats the listed NVMe drives for MemKV and prints a working config.yaml to
stdout. Logs go to stderr, so you can redirect stdout straight to the
configuration file.
sudo memkv setup \
--drives /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 \
--rdma mlx5_0 \
| sudo tee /etc/memkv/config.yaml| Flag | Type | Default | Description |
|---|---|---|---|
--drives | PATH... | required | One or more NVMe block devices to format. After setup, MemKV owns these drives. |
--shard-size | KB | 64 | Minimum shard size in kilobytes. A value of 1024 or more sets the slot size (storage.block_size) to shard_size / 1024 MiB. A smaller value keeps the default slot size, 4 MiB. |
--rdma | STRING | mlx5_0 | RDMA device name to write to rdma.device in the generated YAML. |
--force | flag | off | Reformat drives that already hold MemKV data. Erases all data on the listed drives. |
--idempotent | flag | off | Exit 0 without changes if every drive is already set up. If only some drives are set up, the command still fails; add --force to reformat them all. For tools such as Helm or systemd that run setup on every restart. |
Behavior
- Logs each drive's model, optimal I/O size, and
max_sectors_kbto stderr before formatting. - Sets
memory.max_sizeto 50% of available system memory, with a minimum of 1 GB. - Without
--force, stops at the first drive that already holds MemKV data and names it. - Always writes
storage.mode: direct. For thefileormemorymodes, edit the YAML by hand. See Configuration.
Exit codes
| Code | Meaning |
|---|---|
0 | Drives formatted (or, with --idempotent, already set up) and YAML printed to stdout. |
1 | A drive path is missing, a drive holds data and --force is not set, drives are in mixed states with --idempotent, or formatting failed. Stderr gives the reason. |
start
Runs the MemKV server. At startup it checks the license, starts RDMA, recovers stored blocks, and opens the data and admin listeners.
sudo memkv start --config /etc/memkv/config.yaml| Flag | Type | Default | Description |
|---|---|---|---|
--config | PATH | /etc/memkv/config.yaml | YAML configuration file. See Configuration for every key. |
--license | PATH | unset | License file. When set and not empty, it is used before the other license sources (MEMKV_LICENSE, AISTOR_LICENSE, MINIO_LICENSE, and the standard file paths). See License for the accepted licenses. |
--log-level | STRING | from config | Overrides logging.level. Accepts trace, debug, info, warn, error, or a per-module filter such as memkv_server=debug,info. |
--log-file | PATH | memkv.log | File to append logs to. --log-file none sends logs to stderr. The format follows logging.format. |
--log-write-timing | SEC? | disabled | Logs the timing of write requests, at most once per the given number of seconds. The flag without a value means 3600. Omit the flag to turn it off. Use it to investigate tail latency without filling the log under heavy traffic. |
--metrics-history-path | PATH | memkv-metrics-history.bin | File that stores the 1m/1h/24h metrics history for the monitoring console. --metrics-history-path none turns off the file; history is then kept in memory only, until the process exits. |
Behavior
- Refuses to start on Linux kernels older than
6.8, because theio_uringand RDMA features MemKV uses are unstable on older kernels. - Checks that the memory pool fits in free hugepages or in 80% of available
system memory. If it does not, it prints a fix such as
sysctl -w vm.nr_hugepages=…. - Starts RDMA on the device in
rdma.device. If the device is missing or RDMA setup fails, the server logs an error, setsmemkv_rdma_active=0, and keeps running without RDMA. This is acceptable for development, never for production. - Recovers stored blocks from the configured drives. If there are none, it logs this and continues.
- On
SIGINTorSIGTERM, writes its storage metadata to disk and exits.
Exit codes
| Code | Meaning |
|---|---|
0 | Clean shutdown after SIGINT or SIGTERM. |
1 | Configuration error, license check failure, kernel too old, not enough memory or hugepages, storage failed to open, admin TLS misconfigured, or the license became invalid while running. |
doc
Serves this documentation site from inside the binary, so you can read it without internet access.
memkv docThe command listens on a random loopback port and logs the URL at startup
(http://127.0.0.1:<port>/).
admin
Queries the admin HTTP endpoint of one or more running MemKV servers. All
routes start with /v1/.
memkv admin [--servers <URLS>] <subcommand> [SUBCOMMAND ARGS]Server resolution
memkv admin uses the first of these that is set:
--servers <URLS>(short-s): a comma-separated list. Spaces and empty entries are ignored.- The
MEMKV_SERVERSenvironment variable, in the same format. http://127.0.0.1:9901.
An entry without a scheme, such as host:port, uses http://. For servers
with TLS (network.tls_cert and network.tls_key), use https:// URLs.
export MEMKV_SERVERS="coe02:9901,coe04:9901"
memkv admin statusSubcommands
| Subcommand | HTTP | Notes |
|---|---|---|
health | GET /v1/health | Liveness probe. Shows a table with each server's status. |
ready | GET /v1/ready | Readiness probe. Marks servers that are not ready and counts them as errors for the exit code. |
status [--json] [--verbose] | GET /v1/status | Detailed status. See the flags below. |
metrics | GET /v1/metrics | Prometheus metrics, printed as received. Output for each server is separated by a labeled line. |
drives failed [--json] | GET /v1/drives/failed | Table of failed drives for each server. With --json, prints a JSON array for each server. |
drives reset <device_id> [--secure] | POST /v1/drives/{device_id}/reset | Discards the drive's contents (BLKDISCARD) and sets it up again. Needs exactly one server: if more are configured, pass --servers <one>. --secure also writes zeros over the data area. |
admin status flags
| Flag | Description |
|---|---|
--json | Print the raw status JSON instead of a summary. With several servers, prints one JSON document per server, separated by a labeled line. |
--verbose, -v | Show details for each server: uptime, memory pool with a usage bar, a storage table for each drive, RDMA connections, and block totals. |
admin drives failed flags
| Flag | Description |
|---|---|
--json | Print the raw failed-drives JSON instead of the table. |
admin drives reset flags
| Flag | Description |
|---|---|
--secure | Write zeros over the data area after BLKDISCARD. Slower, but old data is overwritten whatever the drive does on discard. Sent as ?secure=true on the request. |
Admin HTTP API
memkv admin uses the HTTP endpoints that every server serves at
0.0.0.0:9901 (the data port + 1). The endpoints use HTTPS when
network.tls_cert and network.tls_key are set, and HTTP otherwise. Tools that
do not have the memkv binary, such as Helm hooks or external monitors, can
call the endpoints with curl.
| Endpoint | Method | Description |
|---|---|---|
/v1/health | GET | Liveness probe. |
/v1/ready | GET | Readiness probe. |
/v1/status | GET | Detailed status (uptime, memory, drives, RDMA). |
/v1/metrics | GET | Prometheus metrics. |
/v1/drives/failed | GET | Failed drives, with failure counts and state. |
/v1/drives/{device_id}/reset | POST | Erase and set up a failed drive again. Add ?secure=true to also write zeros over the data area. |
curl http://localhost:9901/v1/drives/failed[
{
"device_id": 2,
"failure_count": 3,
"first_failed_at": 1738800000,
"last_failed_at": 1738810000,
"blacklisted": false
}
]A reset discards the drive's contents and sets up its metadata again. The drive
then returns to service. To also write zeros over the data area, add
?secure=true; this takes time in proportion to the drive's size.
curl -X POST http://localhost:9901/v1/drives/2/reset
curl -X POST 'http://localhost:9901/v1/drives/2/reset?secure=true'A drive with more than storage.flap_threshold failures is blacklisted,
and you cannot reset it through the API above. The offline
memkv drive reset <path> command does not help either: the other drives
still record the blacklist, and the server restores it at startup. To use a
blacklisted drive again, reformat all drives with memkv setup --force, or
replace the drive.
Exit codes
| Code | Meaning |
|---|---|
0 | Every server responded successfully. |
1 | At least one server returned a connection or HTTP error, ready reported not ready, drives reset had more or fewer than one server, or no servers were configured. |
After an error, the command still queries the remaining servers, reports every failure, and sets the exit code at the end.
drive
Offline drive maintenance. These commands open a drive directly, so stop the
server first. To reset a drive while the server runs, use
memkv admin drives reset <device_id>.
Stop the server before you run any memkv drive command. The commands open
the drive with O_DIRECT, and a running server that also has the drive open
can leave it in an inconsistent state. For drive health on a running server,
use memkv admin status and memkv admin drives failed.
drive reset
memkv drive reset <PATH> [--secure]Erases the drive's metadata (superblock, journal, B+ tree, and bitmap) and sets
it up again, and discards the data area (BLKDISCARD). All data on the drive is
lost. The command reads the drive's device_id and the number of
drives from the drive itself, so you do not need to know them. If the main
superblock is unreadable, it uses the backup copy.
| Flag | Description |
|---|---|
--secure | Write zeros over the data area after BLKDISCARD. Slower, but old data is overwritten whatever the drive does on discard. Default: BLKDISCARD only. |
sudo memkv drive reset /dev/nvme2n1
sudo memkv drive reset /dev/nvme2n1 --securedrive reset does not clear a blacklist. See the callout under
Admin HTTP API.
drive verify
Checks the integrity of one drive. It only reads, never writes.
memkv drive verify <PATH> [--quick] [--json]It checks, in order:
- the superblock and its backup copy at the end of the drive;
- every B+ tree page against its stored checksum;
- the journal: if the drive was not shut down cleanly, the command replays it, as the server does, so a drive after a crash is not reported as corrupt;
- the allocation bitmap against the slots the index uses, reporting wasted slots and missing entries;
- unless
--quickis set, the CRC32 of every stored block. This is the only check that finds corrupted data, because the server does not verify checksums on read by default.
| Flag | Description |
|---|---|
--quick, -q | Skip the data-area checksum scan; check metadata only. |
--json | Print the report as JSON instead of a summary. |
sudo memkv drive verify /dev/nvme2n1
sudo memkv drive verify /dev/nvme2n1 --quick --jsonThe exit code is 0 when the drive is clean and 1 when errors remain. The
message then points you to drive fsck --repair.
drive fsck
Runs the same checks as verify. Without --repair, it only reports what it
would fix (like xfs_repair -n). With --repair, it fixes the metadata.
memkv drive fsck <PATH> [--repair] [--quick] [--json]A repair rebuilds the B+ tree from the valid entries, updates the bitmap to match, resets the journal, and marks the drive as cleanly shut down.
| Flag | Description |
|---|---|
--repair | Apply repairs. Without it, the command only reports. |
--quick, -q | Skip the data-area checksum scan; check and repair metadata only. |
--json | Print the report as JSON instead of a summary. |
sudo memkv drive fsck /dev/nvme2n1 # dry run — report only
sudo memkv drive fsck /dev/nvme2n1 --repair # apply repairsMemKV keeps no copy of a block on another drive, so a block with corrupted data cannot be recovered. A repair makes the drive consistent and safe to use: it removes each corrupted, duplicate, or orphaned block from the index. The inference engine then sees a cache miss and computes the block again. A repair never serves or keeps data that fails its checksum.
drive health
Shows a drive's model, capacity, fill level, whether it was shut down cleanly, and its recorded failures. It reads only metadata, not the data area.
memkv drive health <PATH> [--json]sudo memkv drive health /dev/nvme2n1
sudo memkv drive health /dev/nvme2n1 --jsondrive bench
Benchmarks the storage layer on its own, with no network and no running server. It can test raw NVMe drives or file-based storage.
memkv drive bench <SUITE> [flags]| Suite | Measures |
|---|---|
throughput | Write / read / mixed bandwidth across a range of value sizes. |
latency | Per-operation write / read latency distribution. |
scalability | How throughput scales with drive count, thread count, and key count. |
recovery | Index / journal recovery time as a function of key count. |
full | Runs the whole suite (file-based) and writes JSON reports to --output. |
To test raw NVMe drives, pass --devices /dev/nvme0n1,.... To test file-based
storage, pass a scratch directory with --dir. Results print to stdout; with
--output, they are also written as JSON.
sudo memkv drive bench throughput --devices /dev/nvme0n1 --data-sizes 4096,65536,1048576
memkv drive bench full --dir /tmp/bench --output ./benchmark-resultsTo benchmark the whole data path against a running cluster, use
memkv bench. To check the RDMA fabric without generating load, use
memkv net.
bench
Benchmarks the whole data path: it sends PUT and GET requests to a running
MemKV server over the network, through client, RDMA or TCP, server, and
storage. To test storage alone, use memkv drive bench. To
check the fabric without load, use memkv net.
MEMKV_AUTH_KEY=<hex> memkv bench --servers <ip:port>[,...] [--devices mlx5_0,...] [flags]Common flags (memkv bench --help lists all of them):
| Flag | Description |
|---|---|
--servers, -s | Comma-separated server addresses, one per rail. Default 127.0.0.1:9900. |
--devices, -d | Comma-separated RDMA devices, one per rail. Default mlx5_0. Ignored with --tcp. |
--tcp | Use TCP instead of RDMA. |
--block-size | Bytes per operation. Default 1048576. |
--threads, -t | Number of client threads. Default 1. |
--iterations / --warmup | Measured operations, and warm-up operations, per thread. Defaults 100 / 10. |
--read-only / --write-only | Run only reads, or only writes. |
--batch / --engine-batch / --engine-read / --nixl | Workload shapes that reproduce the batch and plugin call patterns. Use only one. |
--auth-key (or MEMKV_AUTH_KEY) is required and must match the server's
network.auth_key.
MEMKV_AUTH_KEY=$KEY memkv bench --servers 10.0.1.1:9900 --devices mlx5_0 --block-size 65536 --threads 8
MEMKV_AUTH_KEY=$KEY memkv bench --tcp --servers 10.0.1.1:9900 --write-onlynet
Checks the RDMA fabric on RoCEv2 and InfiniBand without generating load. Use it to confirm a NIC or fabric works, before or without a running server.
net show
Prints the settings MemKV would use on a device: the port's link layer, path MTU, whether the DC transport is available, and the fabric settings. On Ethernet these are the detected RoCEv2 GID index and traffic class (DSCP). On InfiniBand they are the LID and partition index. It makes no connection.
It also prints the NIC's kernel driver and vendor, whether the host's
libibverbs can register GPU memory as a dma-buf, which needs rdma-core 34 or
later, and the kernel peer-memory clients registered with the RDMA core,
such as amdkfd or nv_mem, which register GPU memory without one.
Whether the NIC driver accepts a given registration is known only by
trying one, which memkv bench --gpu-devices does.
memkv net show [--device mlx5_0] [--port 1] [--gid-index N] [--pkey-index N] [--traffic-class N] [--service-level N] [--mtu 4096]On RoCEv2, 0 means detect automatically and any other value sets the
setting:
--gid-indexis detected from the port's GID table (the routable RoCEv2 entry).--traffic-classand--service-levelare detected together from the NIC's DCB settings. When--traffic-classis0and detection succeeds, it also sets the service level and ignores any--service-levelyou pass. Set both or neither.
On InfiniBand, --gid-index and --traffic-class are ignored, and
--service-level 0 is not automatic detection: it selects virtual lane 0.
--pkey-index selects the InfiniBand partition; 0 is the default partition.
--mtu must be 256, 512, 1024, 2048, or 4096.
net verify
Connects to a running MemKV server over RDMA, reports the transport in use
(DC or RC) and the fabric settings, then writes and reads back data to prove
that it moves. Use it to check connections between NIC vendors, such as a
Broadcom bnxt_re client and an NVIDIA mlx5 server, and to confirm an
InfiniBand path end to end.
MEMKV_AUTH_KEY=<hex> memkv net verify --server <ip:port> [--device mlx5_0] [fabric flags]It takes the same fabric flags as net show, plus --auth-key (or
MEMKV_AUTH_KEY), which must match the server's key.
net probe
Takes a snapshot of a NIC's priority, pause, and PFC counters (from
ethtool -S). Compare snapshots from before and after a load test to confirm
that RoCE traffic used the lossless priority. The traffic class alone does not
prove that the fabric kept the traffic lossless. RoCEv2 only: InfiniBand has
its own flow control and no such counters.
memkv net probe [--device mlx5_0] [--netdev <iface>]On a NIC with several ports, where the device-to-interface mapping is unclear,
pass --netdev to name the interface.
net topo
Shows how far each RDMA NIC is from each GPU, and names the NIC each GPU should use for RDMA.
memkv net topo [--devices mlx5_0,mlx5_1] [--gpu-devices 0,1]GPUDirect RDMA reaches line rate only when the NIC and the GPU are on the same
PCIe switch, shown as PIX in the output (the same term nvidia-smi topo -m
uses; rocm-smi --showtopo shows the same layout on AMD). Any other path goes through the CPU. The right memkv_scratch_medium
setting depends on this result, and the vLLM plugin makes the same check at
startup to choose each rank's NIC, so run this command to see what the plugin
will choose. By default it reports
every device under /sys/class/infiniband and every GPU visible to CUDA or
HIP, and prints which runtime it found. The verdict for the whole host reads
every NVIDIA and AMD GPU the drivers list, whatever the visibility mask hides.
Environment variables
| Variable | Read by | Effect |
|---|---|---|
MEMKV_SERVERS | admin, client | Comma-separated list of endpoints. For admin, the admin endpoints; the default is http://127.0.0.1:9901. For the client (NIXL plugin and LD_PRELOAD shim), the data endpoints; it overrides servers: in MEMKV_CONFIG. |
MEMKV_CONFIG | client | Path to the client YAML file that the NIXL plugin and LD_PRELOAD shim read. Environment variables override the file, which overrides the defaults. See Client configuration. |
MEMKV_LICENSE | start, client | License, inline or as the path to a file. The license: field in MEMKV_CONFIG takes priority over it on the client. See License. |
AISTOR_LICENSE | start, client | Checked after MEMKV_LICENSE. Same format. The license must be valid for MemKV; a license issued for another product is rejected. |
MINIO_LICENSE | start, client | Checked after AISTOR_LICENSE. Same format. |
MEMKV_AUTH_KEY | start, client, memkv bench, memkv net verify | Required. The shared HMAC-SHA256 key, 64 hex characters (32 bytes), that signs every message between client and server. Overrides network.auth_key (server) and auth_key (client). Use the same value on both sides. Generate it with openssl rand -hex 32. |
MEMKV_TRANSPORT | client | Selects the client transport: auto (default; RDMA, with TCP if RDMA fails), rdma (RDMA only; errors instead of switching), rdma-rc (RDMA only, always the RC transport), or tcp (TCP only). See Transport selection. |
RUST_LOG | client | Log filter for the client library. Default memkv_client=info,memkv_nixl=info. The memkv commands do not read it: start uses --log-level or logging.level, and the other commands log at info. |
Default ports
| Port | Process | Source |
|---|---|---|
9900 | Data plane | network.address in config |
9901 | Admin HTTP/HTTPS | network.address port + 1 (auto, no separate knob) |
The data port is a TCP port. It carries control messages, RDMA setup, and TCP
data. RDMA data does not use it: RoCEv2 uses UDP port 4791, and InfiniBand does
not use IP ports. The admin endpoint is always at the data port + 1. On macOS, the server has no RDMA, but it listens
on the same network.address, so clients use the same address as on Linux.