Filter concepts by levelShowing all levels.

System Design · Redis and Distributed Caching

Redis and Distributed Caching

What Redis is for beyond caching, its core data structures, and how a shared cache breaks under load

  • Beyond cachingcounters, sessions, rate limits, locks, queues
  • Data structuresstring, hash, list, set, sorted set
  • Pub/Sub vs Streamsfire-and-forget vs persistent log
  • Real failure modesstampede, hot keys, memory pressure

1.What Redis is actually used for beyond caching

Redis is best known as a cache, but its speed and atomic operations make it a fit for anything that needs fast, shared, short-lived state — counters, session storage, rate limiting, lightweight coordination locks, and simple queues. The common thread across all of these is: state that many instances need to share, updated frequently, where losing it is tolerable or backed up elsewhere.

Key features

  • Caching: the most common use — storing expensive-to-compute results with a TTL
  • Counters: Redis's atomic INCR/DECR make it a natural fit for view counts, rate-limit counters, or leaderboard scores
  • Session storage: session data shared across multiple stateless application instances, instead of living in one instance's memory
  • Rate limiting: atomic increment-and-check patterns implement token bucket or sliding window limits without a race condition
  • Lightweight coordination: simple distributed locks (SET key value NX EX ttl) for short-lived mutual exclusion — not a substitute for a real consensus system for anything critical
  • Queues: Redis lists or streams as a simple message queue when a full broker like Kafka or RabbitMQ would be overkill

Redis use cases and the primitive behind each

Redis use cases and the primitive behind each
Use caseRedis primitiveWhy Redis fits
CacheString/hash + TTLSub-millisecond reads, built-in expiration
CounterINCR/DECR (atomic)No race condition on concurrent increments
Session storeHash or string, keyed by session IDShared across stateless app instances
Rate limiterINCR + EXPIRE, or sorted set for sliding windowAtomic check-and-increment in one round trip
Lightweight lockSET key val NX EX ttlAtomic "set if not exists" with automatic expiry
Simple queueList (LPUSH/RPOP) or StreamFast, ordered, no separate broker needed for simple cases
What Redis is used for, beyond caching

Cache

string/hash + TTL

Counter

atomic INCR/DECR

Session store

shared across instances

Rate limiter

INCR + EXPIRE

Lightweight lock

SET NX EX

Simple queue

list or stream

  1. Cache — string/hash + TTL
  2. Counter — atomic INCR/DECR
  3. Session store — shared across instances
  4. Rate limiter — INCR + EXPIRE
  5. Lightweight lock — SET NX EX
  6. Simple queue — list or stream

Command

text
INCR page_views:42          -- atomic counter
SET session:abc "{...}" EX 1800  -- session with TTL
SET lock:job-1 "worker-a" NX EX 30  -- lightweight lock
LPUSH queue:emails "{...}"  -- simple queue push

Redis fits anything that needs fast, shared, short-lived state: caching, atomic counters, session storage, rate limiting, lightweight locks, simple queues — not as a substitute for a durable primary store or a full-featured message broker when the workload genuinely needs one.

2.Redis data structures, atomicity and pipelines

Redis is not just a key-value string store — it offers several distinct data structures (hashes, lists, sets, sorted sets, streams) natively, each with commands that operate atomically on the server. Pipelining batches multiple commands into one round trip for throughput; Pub/Sub broadcasts messages to subscribers with no storage; Streams add an append-only, replayable log on top.

Key features

  • String: the most basic type — text, a number, or serialized bytes; supports atomic INCR/DECR when numeric
  • Hash and List: a hash is a field-value map under one key (good for object-like records); a list is an ordered sequence supporting push/pop from either end
  • Set and sorted set: a set is an unordered collection of unique strings with O(1) membership checks; a sorted set adds a score per member, kept in order — the standard leaderboard structure
  • Pipelining: sending multiple commands in one network round trip instead of one round trip per command, cutting latency for a batch of operations
  • Pub/Sub: publishers broadcast to a channel, subscribers receive live — messages are not stored, so a subscriber that wasn't listening misses them
  • Streams: an append-only log (unlike Pub/Sub) that persists entries and supports consumer groups reading at their own pace

The five core data types and what each is good for

