Administration, Monitoring & Troubleshooting

This content was generated with the assistance of AI and should be verified against the official Redis documentation before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

Examples on this page target Redis Open Source 8.10 (8.10.2) with the Jedis 8 and Lettuce 7.7 client libraries, and cover the day-to-day administration surface: configuring a running server, reading its built-in diagnostics (INFO, SLOWLOG, LATENCY, MEMORY, HOTKEYS, CLIENT), benchmarking it, tuning memory usage, and exporting its metrics to an external monitoring stack.

Configuration: redis.conf and CONFIG

Redis 8.0 through 8.8.x ship two sample configuration files: redis.conf for the core server only, and redis-full.conf — which starts with include redis.conf — for the server plus the bundled search, time series, and probabilistic-data-structure components. Redis 8.10 (the version these examples target) folds everything back into a single redis.conf, so redis-full.conf no longer exists on 8.10+; only older 8.x installs need to choose between the two files. See Redis configuration.

# redis.conf -- one directive per line, "keyword argument1 [argument2 ...]"
maxmemory 2gb
maxmemory-policy allkeys-lru
appendonly yes

A running server can be reconfigured live, without editing that file or restarting, using CONFIG GET parameter [parameter …​] and CONFIG SET parameter value [parameter value …​] — both accept glob patterns on CONFIG GET and multiple parameter/value pairs on CONFIG SET in one call, though most (not all) directives support being changed this way. Live changes never touch redis.conf itself, so a restart reverts to whatever the file still says unless CONFIG REWRITE is run afterward, which scans the config file(s) the server was started with and updates only the fields that drifted from the live value, leaving comments and everything else untouched. See CONFIG GET, CONFIG SET, and CONFIG REWRITE.

127.0.0.1:6379> CONFIG GET maxmemory*
127.0.0.1:6379> CONFIG SET maxmemory 4gb maxmemory-policy allkeys-lru
OK
127.0.0.1:6379> CONFIG REWRITE
OK

INFO: the built-in health snapshot

INFO [section [section …​]] returns a text block of field:value pairs grouped into sections; calling it with no argument returns the default sections, INFO all returns every section including the more expensive ones, and naming a section (or several) narrows the reply to just that data instead of parsing the whole block. The sections worth checking first when something looks wrong:

Section What to look at

server

redis_version, uptime_in_seconds, process_id — confirms which build and how long it has run.

clients

connected_clients, blocked_clients, maxclients — a client count near maxclients explains refused connections before anything else does.

memory

used_memory, used_memory_rss, maxmemory, mem_fragmentation_ratio — a fragmentation ratio well above 1.0 is the first signal to look at activedefrag below.

persistence

rdb_bgsave_in_progress, aof_enabled, aof_rewrite_in_progress, loading — whether a background save or rewrite is running right now, which competes for CPU and I/O with normal traffic.

stats

total_commands_processed, instantaneous_ops_per_sec, evicted_keys, keyspace_hits/ keyspace_misses, expired_keys — throughput and cache-effectiveness over the server’s lifetime.

replication

role, connected_slaves, master_repl_offset, and per-replica slaveN:…​,lag=N fields — lag above a few seconds is worth investigating before it becomes stale-read risk.

cpu

used_cpu_sys, used_cpu_user — cumulative CPU time, useful as a coarse trend rather than a point-in-time reading.

keyspace

One dbN:keys=N,expires=N,avg_ttl=N line per non-empty logical database.

See INFO.

127.0.0.1:6379> INFO memory
127.0.0.1:6379> INFO replication

SLOWLOG: the slow-command log

Redis keeps an in-memory ring buffer of commands that took longer than slowlog-log-slower-than microseconds to execute (default 10000, i.e. 10ms; 0 logs every command, a negative value disables logging), up to slowlog-max-len entries. SLOWLOG GET [count] returns the most recent entries (each with an ID, Unix timestamp, execution time in microseconds, and the command’s argument vector), SLOWLOG LEN returns how many entries are currently stored, and SLOWLOG RESET clears the log — typically the first place to look once INFO stats or an application trace has already pointed at a period of elevated latency. See SLOWLOG GET and Diagnosing latency issues.

127.0.0.1:6379> CONFIG SET slowlog-log-slower-than 5000
OK
127.0.0.1:6379> SLOWLOG GET 10
127.0.0.1:6379> SLOWLOG LEN
(integer) 3
127.0.0.1:6379> SLOWLOG RESET
OK

LATENCY DOCTOR and LATENCY HISTORY

Beyond SLOWLOG, Redis’s latency-monitoring subsystem tracks latency spikes per named event (e.g. command, fork, expire-cycle) once latency-monitor-threshold (milliseconds) is set above zero. LATENCY HISTORY event-name returns that event’s raw time series of recorded spikes, each a timestamp/duration pair — useful for graphing or correlating against an external incident timeline. LATENCY DOCTOR goes further and returns a free-form, human-readable report that analyzes every recorded event and suggests likely causes (page faults during a fork, slow commands, expire-cycle pressure, and so on), which is usually the faster starting point when the root cause isn’t already suspected. See LATENCY HISTORY and LATENCY DOCTOR.

