Redis cheat sheet

A scannable Redis reference: 26 short snippets across 12 topics, each linking back to the lesson it came from.

At a glance

TopicWhat it covers
Data types and the commands that matterA Redis string holds up to 512 MB of binary-safe bytes, which means it also stores JSON, a serialised object, or alesson
Expiry and caching patternsThe dominant pattern is cache-aside: read from Redis, and on a miss read from the database, write the value back with alesson
Pub/sub, queues and persistenceReplication is asynchronous by default, so a primary that fails can lose writes that no replica has yet received. WAITlesson
Installing Redis, redis-cli and RESP basicsServer and Redis Stack options, the redis-cli commands worth memorising, the RESP protocol, SCAN instead of KEYS, andlesson
Key design, memory and evictionMixing a cache and a queue in one instance means the cache policy can silently delete queued work. Separate instanceslesson
Transactions, Lua scripting and atomicityAny read-then-write sequence issued as two round trips is a race. If the correctness of your feature depends on thelesson
Streams and reliable queue processingThe ~ in MAXLEN ~ makes trimming approximate, which is far cheaper because Redis can remove whole radix-tree nodeslesson
Distributed locks and rate limitingCorrect SET NX PX locks, the token that makes release safe, the real caveats of Redlock, and token bucket andlesson
Everyday patterns: sessions, leaderboards and countersSession storage with sliding expiry, sorted-set leaderboards with ties and time decay, atomic counters, HyperLogLoglesson
Security: ACLs, TLS and hardeningACL users with key and command patterns, TLS configuration, disabling dangerous commands, protected mode, and networklesson
Performance, pipelining and monitoringPipelining and batching, latency diagnosis, SLOWLOG, client-side caching, hot keys, fork stalls and the metrics worthlesson
Replication, Sentinel and high availabilityClients must ask Sentinel for the current primary rather than caching an address. Every mature client library has alesson

Quick snippets

Data types and the commands that matter

Atomicity and the O(N) trap

MULTI
INCR  stats:orders
ZADD  leaderboard 10 alice
EXEC                     # both run, in order, with nothing in between

EVAL "return redis.call('GET', KEYS[1])" 1 user:42:name

SCAN 0 MATCH user:42:* COUNT 100      # safe cursor-based iteration
OBJECT ENCODING leaderboard           # listpack or skiplist?
MEMORY USAGE user:42

Full lesson: Data types and the commands that matter →

Expiry and caching patterns

How expiry works

SET cache:user:42 '{"name":"Ada"}' EX 300
EXPIRE cache:user:42 300
TTL    cache:user:42          # -1 has no TTL, -2 does not exist
PERSIST cache:user:42         # remove the TTL

SET lock:job:9 worker-3 NX EX 30   # atomic: only one worker wins

CONFIG SET maxmemory 4gb
CONFIG SET maxmemory-policy allkeys-lru
INFO memory

Full lesson: Expiry and caching patterns →

Pub/sub, queues and persistence

Reliable queue patterns

# naive: the message is gone if the worker dies after BRPOP returns
BRPOP queue:email 5

# reliable: move to a per-worker processing list atomically, then remove on success
LMOVE queue:email processing:w3 LEFT RIGHT
LREM  processing:w3 1 "m-1"         # on success
LPUSH queue:email "m-1"            # on failure: put it back

# a separate sweeper re-queues anything stuck too long
LRANGE processing:w3 0 -1

Persistence and replication

# redis.conf
save 900 1            # RDB snapshot after 1 change in 900s
save 300 10
appendonly yes        # AOF on
appendfsync everysec  # fsync once per second: at most ~1s of writes lost
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# on a replica
REPLICAOF 10.0.0.10 6379
WAIT 1 100            # block until 1 replica acknowledges, max 100 ms

Full lesson: Pub/sub, queues and persistence →

Installing Redis, redis-cli and RESP basics

RESP, the wire protocol

Client:  *3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n
Server:  +OK\r\n

Client:  *2\r\n$3\r\nGET\r\n$3\r\nfoo\r\n
Server:  $3\r\nbar\r\n

# types
#   +simple string   -error   :integer   $bulk string   *array
#   RESP3 adds: %map  ~set  >push  _null  ,double  #boolean

RESP, the wire protocol

# a pipeline of 10k commands, one round trip
redis-cli --pipe < commands.txt

# measure the cost of a round trip
redis-cli --latency-history -i 5

# a slow-motion trace of big or slow commands
redis-cli slowlog get 10
redis-cli --intrinsic-latency 5