The five core data types and what each is good for
TypeShapeGood for
StringSingle value per keyCache values, counters, flags
HashField-value map per keyObject-like records (a user, a product)
ListOrdered sequenceSimple queues, recent-activity feeds
SetUnordered unique membersTags, unique-visitor tracking, set operations
Sorted setUnique members with a score, orderedLeaderboards, priority queues, range queries
The five core data types

String

single value per key

Hash

field-value map

List

ordered sequence

Set

unordered, unique members

Sorted set

unique + scored, ordered

  1. String — single value per key
  2. Hash — field-value map
  3. List — ordered sequence
  4. Set — unordered, unique members
  5. Sorted set — unique + scored, ordered

Command

text
HSET user:42 name "Ada" email "ada@example.com"
LPUSH recent:42 "viewed:product-99"
SADD tags:99 "sale" "featured"
ZADD leaderboard 1500 "player-7"
XADD events:orders '*' order_id 42 status "placed"

Five core data structures — string, hash, list, set, sorted set — each with atomic commands. Pipelining batches commands into one round trip. Pub/Sub broadcasts live with no storage; Streams add a persistent, replayable log.

3.Cache stampede, hot keys and memory pressure

These are three specific ways a distributed cache breaks down under real load. A cache stampede (or dogpile) happens when a popular key expires and many concurrent requests all miss at once, hammering the backend simultaneously. A hot key is a single key receiving disproportionate traffic, which can overload the one Redis node/shard holding it even if the cluster overall has capacity. Memory pressure is Redis running low on memory and having to evict data, sometimes unpredictably.

Key features

  • Cache stampede (dogpile): a popular key expires, and many concurrent requests all miss simultaneously, all hitting the backend at once instead of one request refilling the cache for everyone
  • A common fix: only one request refills the cache on a miss (a short-lived "refilling" lock), while others either wait briefly or serve a stale value
  • Hot key: one key receives far more traffic than others — in a sharded/clustered cache, all that traffic lands on a single node, which can bottleneck even with total cluster capacity to spare
  • Hot key fix: replicate the hot value across multiple keys/nodes (e.g. key_0 through key_9, chosen randomly by the client) to spread the load
  • Memory pressure: Redis evicts data under an eviction policy (e.g. LRU) once it approaches its configured memory limit — eviction under pressure can remove keys a team assumed were safe

Three distinct failure modes and their fixes

Three distinct failure modes and their fixes
ProblemCauseCommon fix
Cache stampedeMany concurrent misses on the same expired keyRefill lock (single-flight), staggered/jittered TTLs
Hot keyTraffic concentrated on one key, one shardReplicate the value across multiple keys, client-side load spreading
Memory pressureCache nears its memory limitRight-size memory, choose an eviction policy deliberately, monitor evictions
Three ways a distributed cache breaks under load

Stampede

concurrent misses hit the backend at once

Hot key

one key overloads one node

Memory pressure

eviction under a memory limit

  1. Stampede — concurrent misses hit the backend at once
  2. Hot key — one key overloads one node
  3. Memory pressure — eviction under a memory limit

Command

text
-- single-flight refill lock (prevents a stampede)
if SET lock:key1 1 NX EX 5:
    value = recompute_expensive_thing()
    redis.set("key1", value, ex=300)
    redis.delete("lock:key1")
else:
    return stale_or_wait()

Cache stampede: many concurrent misses on one expired key hit the backend at once — fix with a single-flight refill lock or jittered TTLs. Hot key: one key overloads one node — fix by spreading it across several keys. Memory pressure: watch eviction counts, not just memory usage.

Remember

  • Redis is fast, shared, short-lived state — not a durable primary store by default.
  • Sorted sets give O(log N) ranking and range queries — the standard leaderboard structure.
  • Pub/Sub delivers only to currently connected subscribers; Streams persist and support replay.
  • A cache stampede hits the backend hardest at exactly the moment a popular key expires — guard it explicitly.

Pro tip

  • Add small random jitter to TTLs on related keys to avoid synchronized, recurring stampedes.
  • Monitor evicted_keys directly — memory usage alone can look fine right after Redis has already evicted data.

Next up

  • CDN and edge caching
  • Messaging and queues
  • Distributed locks

Sources

  • Redis documentation — redis.io/docs, fetched 2026-08-21
  • Checked 2026-08-21

Spotted a mistake on this page? Tell us.