Redis Explained: Way More Than Just a Cache
Redis data structures, use cases beyond caching, persistence options, pub/sub, and when it's overkill — a practical guide for developers.
Most developers first encounter Redis as "the caching layer." You put stuff in, it comes back fast because it's in memory. And that's true, but it barely scratches the surface of what Redis actually does.
Redis is an in-memory data structure server. That distinction matters. It's not a key-value store that happens to be fast. It's a server that gives you data structures — strings, lists, sets, sorted sets, hashes, streams, bitmaps — and lets you manipulate them with atomic operations at sub-millisecond latency.
The Data Structures That Matter
Strings are the basic building block. But "string" is misleading — it's really a binary-safe byte sequence up to 512MB. You can store JSON, serialized objects, counters, or actual text.SET user:1001:name "Alice"
GET user:1001:name # "Alice"
INCR page:views:home # atomic increment, returns new value
INCRBY api:rate:192.168.1.1 1
EXPIRE api:rate:192.168.1.1 60 # auto-delete after 60 seconds
That INCR + EXPIRE combo is the foundation of rate limiting. Atomic increment, automatic cleanup. Three lines and you've got a rate limiter.
HSET user:1001 name "Alice" email "alice@example.com" login_count 42
HGET user:1001 name # "Alice"
HINCRBY user:1001 login_count 1 # atomic field increment
HGETALL user:1001 # returns all fields
Lists are linked lists. O(1) push/pop on both ends. Great for queues, activity feeds, and recent-items lists:
LPUSH notifications:user:1001 "New comment on your post"
LPUSH notifications:user:1001 "Alice liked your photo"
LRANGE notifications:user:1001 0 9 # last 10 notifications
LTRIM notifications:user:1001 0 99 # keep only last 100
Sorted Sets are the secret weapon. Every member has a score, and the set is always sorted by that score. This is how leaderboards work:
ZADD leaderboard 2500 "player:alice"
ZADD leaderboard 3100 "player:bob"
ZADD leaderboard 1800 "player:charlie"
ZREVRANGE leaderboard 0 9 WITHSCORES # top 10 players
ZRANK leaderboard "player:alice" # Alice's rank
ZINCRBY leaderboard 200 "player:alice" # Alice scored 200 more points
Building a leaderboard in a relational database means ORDER BY score DESC on every request, hitting an index each time. In Redis, the sorted set is always in order. Reads are O(log N + M) where M is the number of results you want.
SADD online:users "alice" "bob" "charlie"
SISMEMBER online:users "alice" # 1 (true)
SCARD online:users # 3 (count)
SINTER online:users premium:users # users who are both online and premium
Pub/Sub
Redis has a built-in publish/subscribe system. It's simple and fast, but fire-and-forget — if a subscriber isn't connected when a message is published, it's gone.
# Terminal 1: subscribe
SUBSCRIBE chat:room:general
# Terminal 2: publish
PUBLISH chat:room:general "Hello everyone"
For durable messaging, look at Redis Streams (added in 5.0), which give you consumer groups, acknowledgment, and message persistence — essentially a lightweight Kafka.
Real-World Use Cases
Caching is the obvious one. Database query results, API responses, computed values. Set a TTL, and Redis handles expiration automatically. Session storage. Instead of sticky sessions or database-backed sessions, store them in Redis. Every app server can read any session. Horizontal scaling becomes trivial. Rate limiting.INCR a key per IP/user, EXPIRE it after the window resets. Sliding window? Use a sorted set with timestamps as scores.
Job queues. LPUSH jobs onto a list, workers BRPOP to block until a job arrives. Libraries like Sidekiq (Ruby), Bull (Node.js), and RQ (Python) all use Redis as the queue backend.
Real-time analytics. HyperLogLog gives you approximate unique counts using 12KB of memory regardless of cardinality. Count unique visitors across millions of events without storing every visitor ID.
PFADD unique:visitors:2026-03-26 "user:1001" "user:1002" "user:1001"
PFCOUNT unique:visitors:2026-03-26 # 2 (approximate)
Persistence: RDB vs AOF
"But it's in-memory — what if it crashes?" Redis has two persistence mechanisms:
RDB (Redis Database) takes point-in-time snapshots. Fast to load, compact files, but you lose data since the last snapshot. Good for caches where some data loss is acceptable. AOF (Append-Only File) logs every write operation. More durable (you can configurefsync per second or per write) but larger files and slightly slower. Good for data you can't afford to lose.
You can use both. Most production setups do — RDB for fast restarts, AOF for durability.
Redis vs Memcached
Memcached is simpler: string keys, string values, LRU eviction. That's it. If all you need is a dead-simple cache, Memcached works and uses memory slightly more efficiently due to its slab allocator.
Redis wins on everything else. Data structures, persistence, pub/sub, scripting (Lua), replication, Sentinel for HA, Cluster for sharding. Unless you have a specific reason to pick Memcached, Redis is the more capable choice.
When Redis Is Overkill
Not every project needs Redis. If your application serves a few hundred users and your database handles queries in single-digit milliseconds, adding Redis introduces complexity for negligible gain. An in-process cache (like a simple dictionary or LRU cache in your application) might be all you need.
Redis also isn't a replacement for your primary database. It's a complement. Don't try to model complex relational data in Redis hashes — that way lies madness.
If you want to get hands-on with Redis commands and see how these data structures work in practice, CodeUp has interactive exercises that let you run real Redis commands and build things like rate limiters and leaderboards step by step.
Redis is one of those tools that, once you understand it, you'll find uses for everywhere. The trick is knowing when "everywhere" is actually "here and here, but not over there."