Navigating the keyspace

127.0.0.1:6379> KEYS user:*              # NEVER in production: blocks the server
127.0.0.1:6379> SCAN 0 MATCH user:* COUNT 100
127.0.0.1:6379> SSCAN myset 0 COUNT 100
127.0.0.1:6379> HSCAN myhash 0 COUNT 100
127.0.0.1:6379> TYPE user:42
127.0.0.1:6379> TTL user:42
127.0.0.1:6379> OBJECT ENCODING user:42   # listpack, intset, skiplist, hashtable...
127.0.0.1:6379> MEMORY USAGE user:42
127.0.0.1:6379> INFO keyspace
127.0.0.1:6379> INFO memory | grep -E "used_memory_human|maxmemory_human"

Full lesson: Installing Redis, redis-cli and RESP basics →

Key design, memory and eviction

Key design

# colon-separated, type-prefixed keys
SET    user:42:profile:1     '{"name":"Ada"}'
HSET   cart:42:items        sku1 2 sku2 1
ZADD   board:daily:2026-09-18 1500 user:42
EXPIRE user:42:profile:1 3600

# hash tags force related keys onto the same cluster slot
# user:{42}:profile   user:{42}:orders   -> both hash to slot(user:{42})
# note the braces: only the part inside them is used for the slot

Eviction policies

CONFIG SET maxmemory 4gb
CONFIG SET maxmemory-policy allkeys-lru
CONFIG SET maxmemory-samples 10

# check what is actually happening
INFO stats | grep evicted_keys
INFO memory | grep -E "maxmemory_policy|mem_fragmentation_ratio"

Eviction policies

# never mix cache and durable data in one instance
# instance A: cache only
maxmemory-policy allkeys-lru

# instance B: locks, queues, sessions
maxmemory-policy noeviction
# and alert on evicted_keys > 0 and on rejected_connections

Full lesson: Key design, memory and eviction →

Transactions, Lua scripting and atomicity

Lua scripting

-- rate limit: increment and set a TTL only on the first hit
-- KEYS[1] = counter key, ARGV[1] = limit, ARGV[2] = window seconds
local current = redis.call('INCR', KEYS[1])
if current == 1 then
  redis.call('EXPIRE', KEYS[1], ARGV[2])
end
if current > tonumber(ARGV[1]) then
  return 0
end
return 1

Lua scripting

redis-cli --eval ratelimit.lua counter:user:42 , 100 60

# or inline
EVAL "return redis.call('GET', KEYS[1])" 1 mykey

# load once, run by hash: the preferred production pattern
SCRIPT LOAD "return redis.call('GET', KEYS[1])"
EVALSHA <sha1> 1 mykey
SCRIPT EXISTS <sha1>

Redis Functions and atomic patterns

#!lua name=mylib

redis.register_function('claim_job', function(keys, args)
  local job_id = redis.call('LMOVE', keys[1], keys[2], 'LEFT', 'RIGHT')
  if not job_id then return false end
  redis.call('HSET', keys[3], job_id, args[1])
  return job_id
end)

Full lesson: Transactions, Lua scripting and atomicity →

Streams and reliable queue processing

Adding and reading

XADD events * type order_placed order_id 42 amount 1999
XADD events * type order_paid order_id 42

XLEN events
XRANGE events - +
XREVRANGE events + - COUNT 10
XREAD COUNT 10 BLOCK 5000 STREAMS events $

# only messages newer than a known id, for catch-up after a restart
XREAD COUNT 100 STREAMS events 1758200000000-0

Consumer groups

# reclaim messages a dead worker left behind after 60s of idle
XAUTOCLAIM events workers worker-2 60000 0-0 COUNT 50

# trim to the last 100k entries when adding
XADD events MAXLEN ~ 100000 * type tick value 1.23

# or trim by time: keep roughly the last day
XTRIM events MINID ~ 1758000000000

Reliable processing patterns

# find consumers that have stopped acking
XPENDING events workers - + 1000
# then, per consumer, compare delivered and acknowledged counts
XINFO CONSUMERS events workers

Full lesson: Streams and reliable queue processing →

Distributed locks and rate limiting

A lock that actually works

# acquire: atomic set-if-absent with an expiry and an owner token
SET lock:order:42 <token> NX PX 30000

# release: compare and delete, in one atomic step (see the Lua script earlier)
# never: DEL lock:order:42   -- you may delete someone else's lock

# extend only if you still hold it: renewal, not acquisition
# repeated in a heartbeat while the work continues