127.0.0.1:6379> CONFIG SET latency-monitor-threshold 100
OK
127.0.0.1:6379> LATENCY HISTORY command
127.0.0.1:6379> LATENCY DOCTOR

MEMORY DOCTOR, MEMORY USAGE, and MEMORY STATS

MEMORY USAGE key [SAMPLES count] reports the number of bytes a single key (its value plus its own overhead) currently occupies — for a large aggregate type, SAMPLES controls how many elements are sampled to estimate the total rather than walking every element, trading accuracy for speed. MEMORY STATS returns a structured breakdown of the whole keyspace’s memory (per-database overhead, the allocator’s own bookkeeping, replication backlog size, and more) as RESP field/value pairs, the same underlying numbers INFO memory summarizes but broken out further. MEMORY DOCTOR mirrors LATENCY DOCTOR for memory: it inspects the current allocation pattern and returns a plain-language report flagging things like high fragmentation or a large number of small keys, without requiring the reader to already know which MEMORY STATS field to look at. See MEMORY USAGE, MEMORY STATS, and MEMORY DOCTOR.

127.0.0.1:6379> MEMORY USAGE bookshop:book:9780000000001 SAMPLES 0
(integer) 512
127.0.0.1:6379> MEMORY STATS
127.0.0.1:6379> MEMORY DOCTOR

HOTKEYS: finding disproportionately busy keys

HOTKEYS (added in Redis 8.6.0, so available on the 8.10 target of this page) is a container command for a short tracking session that identifies keys responsible for a disproportionate share of CPU time and/or network bytes — the same job redis-cli --hotkeys and the older sampling-based approach did far less precisely. HOTKEYS START METRICS count [CPU] [NET] [COUNT k] [DURATION seconds] [SAMPLE ratio] begins a session: METRICS is required and names at least one of CPU/NET to track, COUNT sets how many top keys (k) to keep, DURATION auto-stops the session after that many seconds, and SAMPLE trades accuracy for overhead by only sampling one key in every ratio commands. HOTKEYS GET returns the current or most recent session’s results (including by-cpu-time-us and by-net-bytes key/value arrays), HOTKEYS STOP ends tracking early while keeping the collected data available to HOTKEYS GET, and HOTKEYS RESET discards it. Because tracking adds per-command overhead, a DURATION and a conservative SAMPLE ratio keep a production session’s cost bounded. See HOTKEYS, HOTKEYS START, and HOTKEYS GET.

127.0.0.1:6379> HOTKEYS START METRICS 2 CPU NET COUNT 10 DURATION 60 SAMPLE 10
OK
127.0.0.1:6379> HOTKEYS GET
 1) "tracking-active"
 2) (integer) 1
 3) "by-cpu-time-us"
 4) 1) "bookshop:book:9780000000001"
    2) (integer) 842
127.0.0.1:6379> HOTKEYS STOP
OK

CLIENT LIST and CLIENT KILL

CLIENT LIST [TYPE normal|master|replica|pubsub] returns one line per connected client with its address, age, idle time, last command, and more, optionally filtered to one connection class — the starting point for "who is connected right now and what are they doing." CLIENT KILL supports several selector forms: the legacy CLIENT KILL ip:port, and the newer filter form CLIENT KILL ID client-id | ADDR ip:port | TYPE type | USER username | SKIPME yes\|no […​], which can combine filters and closes every matching connection instead of exactly one. SKIPME defaults to yes so a filtered kill never closes the very connection issuing the command; because Redis is single-threaded, a client cannot be killed mid-command, only once it yields back to the event loop. See CLIENT LIST and CLIENT KILL.

127.0.0.1:6379> CLIENT LIST TYPE normal
id=7 addr=127.0.0.1:52344 ... cmd=get age=12 idle=0
127.0.0.1:6379> CLIENT KILL ID 7
(integer) 1

MONITOR

MONITOR streams every command processed by the server, in real time, as it happens — invaluable for a quick "what is actually being sent right now" trace against a misbehaving application. It comes with a real performance cost: because Redis is single-threaded, streaming every command to a MONITOR client competes directly with normal command processing, and the throughput hit grows with the server’s own command rate, so running it against a busy production instance for anything beyond a short, targeted trace measurably slows every other client. Ctrl-C (or closing the connection) is the only way to stop it once started. See MONITOR.

127.0.0.1:6379> MONITOR
OK
1758802531.128374 [0 127.0.0.1:52344] "JSON.GET" "bookshop:book:9780000000001"

redis-benchmark

