Redis in System Design: Data Structures and Use Cases
Redis explained for system design: strings, hashes, sorted sets and streams, caching, leaderboards, rate limits, persistence, replication and Redis Cluster.
Redis is an in-memory data store that serves reads and writes in well under a millisecond and offers rich data structures, not just key-value strings: hashes, lists, sets, sorted sets, streams and more. In system design it's the default choice for caching, but also for session storage, rate limiting, leaderboards, counters, distributed locks with care, and lightweight queues. Knowing which data structure fits each problem, and what happens when Redis restarts, is what interviewers look for.
Data structures and what they're for
| Structure | Key commands | Typical use |
|---|---|---|
| String | GET, SET key value EX 60, INCR | Cached values, counters, flags |
| Hash | HSET, HGET, HGETALL | An object's fields, such as a session or user profile |
| List | LPUSH, RPOP, LRANGE | Recent items, simple queues |
| Set | SADD, SISMEMBER, SINTER | Unique members, tags, "who's online" |
| Sorted set | ZADD, ZRANGE, ZREVRANK, ZRANGEBYSCORE | Leaderboards, priority queues, time-ordered indexes, sliding-window rate limits |
| Stream | XADD, XREADGROUP, XACK | Append-only event logs with consumer groups |
| HyperLogLog | PFADD, PFCOUNT | Approximate unique counts with tiny memory. See probabilistic data structures |
| Geo | GEOADD, GEOSEARCH | Nearby search within a radius. See geospatial indexing |
Common patterns
- Cache-aside: read Redis, fall back to the database on a miss and populate with a TTL. See cache strategies.
- Leaderboard:
ZINCRBY leaderboard 10 user:42on each score;ZREVRANGE leaderboard 0 9 WITHSCORESfor the top ten;ZREVRANKfor a user's position. Every operation is logarithmic. - Rate limiting:
INCRa per-user, per-minute key with an expiry for a fixed window, or a sorted set of timestamps for a sliding window. Use a Lua script so check-and-increment is atomic. See rate limiting. - Sessions: a hash per session with an expiry, shared by all app servers, so the app servers stay stateless. See scalability.
- Counters:
INCRis atomic, so millions of likes or views can be counted without races, flushed to the database periodically. - Pub/sub and streams: pub/sub for fire-and-forget fan-out (no persistence); streams when messages must be durable and acknowledged.
Redis runs commands one at a time on a single main thread, so each command is atomic. That's why INCR and Lua scripts need no locks, and also why one slow command (KEYS * on millions of keys) blocks everything. Use SCAN instead.
Persistence and durability
| Option | How | Data at risk on crash |
|---|---|---|
| None | Pure cache | Everything (rebuilt from the source of truth) |
| RDB snapshots | Periodic point-in-time dumps | Changes since the last snapshot (minutes) |
| AOF (append-only file) | Log every write; fsync every second or always | About a second with everysec, or none with always (slower) |
| RDB + AOF | Both | Small, with faster restarts |
Treat Redis as a cache unless you've deliberately configured and tested durability. If losing its contents would lose business data, that data should also live in a durable database.
Memory and eviction
Everything lives in RAM, so set maxmemory and an eviction policy such as allkeys-lru for caches (evict the least recently used keys) or volatile-ttl to evict keys closest to expiry. Without a limit, memory grows until the process is killed. Use TTLs on cache keys, keep values small, and watch for big keys (a hash with millions of fields) that are slow to read and delete. See cache eviction.
Scaling and availability
- Replication: a primary with replicas for read scaling and failover. Replication is asynchronous, so a failover can lose the last writes.
- Sentinel or managed failover: monitors the primary and promotes a replica automatically.
- Redis Cluster: shards keys across primaries using 16,384 hash slots; multi-key operations work only when keys share a slot, which you can force with hash tags such as
{user42}:cartand{user42}:profile. - Hot keys: a single very popular key can overload one shard; replicate it or cache it in-process. See hot partitions.
- Locks: Redis-based locks are fine for efficiency (avoid duplicate work) but need fencing tokens when correctness depends on them. See distributed locks.
Where it’s used
Hot database rows and user sessions served in under a millisecond, shared by stateless app servers.
Sorted-set leaderboards and atomic counters for scores, likes and views.
Per-key rate limiting with atomic Lua scripts across a fleet of gateways.
In an interview
- Pick the right data structure: sorted sets for leaderboards, hashes for objects, INCR for counters.
- Explain single-threaded atomicity and why slow commands are dangerous.
- State the persistence setting and what's lost on a crash.
- Cover maxmemory with eviction, replication and Redis Cluster hash slots.
Further reading
- Redis data typesRedis documentation
- Redis persistenceRedis documentation