# a fencing token is the only real protection
# every write to the protected resource carries the token,
# and the resource rejects any token lower than the highest seen

Rate limiters

-- sliding window log: precise, memory proportional to the limit
-- KEYS[1] = key, ARGV[1] = now ms, ARGV[2] = window ms, ARGV[3] = limit
redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, ARGV[1] - ARGV[2])
local count = redis.call('ZCARD', KEYS[1])
if count >= tonumber(ARGV[3]) then
  return 0
end
redis.call('ZADD', KEYS[1], ARGV[1], ARGV[1] .. '-' .. math.random(1000000))
redis.call('PEXPIRE', KEYS[1], ARGV[2])
return 1

Full lesson: Distributed locks and rate limiting →

Everyday patterns: sessions, leaderboards and counters

Session storage

HSET session:<id> user_id 42 role admin csrf <token> ip 203.0.113.9
EXPIRE session:<id> 1800

# sliding expiry: refresh on every request, but not on every request
# - refreshing on each call makes the key hot and the TTL meaningless
# - refresh only when more than 25 percent of the TTL has elapsed

# find a session by user for forced logout
SET user:42:session <session-id>

# log out everywhere
DEL session:<id> user:42:session

Leaderboards with sorted sets

# keep only the top 10k: sorted sets do not trim themselves
ZREMRANGEBYRANK board:global 0 -10001

# combine score and timestamp so ties break by who reached it first
# score = points, tie-break = (a large constant - unix seconds) / 1e6
# then ZREVRANGE gives the earlier achiever first

Full lesson: Everyday patterns: sessions, leaderboards and counters →

Security: ACLs, TLS and hardening

TLS and transport

redis-cli --tls --cacert /etc/redis/tls/ca.crt \
  --cert /etc/redis/tls/client.crt --key /etc/redis/tls/client.key \
  -h redis.internal -p 6379 PING

Network and operational hardening

# verify what is exposed before you ship
ss -ltnp | grep redis
redis-cli ACL WHOAMI
redis-cli CONFIG GET bind
redis-cli CONFIG GET requirepass
redis-cli INFO server | grep -E "redis_version|config_file"

Full lesson: Security: ACLs, TLS and hardening →

Performance, pipelining and monitoring

Diagnosing latency

redis-cli --latency                 # continuous round-trip measurement
redis-cli --latency-history -i 5    # over time, shows spikes
redis-cli --intrinsic-latency 5     # how fast can this box run at all
redis-cli --stat                    # live ops/s, memory, clients

redis-cli SLOWLOG GET 10
redis-cli CONFIG SET slowlog-log-slower-than 10000   # 10 ms
redis-cli CONFIG SET latency-monitor-threshold 100   # 100 ms
redis-cli LATENCY HISTORY command
redis-cli LATENCY RESET

redis-cli INFO commandstats | sort -t= -k2 -rn | head

Full lesson: Performance, pipelining and monitoring →

Replication, Sentinel and high availability

Replication

# on the primary
bind 10.0.0.10
requirepass ...          # or an ACL user
masterauth ...

# on each replica
replicaof 10.0.0.10 6379
replica-read-only yes
replica-serve-stale-data yes
repl-backlog-size 64mb
min-replicas-to-write 1
min-replicas-max-lag 10

Replication

redis-cli INFO replication
# role:master
# connected_slaves:2
# slave0:ip=10.0.0.11,state=online,offset=12345,lag=0

redis-cli -h 10.0.0.11 INFO replication | grep master_repl_offset

# WAIT reports how many replicas acknowledged a write
redis-cli SET important value
redis-cli WAIT 1 100        # at least 1 replica, within 100 ms

Sentinel and failover

# sentinel.conf, one file per Sentinel process, three or more across hosts
port 26379
sentinel monitor mymaster 10.0.0.10 6379 2
sentinel auth-pass mymaster ...
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

Full lesson: Replication, Sentinel and high availability →

FAQ

Is this Redis cheat sheet free to use?
Yes. No sign-up and no tracking: the page is static, every example is on the page itself, and you can print it or save it as a one-page reference.
Where do the examples come from?
Every snippet is taken from the 12 lessons of the Redis course on this site, and each section links back to the lesson it was pulled from.
How do I go deeper than a cheat sheet?
Open the full Redis course — it carries the worked explanations, the edge cases and the exercises behind every line here.

SQL MySQL PostgreSQL MongoDB SQLite

Last refreshed 2026-09-27.