08.07.2026 • 6 min read

DesignFlix 22: Eight Redis Uses and What Can Go Wrong

Most engineers know Redis as a cache. That's often our first introduction to it: put a slow database result in memory and make the next request faster.

Then the application grows. Sessions need to work across servers, a leaderboard needs rankings, and background workers need somewhere to collect jobs. Redis can help with all of these, but the choice of data structure changes what we can safely expect from it.

Let's walk through eight uses, including the decisions that matter after the first successful demo.

1. Keep a copy of something expensive to fetch

Imagine a learning app that shows the same course catalogue to thousands of visitors. Reading it from the database for every page view is unnecessary work if it changes only occasionally.

The application can check Redis first. On a miss, it reads the database and saves a temporary copy. Here's an illustrative command for a small cached result:

SET catalogue:v1 '{"courses":["Python","Databases"]}' EX 60

The copy expires after 60 seconds. That gives us a freshness policy we can explain, but it also means a newly added course might not appear immediately. If the page must reflect a change at once, we need to invalidate or update the cached entry when the catalogue changes.

There's another question worth testing: what happens when Redis is unavailable? Falling back to the database may work at normal traffic, yet overwhelm it during a rush. A cache changes the load the database usually sees, so its failure belongs in our capacity planning.

The eight Redis patterns from the original post
The Fast and the Furious: Tokyo Drift scene

Cache hit. Hold on.

The Fast and the Furious: Tokyo Drift · Tenor · Adapted dialogue

2. Share sessions across application servers

Suppose the app runs on three servers. A customer signs in through one, then their next request reaches another. Keeping session data only in the first server's memory makes that second request awkward.

A shared session store gives each server access to the same session record. The browser carries an unpredictable session ID; the backend uses it to look up the signed-in account and expiry.

Now Redis holds something more important than a catalogue copy. Losing those records could sign people out. Decide whether that is acceptable, how sessions expire, and how logout or account restrictions invalidate them. Don't treat a session store's availability requirements as identical to a disposable cache's.

3. Count requests before they become a problem

The app's login endpoint shouldn't accept unlimited guesses from one source. Redis can hold counters shared by all application servers, so each server doesn't give the same caller a fresh allowance.

A fixed-window limiter can count requests under a key containing the caller and time window. The increment and initial expiry need to happen together, for example in a Lua script. Two independent commands leave a gap where a crash can create a counter that never expires.

Choose the key carefully too. An IP address can represent many people behind a shared connection. For authenticated endpoints, an account-level allowance may better match the policy. The counter implements the rule; deciding who the rule applies to is still our job.

4. Keep a leaderboard in score order

A course challenge needs a live ranking. Redis sorted sets fit this because each member has a score and Redis maintains the ordering.

ZADD challenge:weekly 120 learner:17 95 learner:42
ZREVRANGE challenge:weekly 0 9 WITHSCORES

This retrieves the highest-scoring ten members. The useful part is that we don't have to fetch every score and sort the whole collection in application code for each request.

Define how ties work and where scores come from. If Redis is a fast ranking view of results saved elsewhere, you can rebuild it. If it's the only place those results exist, losing it means losing more than a convenient display.

5. Search by meaning and reuse suitable answers

A learning assistant may receive differently worded versions of the same question. Vector search compares numeric representations of those questions, helping us find related material or candidate cached answers.

That can reduce repeated model calls, but similarity isn't permission to reuse an answer. "Can I access this course?" depends on the account and purchase state, even when the wording is identical.

Check the Redis version and search capabilities your deployment provides. Then test the similarity threshold against real questions, and include relevant account, source-version and freshness boundaries in the cache policy. A cheap wrong answer isn't much of a saving.

6. Give workers jobs they can acknowledge

Generating course certificates doesn't need to hold the page request open. Redis Streams can record jobs for workers, and consumer groups can distribute that work while tracking messages awaiting acknowledgement. The Redis Streams documentation explains those mechanics.

The interesting failure happens after a worker creates a certificate but before it acknowledges the message. Another worker may process it again. Use a stable job ID and make repeat processing safe, rather than assuming delivery means each action happens exactly once.

Persistence, retention and recovery settings matter here. Decide how long entries and pending jobs must remain available before treating a stream as a reliable work queue.

7. Broadcast updates to connected listeners

For a live classroom, Pub/Sub can announce that a poll has opened. Connected subscribers receive the announcement without each checking repeatedly.

But Pub/Sub doesn't keep a backlog for a disconnected subscriber to replay. If a student's connection drops during the announcement, the app needs another way to discover the current poll when they return.

Does this message describe a moment, or does somebody have to complete a piece of work because of it?

That question helps distinguish a live notification from a durable job. Redis supports both kinds of pattern, but they have different promises.

8. Coordinate work with a lock, carefully

Finally, imagine two workers trying to rebuild the same expensive leaderboard. A temporary Redis lock can reduce duplicate work.

A basic lock uses a unique owner value and an expiry. Releasing it must check that the value still belongs to the releasing worker. Otherwise, a delayed worker could delete a newer worker's lock.

Expiry introduces a harder problem: the old worker may still be running when another acquires the lock. For operations where overlapping work would cause damage, the protected system may need a fencing token: an increasing number it checks to reject writes from an older lock holder. Another option is stronger coordination appropriate to the operation. Redis's distributed-lock guidance discusses the assumptions behind these designs.

Start with the promise your feature needs

These eight uses explain why Redis keeps appearing in backend systems. Its data structures let us store and access information in ways that fit particular jobs.

Before adding it to a feature, write down three things: what can be lost, how old the result may be, and what repeated processing would do. Those answers often matter more than the first latency measurement. Once they're clear, choosing between a cache, sorted set, stream, notification channel or lock becomes a much more useful conversation.

Try it yourself

A worker creates a certificate from a Redis Stream job, then crashes before acknowledging it. What should a replacement worker do when it receives that job?

A possible solution

Treat the job as a possible repeat. Use its stable ID to check or enforce whether the certificate already exists, and complete any unfinished work safely before acknowledging it. Acknowledgement records processing progress; it cannot make the external action and acknowledgement one atomic operation by itself.

Share this article with your friends

Know someone who would enjoy this? Send it their way.

WhatsAppLinkedInXEmail