MEMTIER\_BENCHMARK(1) User Commands MEMTIER\_BENCHMARK(1)

# [NAME](#NAME)

memtier\_benchmark - NoSQL benchmark tool

# [SYNOPSIS](#SYNOPSIS)

**memtier\_benchmark** \[*options*]

# [DESCRIPTION](#DESCRIPTION)

A memcache/redis NoSQL traffic generator and performance benchmarking tool.

## [Connection and General Options:](#Connection_and_General_Options:)

[**-h**, **--host**=*ADDR*](#h)

Server address (default: localhost)

[**-s**, **--server**=*ADDR*](#s)

Same as **--host**

[**-p**, **--port**=*PORT*](#p)

Server port (default: 6379)

[**-S**, **--unix-socket**=*SOCKET*](#S)

UNIX Domain socket name (default: none)

**-4**, **--ipv4**

Force IPv4 address resolution.

**-6** **--ipv6**

Force IPv6 address resolution.

[**-P**, **--protocol**=*PROTOCOL*](#P)

Protocol to use (default: redis). other supported protocols are resp2, resp3, memcache\_text and memcache\_binary. when using one of resp2 or resp3 the redis protocol version will be set via HELLO command.

[**-a**, **--authenticate**=*CREDENTIALS* Authenticate using specified credentials.](#a)

A simple password is used for memcache\_text and Redis &lt;= 5.x. &lt;USER&gt;:&lt;PASSWORD&gt; can be specified for memcache\_binary or Redis 6.x or newer with ACL user support.

[**-u**, **--uri**=*URI*](#u)

Server URI on format redis://user:password@host:port/dbnum User, password and dbnum are optional. For authentication without a username, use username 'default'. For TLS, use the scheme 'rediss'.

[**--tls**](#tls)

Enable SSL/TLS transport security

[**--cert**=*FILE*](#cert)

Use specified client certificate for TLS

[**--key**=*FILE*](#key)

Use specified private key for TLS

[**--cacert**=*FILE*](#cacert)

Use specified CA certs bundle for TLS

[**--tls-skip-verify**](#tls~2)

Skip verification of server certificate

[**--tls-protocols**](#tls~3)

Specify the tls protocol version to use, comma delemited. Use a combination of 'TLSv1', 'TLSv1.1', 'TLSv1.2' and 'TLSv1.3'.

[**--sni**=*STRING*](#sni)

Add an SNI header

[**-x**, **--run-count**=*NUMBER*](#x)

Number of full-test iterations to perform

[**-D**, **--debug**](#D)

Print debug output

[**--cluster-mode**](#cluster)

Run client in cluster mode

[**--transaction**](#transaction)

Treat one full rotation of **--command** entries as a transactional unit (e.g. WATCH/GET/MULTI/SETEX/EXEC/UNWATCH). Every \_\_key\__ in a rotation resolves to the same key (taken from the first keyed command's **--command-key-pattern**), so all keyed commands hit one key and one slot: the WATCH guards the key the SETEX writes and the unit runs without CROSSSLOT errors **--** no hash-tag needed. This same-key behavior applies in every mode, so it also works against a single endpoint fronting a sharded backend (e.g. a Redis Enterprise proxy) where keyed commands must share a slot. In **--cluster-mode** it additionally pins the whole rotation to the owning shard connection so the keyless commands (MULTI/EXEC/ UNWATCH) stay with the keyed ones. Caveat: keep the literal text around \_\_key\__ (including any {tag}) identical across keyed commands; differing affixes still hash to different slots. Requires at least one **--command**. **--pipeline** &gt; 1 is supported: in **--cluster-mode** each rotation is sent contiguously on its pinned connection, so multiple whole transactions can be in flight without interleaving MULTI/EXEC. Note: if **--reconnect-on-error** triggers mid-rotation, the interrupted rotation's stats will be inaccurate (server-side WATCH/MULTI state is lost on reconnect).

[**-h**, **--help**](#h~2)

Display this help

[**-v**, **--version**](#v)

Display version information

## [Results Output Options:](#Results_Output_Options:)

[**-o**, **--out-file**=*FILE*](#o)

Name of output file (default: stdout)

[**--json-out-file**=*FILE*](#json)

Name of JSON output file, if not set, will not print to json

[**--client-stats**=*FILE*](#client)

Produce per-client stats file

[**--hdr-file-prefix**=*FILE*](#hdr)

Prefix of HDR Latency Histogram output files, if not set, will not save latency histogram files

[**--show-config**](#show)

Print detailed configuration before running

[**--hide-histogram**](#hide)

Don't print detailed latency histogram

[**--print-percentiles**](#print)

Specify which percentiles info to print on the results table (by default prints percentiles: 50,99,99.9)

[**--print-all-runs**](#print~2)

When performing multiple test iterations, print and save results for all iterations

[**--realtime-latencies**](#realtime)

Replace the periodic single-line progress output with a per-tick block: line 1 = throughput + miss ratio, then one or more latency lines carrying the percentiles configured by **--print-percentiles** (immediate and overall, side-by-side). Redraws in place on a TTY; appends cleanly when stderr is redirected to a file.

[**--command-stats-breakdown**=*command*|line](#command)

How to group command statistics in the output (default: command) command: aggregate by command name (first word, e.g., SET, GET) line: show each command line separately

[**--command-miss-tracking**=*auto*|off](#command~2)

Track per-key cache misses for arbitrary commands (default: auto) auto: enable for commands with known reply shape (GET, MGET, HGET, HMGET, GETEX, EXISTS, ...) off: disable; mb.json will not contain per-arbitrary-command Hits/Misses fields

[**--miss-rate-threshold**=*PERCENTAGE*](#miss)

Warn when miss rate exceeds this percentage (default: 1.0). Accepts fractional values, e.g. 0.5 for half a percent. 0 warns on any miss.

[**--cpu-warn-threshold**=*PERCENTAGE*](#cpu)

Warn when a memtier worker thread's CPU exceeds this percentage of a core (default: 95.0), indicating memtier itself may be the bottleneck and results may be unreliable. 0 warns on any CPU usage.

[**--statsd-host**=*HOST*](#statsd)

StatsD server hostname to send real-time metrics (default: none, disabled)

[**--statsd-port**=*PORT*](#statsd~2)

StatsD server UDP port (default: 8125)

[**--statsd-prefix**=*PREFIX*](#statsd~3)

Prefix for StatsD metric names (default: memtier)

[**--statsd-run-label**=*LABEL*](#statsd~4)

Label for this benchmark run, used to distinguish runs in dashboards (default: default)

[**--graphite-port**=*PORT*](#graphite)

Graphite HTTP port for event annotations (default: 8080 for host access; use 80 when running inside the Docker network)

[**--prometheus-port**=*PORT*](#prometheus)

Serve Prometheus metrics on this port at */metrics* (default: disabled; 0 = ephemeral port)

[**--prometheus-bind-addr**=*ADDR*](#prometheus~2)

Numeric IPv4/IPv6 address to bind the Prometheus exporter to (default: 127.0.0.1; hostnames not supported)

[**--prometheus-run-label**=*KEY=VALUE*](#prometheus~3)

Add a constant label to every Prometheus metric (repeatable; max 16)

[**--prometheus-latency-buckets**=*LIST*](#prometheus~4)

Comma-separated, strictly ascending latency histogram bounds in seconds (default: built-in 26-bound list). Bounds closer than 1% of their value collapse to the same histogram slot and are rejected

## [Test Options:](#Test_Options:)

[**-n**, **--requests**=*NUMBER*](#n)

Number of total requests per client (default: 10000) use 'allkeys' to run on the entire key-range

[**--rate-limiting**=*NUMBER*](#rate)

The max number of requests to make per second from an individual connection (default is unlimited rate). If you use **--rate-limiting** and a very large rate is entered which cannot be met, memtier will do as many requests as possible per second.

[**-c**, **--clients**=*NUMBER*](#c)

Number of clients per thread (default: 50)

[**-t**, **--threads**=*NUMBER*](#t)

Number of threads (default: 4)

[**--test-time**=*SECS*](#test)

Number of seconds to run the test

[**--clients-start**=*NUMBER*](#clients)

Starting number of clients per thread for staircase ramp-up. Must be less than **--clients**. Requires **--clients-step** and **--step-duration**.

[**--clients-step**=*NUMBER*](#clients~2)

Number of clients to add per step in staircase ramp-up.

[**--step-duration**=*SECS*](#step)

Duration in seconds of each step before adding more clients.

[**--ratio**=*RATIO*](#ratio)

Set:Get ratio (default: 1:10)

[**--pipeline**=*NUMBER*](#pipeline)

Number of concurrent pipelined requests (default: 1)

[**--reconnect-interval**=*NUM*](#reconnect)

Number of requests after which re-connection is performed

[**--reconnect-on-error**](#reconnect~2)

Enable automatic reconnection on connection errors (default: disabled)

**--max-reconnect-attempts**=*NUM* Maximum number of reconnection attempts (default: 0, unlimited)

**--reconnect-backoff-factor**=*NUM* Backoff factor for reconnection delays (default: 0, no backoff)

[**--retry-on-error**](#retry)

Resend a request when the server returns a transient error or the connection drops mid-flight. Excludes permanent errors (WRONGTYPE, NOAUTH, NOPERM, syntax/argcount/unknown-command). Default: disabled.

[**--max-retries**=*N*](#max)

Maximum retries per request when **--retry-on-error** is set. **-1** = unlimited (default), 0 = disable retries even with the master switch on, N&gt;0 = bounded. MOVED/ASK redirects count toward this.

[**--retry-backoff-ms**=*NUM*](#retry~2)

Delay between retries in milliseconds (default: 0, immediate).

[**--retry-backoff-factor**=*NUM* Exponential multiplier applied to retry-backoff-ms on each](#retry~3)

successive retry (default: 0, constant backoff).

[**--retry-on**=*LIST*](#retry~4)

Restrict retries to error-status prefixes in this comma list (e.g. LOADING,BUSY,TRYAGAIN). Default: retry everything not classified as permanent.

[**--max-retry-queue**=*NUM*](#max~2)

Hard cap on per-connection retry queue depth. When full, the pipeline stops accepting new work until the queue drains. Default: 0 (auto = max(pipeline * 4, 64)).

[**--failed-keys-file**=*PATH*](#failed)

Append every request that ultimately fails (retries exhausted or permanent error) as CSV: timestamp,command,key,status,retries. Off by default. The benchmark continues if the file is unwritable.

[**--connection-timeout**=*SECS*](#connection)

Connection timeout in seconds, 0 to disable (default: 0)

[**--connection-stage-timeout**=*SECS*](#connection~2)

Abort with exit code 2 if no thread reaches steady state within SECS, or if connection-setup failures (AUTH / HELLO / SELECT / CLUSTER SLOTS / **-ERR** during initial probe) persist for SECS without a successful handshake. Bounds the \*startup* phase; **--test-time** still bounds the steady-state run. Default: 30, 0 disables the supervisor.

**--thread-conn-start-min-jitter-micros**=*NUM* Minimum jitter in microseconds between connection creation (default: 0)

**--thread-conn-start-max-jitter-micros**=*NUM* Maximum jitter in microseconds between connection creation (default: 0)

[**--multi-key-get**=*NUM*](#multi)

Enable multi-key get commands, up to NUM keys (default: 0). In cluster mode, keys are probed from the key space so that all keys in one batch route to the same shard (no hash-tag prefix).

[**--select-db**=*DB*](#select)

DB number to select, when testing a redis server

[**--distinct-client-seed**](#distinct)

Use a different random seed for each client

[**--randomize**](#randomize)

random seed based on timestamp (default is constant value)

## [Arbitrary command:](#Arbitrary_command:)

[**--command**=*COMMAND*](#command~3)

Specify a command to send in quotes. Each command that you specify is run with its ratio and key-pattern options. For example: **--command=**"set \_\_key\__ 5" **--command-ratio**=*2* **--command-key-pattern**=*G* To use a generated key or object, enter:

\_\_key\_\_: Use key generated from Key Options.

\_\_data\_\_: Use data generated from Object Options.

[**--command-ratio**](#command~4)

The number of times the command is sent in sequence.(default: 1)

[**--command-key-pattern**](#command~5)

Key pattern for the command (default: R): G for Gaussian distribution. R for uniform Random. Z for zipf distribution (will limit keys to positive). S for Sequential. P for Parallel (Sequential were each client has a subset of the key-range).

[**--monitor-input**=*FILE*](#monitor)

Read commands from Redis MONITOR output file. Commands can be referenced as \_\_monitor\_line1\_\_, \_\_monitor\_line2\_\_, etc. Use \_\_monitor\_line@\__ to select commands from the file. By default, selection is sequential; use **--monitor-pattern**=*R* for random. For example: **--monitor-input**=*monitor*.txt **--command=**"\_\_monitor\_line1\_\_"

[**--monitor-pattern**=*S*|R](#monitor~2)

Pattern for selecting monitor commands (default: S for Sequential) S for Sequential selection. R for Random selection.

[**--scan-incremental-iteration**](#scan)

Enable SCAN cursor iteration mode. When used with **--command=**"SCAN 0 \[MATCH pattern] \[COUNT count] \[TYPE type]", automatically follows the cursor returned by each SCAN response. Sends "SCAN 0 ..." initially, then "SCAN &lt;cursor&gt; ..." until the cursor returns 0, then restarts. Requires **--pipeline** 1. Stats are reported separately for "SCAN 0" and "SCAN &lt;cursor&gt;".

[**--scan-incremental-max-iterations**=*NUMBER*](#scan~2)

Maximum number of continuation SCANs per iteration cycle (default: 0, follow cursor until it returns 0).

[**--command-is-read**](#command~6)

Mark the preceding **--command** as a read operation for **--read-preference** routing (per-command override).

## [Read Preference Options:](#Read_Preference_Options:)

[**--read-preference**=*MODE*](#read)

Which node class receives read commands (default: primary). primary - all reads go to the master/primary node secondary - all reads go to replica nodes only secondaryPreferred - replicas preferred; fall back to primary nearest - EWMA-based selection: seed cold replicas

[round-robin until warm, then route reads](#round)

to the lowest-EWMA endpoint among warm replicas (primary may participate if it has accumulated samples)

[**--read-server**=*HOST*:PORT](#read~2)

Replica endpoint for standalone (non-cluster) mode. Repeatable; each occurrence adds one replica endpoint. IPv6 addresses may be given as \[::1]:6380. NOTE: parsed but read dispatch is currently cluster-only; see README "Read Preference" section.

[**--replica-clients**=*N*](#replica)

Connections per replica per client thread (default: 0 = inherit **--clients**) (parsed but not yet wired - see README "Read Preference" section).

[**--replicas-per-shard**=*K*](#replicas)

Cap on replicas used per shard (default: 0 = all) (parsed but not yet wired - see README "Read Preference" section).

[**--read-preference-fallback**=*MODE*](#read~3)

What to do when the target node class is unavailable (default: error). error - return an error queue - (reserved; currently treated as 'error' - request

[queuing not yet implemented)](#queuing)

primary - fall back silently to the primary

## [Object Options:](#Object_Options:)

[**-d** **--data-size**=*SIZE*](#d)

Object data size in bytes (default: 32)

[**--data-offset**=*OFFSET*](#data)

Actual size of value will be data-size + data-offset Will use SETRANGE / GETRANGE (default: 0)

[**-R** **--random-data**](#R)

Indicate that data should be randomized

[**--data-size-range**=*RANGE*](#data~2)

Use random-sized items in the specified range (min-max)

[**--data-size-list**=*LIST*](#data~3)

Use sizes from weight list (size1:weight1,..sizeN:weightN)

[**--data-size-pattern**=*R*|S](#data~4)

Use together with data-size-range when set to R, a random size from the defined data sizes will be used, when set to S, the defined data sizes will be evenly distributed across the key range, see **--key-maximum** (default R)

[**--expiry-range**=*RANGE*](#expiry)

Use random expiry values from the specified range

## [Imported Data Options:](#Imported_Data_Options:)

[**--data-import**=*FILE*](#data~5)

Read object data from file

[**--data-verify**](#data~6)

Enable data verification when test is complete

[**--verify-only**](#verify)

Only perform **--data-verify**, without any other test

[**--generate-keys**](#generate)

Generate keys for imported objects

[**--no-expiry**](#no)

Ignore expiry information in imported data

## [Key Options:](#Key_Options:)

[**--key-prefix**=*PREFIX*](#key~2)

Prefix for keys (default: "memtier-")

[**--key-minimum**=*NUMBER*](#key~3)

Key ID minimum value (default: 0)

[**--key-maximum**=*NUMBER*](#key~4)

Key ID maximum value (default: 10000000)

[**--key-pattern**=*PATTERN*](#key~5)

Set:Get pattern (default: R:R) G for Gaussian distribution. R for uniform Random. Z for zipf distribution (will limit keys to positive). S for Sequential. P for Parallel (Sequential were each client has a subset of the key-range).

[**--key-stddev**](#key~6)

The standard deviation used in the Gaussian distribution (default is key range / 6)

[**--key-median**](#key~7)

The median point used in the Gaussian distribution (default is the center of the key range)

[**--key-zipf-exp**](#key~8)

The exponent used in the zipf distribution, limit to (0, 5) Higher exponents result in higher concentration in top keys (default is 1, though any number &gt;2 seems insane)

## [WAIT Options:](#WAIT_Options:)

[**--wait-ratio**=*RATIO*](#wait)

Set:Wait ratio (default is no WAIT commands - 1:0)

[**--num-slaves**=*RANGE*](#num)

WAIT for a random number of slaves in the specified range

[**--wait-timeout**=*RANGE*](#wait~2)

WAIT for a random number of milliseconds in the specified range (normal distribution with the center in the middle of the range)

# [COPYRIGHT](#COPYRIGHT)

Copyright © 2011-2026 Redis Ltd.  
This is free software. You may redistribute copies of it under the terms of the GNU General Public License &lt;http://www.gnu.org/licenses/gpl.html&gt;. There is NO WARRANTY, to the extent permitted by law.

October 2026 memtier\_benchmark v=2.5.2 sha=bd85f6c4:1 bits=64 libevent=2.1.12-stable openssl=OpenSSL 3.0.13 30 Jan 2024 prometheus=yes

---

Document: memtier_benchmark(1) from memtier-benchmark 2.5.2-r1 (Chainguard OS)
Source: https://github.com/RedisLabs/memtier_benchmark
