Treating Redis as just a fast key-value store for single cached values leaves most of its actual design on the table — its real data structures exist specifically to make whole categories of caching problem cheap that a plain key-value store makes expensive.
3 min read
SET user:42 '{"name": "Ana", "plan": "pro"}'
GET user:42
A plain string value (often a serialized JSON blob, as in System Design's cache-aside example) is the simplest case — fine for caching a whole object as one unit. The problem appears the moment only part of that object needs updating: changing plan means reading the whole JSON blob, deserializing it, modifying one field, re-serializing, and writing the whole thing back — wasteful, and a real race condition if two requests do this concurrently.
HSET user:42 name "Ana" plan "pro"
HGET user:42 plan # reads ONLY the plan field
HSET user:42 plan "enterprise" # updates ONLY the plan field
A hash stores multiple named fields under one key, letting the application read or write a single field directly — no round trip through the entire object. This is the right structure whenever a cached entity has several fields that get updated independently, which a single-string cache entry forces into an all-or-nothing read-modify-write cycle every time.
ZADD leaderboard 1500 "alice" 1800 "bob" 1200 "carol"
ZREVRANGE leaderboard 0 2 # top 3, highest score first
ZSCORE leaderboard "alice" # alice's specific score
ZREVRANK leaderboard "alice" # alice's rank (0-indexed from the top)
A sorted set keeps every member ordered by a numeric score, with all of the above operations running in logarithmic time even with millions of members. Caching a leaderboard, a trending-items list, or a rate-limiter's sliding window (each member's score is a timestamp) as a sorted set means "give me the top 10" or "what's this user's current rank" never requires fetching everything and sorting it in application code — exactly the kind of computation worth pushing into the cache layer rather than repeating on every request.
A list (an ordered sequence, with fast push/pop from either end) fits a "most recent 20 items" cache — push new items to the front, trim the tail past 20, and the cache never grows unbounded. A set (unordered, unique members) fits fast membership checks — "has this user already seen this notification" as SISMEMBER is a single O(1) operation, versus scanning a list or deserializing a JSON array to check for one value.
The throughline across all four: a plain string forces every operation into "read everything, do the work in application code, write everything back." Each specialized structure exists because some specific operation — partial update, ranked retrieval, membership check, bounded recent-items — is common enough in real caching workloads to deserve its own purpose-built, efficient primitive rather than being reimplemented in application code on top of a generic blob every time.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What problem does using a Redis hash (instead of a plain string) solve for a multi-field object?
2. Why is a sorted set well-suited to caching a leaderboard?
3. Which Redis structure is the best fit for a fast "has this user already seen this notification" check?
Caching Strategies