If you have worked on a backend in the last decade, you have probably touched Redis. Not always knowingly. It is quietly powering session storage, caching layers, rate limiters, job queues, and real-time leaderboards across most of the apps you use daily. But it did not start as a grand database project. It started as one developer's fix for a problem nobody else was solving well enough.
Who Built Redis, and Why
Redis was created in 2009 by Salvatore Sanfilippo, an Italian developer known online as antirez. He was building LLOOGG, a real-time web log analytics tool, and needed to push huge volumes of analytics events and pull back recent page views fast. MySQL, the default choice at the time, simply could not keep up with that access pattern at scale.
Instead of throwing more servers at the problem, he asked a different question: what if the database just lived in RAM? No disk seeks, no query planner overhead, just data structures in memory with simple, atomic commands on top. That idea became Redis, short for REmote DIctionary Server.
Redis was not designed in a boardroom. It was carved out of a real, specific performance wall, and that is a big part of why it stayed so simple.
What Problem Does Redis Actually Solve?
Traditional databases are built to be durable and consistent first, fast second. Redis flips that priority. By keeping the entire dataset in memory, it gives you:
- Sub-millisecond reads and writes with no disk I/O on the hot path
- Rich data structures out of the box: lists, hashes, sets, sorted sets, streams, and bitmaps, not just strings
- Atomic operations like
INCR,LPUSH, andZADDthat run without explicit locking - A single-threaded command core that sounds like a limitation but is actually what makes Redis predictable. No race conditions between commands, no lock contention to debug at 2am
A Quick Example
SET user:1042:session "a8f9c2" EX 3600
INCR page:home:views
ZADD leaderboard 9800 "player_42"
ZRANGE leaderboard 0 9 REV WITHSCORES
Four commands, four different problems solved: a session with auto-expiry, an atomic counter, a leaderboard insert, and a top-10 query.
The Data Structures
The reason developers love Redis is not speed alone. It is that the data structures match real problems. Instead of forcing everything into rows, you pick the structure that fits.
| Type | What it is | Typical use | Example commands |
|---|---|---|---|
| String | Text, numbers, or bytes | Cache values, counters, tokens | SET, GET, INCR |
| Hash | Field-value map | User profiles, small objects | HSET, HGETALL |
| List | Ordered list | Queues, recent activity | LPUSH, RPOP |
| Set | Unique, unordered values | Tags, unique visitors | SADD, SISMEMBER |
| Sorted set | Unique values with scores | Leaderboards, scheduling | ZADD, ZRANGE |
| Stream | Append-only log | Event streaming, consumer groups | XADD, XREADGROUP |
| Bitmap / HyperLogLog | Compact counting structures | Daily active users, unique counts | SETBIT, PFADD |
How Redis Works Under the Hood
Redis runs commands on a single main thread using an event loop. Because commands execute one at a time, each one is atomic by nature. There is no need for locks inside Redis, which removes a whole class of concurrency bugs. Modern versions use extra threads for network I/O, but command execution stays sequential.
That sounds slow until you remember that operations on in-memory data take microseconds. A single Redis instance can often handle tens or hundreds of thousands of operations per second, limited more by the network than by the CPU.
But What If The Server Restarts?
Memory is volatile, so Redis offers persistence options to save data to disk:
| RDB snapshots | AOF (append-only file) | |
|---|---|---|
| How it works | Saves a point-in-time snapshot at intervals | Logs every write command |
| Data loss risk | Can lose changes since the last snapshot | Very small, depends on fsync setting |
| File size | Compact | Larger, rewritten periodically |
| Restart speed | Fast | Slower |
Many production setups use both: AOF for durability and RDB for fast backups. Others disable persistence completely when Redis is only used as a cache, since losing the cache just means a slower warm-up.
Eviction: When Memory Runs Out
RAM is finite. When Redis reaches its maxmemory limit, it uses an eviction policy to decide what to remove.
- noeviction: refuse new writes with an error. Safe for data you cannot lose.
- allkeys-lru: remove the least recently used keys. The most common choice for caches.
- allkeys-lfu: remove the least frequently used keys.
- volatile-lru / volatile-ttl: only evict keys that have an expiry set.
Five Patterns Every Backend Developer Should Know
1. Cache-Aside
The most common pattern. Your app checks Redis first, falls back to the database on a miss, then stores the result.
async function getUser(id) {
const key = `user:${id}`
const cached = await redis.get(key)
if (cached) return JSON.parse(cached)
const user = await db.users.findById(id)
await redis.set(key, JSON.stringify(user), 'EX', 300)
return user
}
2. Rate Limiting
Count requests per user per window, and reject when the limit is passed.
const key = `rate:${userId}:${Math.floor(Date.now() / 60000)}`
const count = await redis.incr(key)
if (count === 1) await redis.expire(key, 60)
if (count > 100) throw new Error('Too many requests')
3. Sessions
Store session data under a random token with a time-to-live. When the key expires, the session ends on its own, with no cleanup job.
4. Leaderboards
Sorted sets keep entries ordered by score automatically. Inserting a score and fetching the top 10 are both fast, even with millions of players.
5. Queues and Pub/Sub
Lists can act as simple job queues, streams support consumer groups for reliable processing, and pub/sub sends real-time messages to subscribers. Tools like BullMQ build full job systems on top of Redis.
Redis vs Other Options
| Redis | Memcached | PostgreSQL / MySQL | |
|---|---|---|---|
| Data model | Many structures | Simple key-value | Relational tables |
| Persistence | Optional (RDB, AOF) | None | Always |
| Speed | Sub-millisecond | Sub-millisecond | Milliseconds |
| Replication and clustering | Built in | Limited | Yes, more complex |
| Best for | Caching, queues, real-time features | Pure caching | Source of truth |
The License Change That Split the Community
For most of its life, Redis shipped under the permissive BSD-3-Clause license. That changed in March 2024, when Redis Ltd. moved future versions to a dual SSPL / RSALv2 license, no longer OSI-approved open source. The community response was immediate. The Valkey project forked from Redis 7.2.4 under the Linux Foundation, picking up backing from AWS, Google Cloud, and others almost overnight.
In 2025, Redis added the AGPLv3 license as an option for Redis 8, which brought it back to an OSI-approved license. Today you will see Redis, Valkey, and several compatible managed services in the wild, and for most application code the commands are the same.
When Should You Reach for Redis?
- A caching layer in front of a slower primary database
- Session storage that expires automatically
- Rate limiting with a sliding window counter
- Real-time leaderboards or rankings
- A lightweight pub/sub layer or job queue
- Counting unique visitors with HyperLogLog
It is a worse fit when your dataset does not fit comfortably in RAM, when you need strong relational guarantees and complex joins, or when durability requirements mean you cannot tolerate data living primarily in memory.
Common Mistakes
- Using Redis as the only copy of important data without proper persistence and backups.
- Forgetting to set expiry on cache keys, so memory slowly fills up.
- Running slow commands such as
KEYS *in production. UseSCANinstead. - Storing huge values, which blocks the single thread while they are read or written.
- Exposing Redis to the public internet without authentication or network rules.
The Verdict
Redis is one of those tools that earns its place by being simple. It does not try to replace your main database. It sits beside it and takes over the jobs where speed matters most. Learn the five patterns above and you will solve a surprising share of backend performance problems with a few lines of code.
If you want to go deeper, the official Redis documentation is genuinely well written, and the source code on GitHub is surprisingly approachable if you are curious how a single-threaded event loop handles this much throughput.
