Redis Operational Guide
Concise operational pointers for deep Redis troubleshooting and tuning.
Assumes you already know SET/GET/EXPIRE/TTL and basic data types. This skill covers the operational layer — the parts models tend to gloss over: persistence durability math, eviction internals, latency monitoring, cluster topology, replication, and the post-2024 fork landscape.
When to use
Load when the question is about:
- Persistence tradeoffs (RDB snapshot vs AOF, fsync policy, hybrid preamble, durability windows)
- Eviction misbehavior (OOM errors, wrong keys evicted, LRU vs LFU semantics, sample size)
- Memory analysis (
MEMORY USAGE/DOCTOR/STATS,--bigkeys, fragmentation,activedefrag) - Latency / slow-query diagnosis (
SLOWLOG,LATENCY MONITOR, fork stalls, AOF rewrites) - Cluster operations (16384 slots, MOVED/ASK redirects, hash tags, resharding, multi-key ops)
- Sentinel HA (quorum,
down-after-milliseconds,parallel-syncs, split-brain) - Replication (
PSYNCpartial vs full,repl-backlog-size,min-replicas-to-write) - Pipelining vs
MULTI/EXEC/WATCH(atomicity, optimistic locking, RTT batching) - Streams (consumer groups, PEL,
XCLAIM/XAUTOCLAIM, at-least-once delivery) - ACL hardening (categories, key/channel patterns, default user lockdown)
- Hot-key detection (
--hotkeys,INFO commandstats, why notMONITOR) - Choosing between Redis 7+, Valkey, KeyDB, Dragonfly
Do NOT load for: writing SET/GET/HSET, basic data-type questions, library client tutorials, schema-style key naming. Those don't need this skill.
Persistence: RDB, AOF, hybrid
- RDB (snapshot): point-in-time binary dump (
dump.rdb). Smallest file, fastest restart. Default triggersave 3600 1 300 100 60 10000(Redis 7+) — snapshot if 1 change in 1h or 100 in 5min or 10000 in 60s.BGSAVEfor manual;SAVEblocks the main thread (don't use in prod). - AOF (append-only file): every write logged; replayed on restart.
appendonly yes. Fsync policy viaappendfsync:always— fsync per write. Strong durability, ~1k ops/s ceiling on rotational disk.everysec— default. ~1s worst-case data loss window; the practical durability/perf sweet spot.no— kernel-driven (~30s on Linux). Fastest, weakest durability.
- AOF rewriting to compact:
BGREWRITEAOFmanual; auto viaauto-aof-rewrite-percentage 100+auto-aof-rewrite-min-size 64mb(rewrite when AOF doubles since last rewrite and ≥ 64 MB). - Hybrid preamble:
aof-use-rdb-preamble yes(default since Redis 4, on by default 7+). AOF starts with an RDB binary chunk, then incremental commands. Faster recovery than pure AOF, more durable than pure RDB. - Restart precedence: if both AOF and RDB exist, Redis loads AOF (better durability). Don't expect RDB to win.
- Cache mode (no persistence): requires BOTH
save ""ANDappendonly no. Setting only one leaves the other active. - Fork cost:
BGSAVE/BGREWRITEAOFusefork()— Linux CoW means the child starts with shared pages but copies on write. Peak memory can transiently approach 2× RSS during heavy write traffic. Watchlatest_fork_usecfromINFO.
Eviction policies
- Set the cap:
maxmemory 4gb. Cgroup memory limit is independent — set both to avoid OOM-kill. maxmemory-policy(defaultnoeviction):noeviction— writes fail with OOM error when full. Reads still work. Default, surprises users.allkeys-lru/allkeys-lfu/allkeys-random— any key eligible.volatile-lru/volatile-lfu/volatile-random/volatile-ttl— only keys with TTL eligible. Footgun: if no keys have TTL, behaves likenoeviction.
- LRU is approximated: Redis samples
maxmemory-sampleskeys (default5) and evicts the worst. Bump to10for accuracy,3for speed. True LRU would require tracking every access. - LFU uses a logarithmic counter with decay:
lfu-log-factor 10(default) — higher = slower counter saturation; favors long-tail hot keys.lfu-decay-time 1(default, minutes) — how fast counter decays toward 0.- LFU survives access bursts better than LRU; preferred for typical caches.
volatile-ttl: evicts keys with the shortest remaining TTL first. Useful when TTL encodes priority.- Diagnostic:
INFO stats→evicted_keyscounter. Rising fast → cap too low or wrong policy.
Memory, key inspection, fragmentation
- Per-key:
MEMORY USAGE key [SAMPLES n]— bytes (sampling for collections). - Aggregate:
MEMORY STATSper-pool (overhead, dataset, allocator).MEMORY DOCTOR— narrative summary; flags fragmentation, child-process forks, big clients. - Scans:
redis-cli --bigkeys— sample-based largest-by-type. Fast, approximate.redis-cli --memkeys --memkeys-samples 0— accurate but full-scan (heavy).redis-cli --keystats— per-type byte/length distribution.redis-cli --hotkeys— top accessed keys. Requiresmaxmemory-policy *-lfu(uses LFU counters).
- Don't
MONITORin production: streams every command server-wide, ~50 % perf hit. Useredis-cli -i 1 -r 60 INFO commandstatsfor periodic sampling; diff between samples surfaces hot patterns. - Hot-key mitigations: client-side caching (
CLIENT TRACKING ONover RESP3), key sharding ({user:1234}:counter:{0..9}then sum), or read replicas withREADONLY. - Fragmentation:
INFO memory→mem_fragmentation_ratio = used_memory_rss / used_memory.> 1.5→ real fragmentation (jemalloc holding free pages).< 1.0→ swapping (RSS smaller than logical). Investigatevmstat.
- Active defrag (Redis 4+, jemalloc only):
activedefrag yes. Triggers whenactive-defrag-ignore-bytes 100mbANDactive-defrag-threshold-lower 10(% fragmentation) both met. CPU-bounded byactive-defrag-cycle-min/max(1–25 % default).
SLOWLOG and LATENCY MONITOR
- Slow log (per-command execution time, excluding I/O):
slowlog-log-slower-than 10000— microseconds; default 10 ms.0logs every command,-1disables.slowlog-max-len 128— ring buffer length.SLOWLOG GET 10last 10;SLOWLOG LEN;SLOWLOG RESET.- Captures command name + truncated args + duration. Args truncated to
slowlog-log-slower-thannot affecting field.
- Latency monitor (Redis 4+, samples event latency, not command):
latency-monitor-threshold 100— ms;0(default) disables.- Events:
command,fast-command,fork,aof-write,aof-fsync-always,aof-stat,aof-rewrite-diff-write,rdb-unlink-temp-file,expire-cycle,eviction-cycle,eviction-del. LATENCY LATEST— most recent event per type.LATENCY HISTORY <event>— time series for one event.LATENCY GRAPH <event>— ASCII spark chart.LATENCY DOCTOR— narrative analysis with remediation hints.LATENCY RESET [event ...].
MONITORis not a diagnostic tool: streams every command to the client. ~50 % perf hit on the server. Useredis-cli -i 1 -r 60 INFO commandstatsfor periodic sampling instead.
Cluster, Sentinel, replication
Cluster (sharded; horizontal scale + HA):
- 16384 hash slots,
slot = CRC16(key) mod 16384. Each master owns a slot range. Min 3 masters for HA failover voting; recommended 6 nodes (3 master + 3 replica). - Slot inspection:
CLUSTER SHARDS(Redis 7+, structured, prefer this),CLUSTER NODES(raw),CLUSTER SLOTS(legacy). Per-slot:CLUSTER COUNTKEYSINSLOT <slot>/CLUSTER GETKEYSINSLOT <slot> <count>. - Redirects:
MOVED <slot> ip:port— permanent, refresh slot map.ASK <slot> ip:port— slot in migration, one-shot, do NOT cache. Smart clients cache the slot table and recompute onMOVED. - Hash tags:
{tag}key— only substring inside{...}is hashed. Forces same-slot routing for multi-key ops. - Multi-key constraint:
MGET,MSET,SINTERSTORE,MULTI/EXEC, LuaEVAL— all keys must hash to same slot orCROSSSLOTerror. - Tooling:
redis-cli --cluster {create,check,fix,reshard,rebalance,info,call,import}.--cluster checkfinds slot coverage gaps and stuck open slots. - Sharded Pub/Sub (Redis 7+):
SPUBLISH/SSUBSCRIBEroute by hash slot; replaces broadcastPUBLISHwhich was inefficient cluster-wide.
Sentinel (HA for non-sharded master + replicas):
- Sentinel monitors a single master and promotes a replica on failure. Not a sharded topology.
sentinel monitor <name> <master> <port> <quorum>.quorum= sentinels that must agree master iss_downbefore voting starts. Election requires majority of all sentinels (distinct from quorum).sentinel down-after-milliseconds <name> <ms>— unresponsive duration befores_down(subjective). Quorum count →o_down(objective) → election.sentinel parallel-syncs <name> <N>— replicas resyncing from new master simultaneously. Default 1; higher = faster convergence, more I/O on new master.sentinel failover-timeout <name> <ms>— bounds full failover; also throttles retry on failed failover. Default 180000 (3 min).- Odd sentinel count: 3 or 5, never 2 or 4. Even counts can split-brain.
- Sentinels rewrite their own config file on state changes — back up before editing.
Replication (under both cluster and sentinel):
replicaof <host> <port>(or deprecatedslaveof). Replica is read-only by default (replica-read-only yes).- Sync types: full — master
BGSAVEs an RDB, ships, replays buffered commands. Triggered on fresh replica, ID mismatch, or backlog gap. Partial (PSYNC) — replica reconnects with last offset; if master's backlog still covers it → ship the delta. repl-backlog-size— circular buffer on master holding recent writes for partial resync. Default1mb. Too small → frequent full resyncs after any blip. Bump to 64–512 MB on busy masters with flaky networks. Cost is buffer size, master-side.repl-backlog-ttl 3600— release backlog after N seconds with no replicas connected.- Durability gate on master:
min-replicas-to-write N+min-replicas-max-lag M(seconds) — master refuses writes unless ≥ N replicas have lag ≤ M. - Eventual consistency on read: replicas can be stale. Don't use
replicaoftopology for read-after-write without explicit fencing. - Replication ID rotation:
failoverto a replica creates a new replication ID, forcing a full sync on any other reconnecting replica. Plan promotion windows accordingly.
Atomicity, scripting, and messaging
Pipelining vs transactions:
- Pipelining: client sends N commands without waiting; server processes in order, replies stream back. Saves RTTs. Not atomic — other clients' commands can interleave.
MULTI/EXEC/DISCARD: server queues commands afterMULTI, executes batch atomically onEXEC. No interleaving. No rollback — each command's error reported but the rest still run, except queue-time syntax errors which abort the whole transaction.WATCH key [key ...]beforeMULTI— optimistic locking / CAS. If any watched key is modified beforeEXEC,EXECreturns nil and nothing runs. Retry loop is the caller's job. Best for low contention.- Pipeline + MULTI together is idiomatic: client batches
MULTI/queued/EXECinto one TCP write.
Lua and Functions:
EVAL script numkeys key1 ... arg1 ...— atomic server-side execution.KEYS/ARGVseparation is mandatory; in cluster mode allKEYSmust hash to same slot.EVALSHA <sha> ...afterSCRIPT LOAD— caches script by SHA1. Fall back toEVALonNOSCRIPT(cache flushed on restart /SCRIPT FLUSH).- Functions (Redis 7+,
FUNCTION LOAD) — persistent server-side library, replicated and persisted. Replaces ad-hoc Lua-per-deploy; preferred for shared logic.
Streams (durable log + consumer groups):
XADD stream '*' field value ...—*autogenerates<ms-timestamp>-<seq>; explicit IDs must be monotonically increasing.- Capped:
XADD stream MAXLEN ~ 100000 ...—~approximate trim (efficient),=exact (expensive).MINIDtrims by ID. XGROUP CREATE stream g $ MKSTREAM($= current end;0= beginning).XREADGROUP GROUP g consumer1 COUNT 10 BLOCK 5000 STREAMS stream >—>= new messages only. Use0to re-read this consumer's pending list (PEL recovery on restart).- PEL (Pending Entries List): every read via
XREADGROUPenters PEL; remains untilXACK. XPENDING stream gsummary;XPENDING stream g IDLE <ms> - + count [consumer]detail.XCLAIM stream g new-consumer min-idle-ms <id> ...— reassign stuck messages.XAUTOCLAIM stream g new-consumer min-idle-ms <start-id> [COUNT n](Redis 6.2+) — automated PEL handover. Prefer over manualXCLAIMloops.- At-least-once, never exactly-once: crash between work and
XACKcauses redelivery. Tracktimes_deliveredviaXPENDING; route to DLQ stream above N.
Pub/Sub:
SUBSCRIBE/PUBLISH/PSUBSCRIBE— fire-and-forget, no persistence, no consumer groups. Subscribers connected at publish time get the message; everyone else loses it. For durable fan-out use Streams. In cluster, use shardedSPUBLISH/SSUBSCRIBE.
Security and runtime control
ACL (Redis 6+):
- Default: single
defaultuser withon nopass ~* &* +@all— full access. Setrequirepassor editdefaultACL to lock down. ACL SETUSER alice on >mypass ~app:* &events:* +@read +get +set -@dangerouson/off— enable;>pwadd password,<pwremove,nopass,resetpass.~pattern— key glob; multiple allowed;~*= all;resetkeysclears.&pattern(Redis 6.2+) — Pub/Sub channel glob;allchannels/resetchannels.+cmd/-cmd/+@category/-@category.
- Categories:
@all,@admin,@dangerous(FLUSHALL/KEYS/CONFIG/...),@write,@read,@keyspace,@connection,@scripting,@stream,@pubsub,@slow,@fast, plus per-data-type (@string,@hash,@list,@set,@sortedset,@geo,@bitmap,@hyperloglog). - Inspect:
ACL WHOAMI,ACL LIST,ACL GETUSER alice,ACL CAT [category],ACL LOG(recent auth/permission failures). - Persist:
user ...lines inredis.confOR externalaclfile /path/users.acl— not both.ACL SAVEwrites to aclfile (only whenaclfileis set). - Cluster: ACLs are NOT auto-replicated. Distribute via config management.
TLS (Redis 6+): tls-port 6380, tls-cert-file, tls-key-file, tls-ca-cert-file. tls-auth-clients yes for mTLS. Compile with make BUILD_TLS=yes (not default in stock builds before 7).
CLIENT control:
CLIENT LIST [TYPE normal|master|replica|pubsub] [ID ...].CLIENT KILL ID <id>/ADDR ip:port/LADDR ip:port/TYPE x/USER alice.CLIENT NO-EVICT ON(Redis 7+) — protect this connection frommaxmemory-clientseviction.CLIENT TRACKING ON(RESP3) — server-assisted client-side caching with invalidations.
CONFIG:
CONFIG GET <pattern>/CONFIG SET <param> <value>— runtime change. Not all params are settable at runtime; some require restart.CONFIG REWRITE— persists in-memory config back toredis.conf, preserving comments where possible. Without it, runtime changes vanish on restart.CONFIG RESETSTAT— zeros theINFO statscounters.
Variants: Redis 7+, Valkey, KeyDB, Dragonfly
- Redis 7.4+ licensing (March 2024): dual SSPLv1 / RSALv2 — not OSI-open-source. Source-available with restrictions on managed-service competitors. Redis 8.0 (May 2025) added back AGPLv3 as a third option, but Linux Foundation still backs the fork.
- Valkey (valkey.io): community fork of Redis 7.2.4 under BSD-3-Clause, governed by the Linux Foundation. Drop-in wire-compatible. AWS ElastiCache, GCP Memorystore, Oracle Cloud, Azure are shipping it. Default migration path for OSS-only shops.
- KeyDB (Snap/EQ Alpha): multi-threaded fork (pre-Valkey). Multiple worker threads share the dataset with per-key locking. Performance up to ~3× single-threaded Redis on the same box. FLASH tiered storage (hot RAM / cold NVMe). Diverging from upstream; use with eyes open.
- Dragonfly (dragonflydb.io): clean-room reimplementation in C++ with shared-nothing multi-threading via
io_uring. Single node replaces a small Redis cluster. Wire-compatible with most commands. Caveats: Lua support limited or absent in some versions, AOF semantics differ, no exactSLOWLOG/LATENCYparity. Vet feature coverage before adopting. - Choosing: drop-in OSS replacement → Valkey. Single-node multicore throughput ceiling → Dragonfly. Tiered storage with Redis API → KeyDB. Stay on Redis only if you need Redis Stack (Search, JSON, TimeSeries, Bloom) modules and accept the license terms.
Authoritative references
Official Redis docs (redis.io/docs/latest):
- Persistence (RDB / AOF / hybrid)
- Key eviction policies
- SLOWLOG command
- Latency monitoring
- Redis cluster specification
- Cluster tutorial
- High availability with Sentinel
- Replication
- Streams introduction
- Transactions (MULTI/EXEC/WATCH)
- ACL
- HOTKEYS / XCLAIM
Source / changelog:
- github.com/redis/redis —
redis.confdefaults, CHANGELOG.md,src/replication.c
Community deep-dives:
- antirez (Salvatore Sanfilippo) — original Redis design notes, e.g. Streams Consumer Group Patterns
- Arpit Bhayani — replication backlog circular-buffer internals
Variants:
- valkey.io — Valkey project, Linux Foundation
- dragonflydb.io — Dragonfly architecture
- docs.keydb.dev — KeyDB multi-threading and FLASH
Guardrails
Before recommending a non-trivial operational change (eviction policy, fsync, backlog size, cluster reshard, ACL, defrag):
- Quote the specific parameter name and its default value.
- Cite the official Redis doc section (or variant doc if Valkey/KeyDB/Dragonfly).
- Make the recommendation conditional on observed metrics (
INFO,LATENCY,SLOWLOG,evicted_keys,mem_fragmentation_ratio) — never blanket-tune. - For variant migrations, name the specific feature that justifies leaving Redis (license, multi-threading, tiered storage, modules) — don't switch on benchmarks alone.
Tuning without measurement is worse than defaults.