Everyone knows Redis as "that fast cache". And that's right — it's absurdly fast. But using Redis only for cache is like buying a Ferrari to go to the bakery.
The basics nobody remembers
Redis is single-threaded. "But isn't that bad?" No. It's genius.
No locks, no race conditions, no concurrency headaches. Every command is atomic by design. When you understand this, you start seeing possibilities everywhere.
Rate Limiting in 3 lines
Need to limit 100 requests per minute per user?
MULTI
INCR rate:user:123
EXPIRE rate:user:123 60
EXEC
If INCR returns > 100, block. That's it. No library, no database, no state in the app.
The trick is EXPIRE — the key self-destructs. You don't need to clean anything. Redis handles your mess.
Queues without Kafka
"But I need a queue!" No, you probably don't need Kafka. You need:
# Producer
LPUSH queue:emails "{\"to\":\"x@y.com\",\"subject\":\"hi\"}"
# Consumer (blocks until there's something)
BRPOP queue:emails 0
BRPOP is blocking pop — the consumer waits until work appears. No polling, no wasted CPU, no Zookeeper.
When is this enough? When you don't need:
- Message replay
- Multiple consumers on the same item
- Long-term persistence
Spoiler: this covers 80% of cases.
Pub/Sub for the rest of us (that works)
Want to notify all servers when a user logs out?
# Listener
SUBSCRIBE user:logout
# Publisher
PUBLISH user:logout "user:123"
All connected instances receive it. Doesn't persist, doesn't guarantee delivery — but for distributed cache invalidation it's perfect.
Sorted Sets are black magic
Player rankings:
ZADD leaderboard 1500 "player:1"
ZADD leaderboard 2300 "player:2"
ZADD leaderboard 1800 "player:3"
# Top 10
ZREVRANGE leaderboard 0 9 WITHSCORES
# player:1's position
ZREVRANK leaderboard "player:1"
Complexity? O(log(N)) for insertion, O(log(N)+M) for range. Try doing this in PostgreSQL with millions of records and come cry.
The pattern that saved my sanity
Distributed locking with SET NX EX:
SET lock:resource:123 "owner:abc" NX EX 30
NX= only set if it doesn't existEX 30= expires in 30 seconds (deadlock protection)
Returned OK? You have the lock. Returned nil? Someone else has it, wait or give up.
When NOT to use Redis
- Data that doesn't fit in memory (duh)
- Complex queries with JOINs
- When you need real ACID
- Persistence as source of truth (you can, but it's risky)
TL;DR
Redis isn't "just cache". It's a distributed, atomic, and stupidly fast data structure.
If you have a problem involving counters, queues, rankings, locks, or temporary state — Redis probably solves it in a fraction of the code you'd write with other tools.
Read the commands documentation. Seriously. It's one of the best docs out there.