redis-benchmark is the bundled load-testing tool: it simulates a number of concurrent clients (-c, default 50) each issuing a total number of requests (-n, default 100000) against a set of commands, and reports requests per second and latency percentiles per command. -t restricts the run to a comma-separated command list instead of the default full suite, -d sets the payload size in bytes for SET/LPUSH-style commands, -P pipelines that many requests per round trip, and --csv switches the summary to CSV for feeding into another tool. See Redis benchmark.

redis-benchmark -h 127.0.0.1 -p 6379 -c 50 -n 100000 -t GET,SET -d 128 -P 16 --csv

Memory optimization: small-collection encodings and active defragmentation

Redis automatically picks a compact, cache-friendly encoding for a collection while it stays small, and transparently upgrades it to the general-purpose encoding once a configured size or count threshold is crossed:

Type Compact encoding Threshold config

Hash

listpack

hash-max-listpack-entries / hash-max-listpack-value

List

listpack

list-max-listpack-size

Set of small integers

intset

set-max-intset-entries

Set of short strings

listpack

set-max-listpack-entries / set-max-listpack-value

Sorted set

listpack

zset-max-listpack-entries / zset-max-listpack-value

Keeping collections under these thresholds (splitting an oversized hash across several keys, for example) is one of the cheapest ways to shrink overall memory use, since a listpack/intset-encoded collection uses a fraction of the per-element overhead of its general-purpose counterpart. OBJECT ENCODING key reports which encoding a given key currently uses. Separately, activedefrag (CONFIG SET activedefrag yes, requires Redis built with jemalloc) runs an incremental background defragmentation pass that compacts memory fragmented by the normal churn of writes and deletes, targeted by active-defrag-ignore-bytes/active-defrag-threshold-lower/active-defrag-threshold-upper so it only kicks in once fragmentation is actually worth paying the CPU cost to fix. See Memory optimization.

127.0.0.1:6379> OBJECT ENCODING bookshop:cart:42
"listpack"
127.0.0.1:6379> CONFIG SET activedefrag yes
OK

Redis Insight’s profiler

Redis Insight (3.8 at the time of writing) is the official GUI, and its Profiler view is a graphical front end over the same command stream MONITOR exposes — it records and displays commands as they run against a chosen database, with filtering and search, without requiring a separate terminal session running MONITOR by hand. It carries the same underlying cost as MONITOR while a profiling session is active, so the same caution against leaving it running against production traffic applies.

Upgrade paths

Redis Open Source generally supports a rolling, in-place upgrade within the same major version by replacing the binary and restarting, and a minor/patch upgrade (e.g. 8.8 to 8.10) is typically safe to apply directly to a replica first, promote it, then upgrade the former primary — avoiding a full-cluster restart window. A major-version upgrade (e.g. 7.x to 8.x) warrants reading that release’s own upgrade notes first, since configuration file layout (as with redis-full.conf disappearing at 8.10) and default behaviors can change between major versions; replicating from the old version to a freshly started new-version replica, verifying it, then failing traffic over is the safer path over an in-place binary swap for anything beyond a small development instance. See Upgrade a standalone Redis instance to Redis 8.

redis_exporter: Prometheus and Grafana

redis_exporter follows the same shape as any other Prometheus exporter described in Exporters & the Pushgateway: it runs as its own process, connects to a Redis instance, and translates the output of INFO (plus, optionally, per-key metrics and LATENCY HISTORY) into Prometheus’s exposition format on its own /metrics endpoint for Prometheus to scrape on its normal schedule — no polling loop or custom collector needs to be written by hand.

docker run -d --name redis_exporter -p 9121:9121 \
  -e REDIS_ADDR=redis://redis:6379 \
  oliver006/redis_exporter

A Grafana dashboard built on the exporter’s metric names (redis_memory_used_bytes, redis_connected_clients, redis_commands_processed_total, redis_keyspace_hits_total/ redis_keyspace_misses_total, and so on) turns the same INFO fields this page reads by hand into graphs and alerts over time, without polling INFO from an application or a cron job.

flowchart TD A["Slow command reported"] --> B["Check SLOWLOG GET"] B --> C{"Slow entries found?"} C -->|Yes| D["Identify offending command/key pattern"] C -->|No| E["Check LATENCY HISTORY / LATENCY DOCTOR"] E --> F{"Latency spikes recorded?"} F -->|Yes| G["Correlate spike event\n(fork, expire-cycle, command)"] F -->|No| H["Check INFO memory / MEMORY DOCTOR\nand CPU (INFO cpu)"] H --> I{"Fragmentation or CPU pressure?"} I -->|Yes| J["Tune activedefrag / maxmemory-policy\nor scale up"] I -->|No| K["Check INFO replication and network\n(replica lag, connected_clients)"] D --> L["Resolution: fix query pattern,\nadd index, or split hot key"] G --> L J --> L K --> L