Redis sits in almost every production stack. It handles session storage, rate limiting, pub/sub, job queues, leaderboards, and distributed locks — often all at once. The 2026 version adds native vector search and ships with integrated ACL-based multi-tenancy. If you have not touched Redis seriously, this is the fastest path to using it correctly.
What changed in 2026
- Redis 8 is open-source again (BSD). After the SSPL controversy in 2024, Redis Ltd reverted to BSD license for the core engine. Valkey (the Linux Foundation fork) remains an alternative.
- Vector search is built-in — no need for the separate RediSearch module.
FT.CREATE with VECTOR field type and HNSW algorithm is part of core Redis 8.
- Redis 8 ships a new I/O threading model — throughput on multi-core machines increased ~40% in benchmarks for mixed read/write workloads.
- Redis Cluster auto-sharding improved — slot rebalancing is now non-blocking and online.
The five core data structures
| Type |
Use-case |
Key commands |
| String |
Cache, counter, session token |
GET, SET, INCR, EXPIRE |
| Hash |
Object fields, user profile |
HGET, HSET, HMGET, HDEL |
| List |
Queue, timeline, log buffer |
LPUSH, RPOP, LRANGE |
| Set |
Unique items, tags, intersections |
SADD, SISMEMBER, SINTER |
| Sorted Set |
Leaderboard, priority queue, rate limit |
ZADD, ZRANGE, ZRANGEBYSCORE |
Learning path
- Install Redis locally —
docker run -p 6379:6379 redis:8 and use redis-cli to explore.
- Master the five core types — set values, read them, expire them.
- Understand TTLs and eviction — the operational survival skill.
- Implement a real cache — write a cache-aside pattern around a slow database call.
- Add distributed locking — implement a simple Redlock or use Redisson.
- Explore Streams — build a producer/consumer pair with consumer groups.
- Learn Lua scripting — atomic multi-command operations without transactions overhead.
- Production config —
maxmemory, eviction policy, persistence (RDB vs AOF).
Cache-aside pattern — the most common Redis use
import redis
import json
import time
r = redis.Redis(host="localhost", port=6379, decode_responses=True)
def get_user(user_id: str) -> dict:
cache_key = f"user:{user_id}"
# 1. Check cache
cached = r.get(cache_key)
if cached:
return json.loads(cached)
# 2. Cache miss — fetch from DB
user = db.query("SELECT * FROM users WHERE id = ?", user_id)
# 3. Store with TTL
r.set(cache_key, json.dumps(user), ex=300) # 5-minute TTL
return user
Sorted sets for leaderboards and rate limiting
# Leaderboard — O(log N) insert and rank lookup
r.zadd("game:leaderboard", {"alice": 9500, "bob": 8800, "carol": 9100})
rank = r.zrevrank("game:leaderboard", "bob") # 0-indexed from top
top10 = r.zrevrange("game:leaderboard", 0, 9, withscores=True)
# Sliding window rate limiter — count requests in last 60s
now = int(time.time() * 1000)
window_start = now - 60_000
key = f"rate:{user_id}"
r.zremrangebyscore(key, 0, window_start) # remove old entries
r.zadd(key, {str(now): now})
r.expire(key, 120)
count = r.zcard(key)
if count > 100:
raise Exception("Rate limit exceeded")
Redis Streams — lightweight event bus
# Producer
r.xadd("orders", {"order_id": "123", "status": "placed", "total": "49.99"})
# Consumer group setup (once)
r.xgroup_create("orders", "processors", id="0", mkstream=True)
# Consumer — reads new messages, acknowledges after processing
messages = r.xreadgroup("processors", "worker-1", {"orders": ">"}, count=10)
for stream, entries in messages:
for msg_id, fields in entries:
print(fields)
r.xack("orders", "processors", msg_id)
Eviction policies — choose before launch
| Policy |
Behavior |
Use when |
noeviction |
Returns error when full |
Primary data store |
allkeys-lru |
Evicts least recently used key |
General cache |
volatile-lru |
LRU only on keys with TTL |
Mixed cache + persistent |
allkeys-lfu |
Evicts least frequently used |
Uneven access distribution |
volatile-ttl |
Evicts key with shortest TTL first |
Time-based freshness priority |
Set via CONFIG SET maxmemory-policy allkeys-lru or in redis.conf.
How to pick your learning focus
- Are you building caching? Master strings, TTLs, and cache-aside pattern first.
- Are you building a queue? Learn Lists for simple FIFO queues or Streams for at-least-once delivery with acknowledgement.
- Are you building rate limiting? Sorted sets with sliding windows or the token bucket pattern via Lua.
- Are you building pub/sub? Redis PUBLISH/SUBSCRIBE for fire-and-forget fan-out; Streams for durable delivery.
Common mistakes
No maxmemory config. Redis will happily consume all available RAM and OOM-kill the host. Always set maxmemory and an eviction policy in production.
Storing large objects in strings. A 1MB JSON blob per cache key with millions of keys exhausts memory fast. Cache field-level with Hash or store references.
Blocking commands in production. KEYS * scans the entire keyspace and blocks Redis for seconds. Use SCAN with a cursor instead.
Missing connection pooling. Creating a new connection per request adds ~1ms overhead and exhausts sockets. Use a pool (redis-py's ConnectionPool, ioredis pool).
No persistence for important data. Default Redis is in-memory only. Enable RDB snapshots or AOF log if the data must survive a restart.
What to skip
- Using Redis as a relational database — no joins, no indexes on values (only sorted sets). Use Postgres.
- Storing large binary blobs — Redis is optimized for small-to-medium values (<1MB). Use S3 for files.
- Rolling your own distributed lock — use an established library (Redlock, Redisson) rather than a naive
SET NX pattern.
FAQ
Is Redis still free and open-source in 2026?
Yes — Redis 8 reverted to the BSD license. Valkey is also a fully open-source alternative with the same API, governed by the Linux Foundation.
Redis vs Memcached — which should I use?
Redis in almost all cases. Memcached is faster for pure string caching at extreme scale, but Redis offers data structures, persistence, Streams, and Lua scripting that Memcached lacks entirely.
How do I secure a Redis instance?
Enable requirepass (AUTH), bind to localhost or a private interface, use Redis ACLs to restrict command sets per user, and run Redis inside a private network. Never expose port 6379 to the public internet.
What is the difference between RDB and AOF persistence?
RDB takes periodic snapshots — compact but can lose the last N seconds of writes. AOF logs every write command — near-zero data loss but larger files. Use both in production: RDB for fast recovery, AOF for durability.
Where to go next