Advanced14 min readLevel 2

Redis

An in-memory data structure server that does far more than caching.

Introduction

Redis is a single-threaded, in-memory data store that keeps data in RAM for microsecond access. It is best known as a cache, but its rich data structures (strings, hashes, sets, sorted sets, streams) make it a Swiss-army knife for caching, rate limiting, queues, leaderboards, locks, and pub/sub.

Why it exists

Applications repeatedly need a fast shared place to put small, hot pieces of state — a cache entry, a counter, a session, a lock, a queue. A relational database is the wrong tool: too slow and too general. Redis gives you a shared, atomic, in-memory store with data structures that make these patterns one or two commands instead of hand-rolled logic.

Analogy

Redis is the kitchen's mise en place: a set of small, labeled containers within arm's reach holding exactly what you reach for constantly. It's not the pantry (the database) — it's the fast, organized surface you actually cook from.

How it works

Redis holds everything in memory and processes commands on a single thread, which means each command is atomic — no locks needed for INCR or SETNX. This is why Redis is a natural fit for counters, locks, and rate limiters.

Durability is optional and tunable: RDB snapshots periodically, AOF logs every write; you trade durability for speed. For scale, Redis offers replication (replicas for read scaling and failover), Sentinel (automatic failover), and Cluster (sharding across nodes by hash slot). Because it's in-memory, capacity is bounded by RAM and an eviction policy (e.g. allkeys-lru) decides what to drop when full.

Beyond key/value, the data structures are the point: hashes for objects, sorted sets for leaderboards and rate windows, streams for durable logs/queues, and pub/sub for fan-out messaging.

  1. 1

    App sends a command over a persistent connection (from a pool).

  2. 2

    Redis executes it on its single command thread — atomically.

  3. 3

    Writes are optionally appended to AOF / captured by RDB for durability.

  4. 4

    Writes replicate asynchronously to replicas for read scaling and failover.

  5. 5

    If the primary dies, Sentinel/Cluster promotes a replica to primary.

Interactive

Architecture

Redis with replication and failover

App instances

Primary (writes)

Redis Primaryin-memory

Replicas (reads + standby)

Replica
Replica

Durability (optional)

RDB / AOF

Single-threaded command processing makes operations atomic; Sentinel promotes a replica if the primary fails.

In code

TypeScriptAtomic rate limiting with INCR + EXPIRE
import { redis } from "@/lib/redis"

// Fixed-window limiter: 100 requests per user per minute.
export async function allow(userId: string): Promise<boolean> {
  const key = `rl:${userId}:${Math.floor(Date.now() / 60000)}`
  const count = await redis.incr(key)     // atomic — no race across instances
  if (count === 1) await redis.expire(key, 60)
  return count <= 100
}
TypeScriptA leaderboard with a sorted set
// Add/update a score, then read the top 10 with ranks.
await redis.zadd("leaderboard", 4200, "user:42")

const top = await redis.zrevrange("leaderboard", 0, 9, "WITHSCORES")
const rank = await redis.zrevrank("leaderboard", "user:42") // 0-based position

In the real world

Where you've seen this

A social app uses one Redis for several jobs: caching user profiles (hashes), rate limiting the API (INCR windows), a real-time leaderboard (sorted set), ephemeral sessions (strings with TTL), and fan-out notifications (pub/sub). Each of these would be awkward and slow in the primary database.

When to use it

Reach for it when

  • Caching hot data and expensive computations.
  • Atomic counters: rate limiting, quotas, metrics.
  • Leaderboards, ranking, and time-window queries (sorted sets).
  • Ephemeral state with TTLs: sessions, short-lived tokens.
  • Lightweight queues/streams and pub/sub fan-out.

Avoid it when

  • As the primary system of record for durable business data.
  • Datasets far larger than available RAM (cost/eviction issues).
  • Complex multi-entity queries, joins, and reporting.
  • Strong cross-key transactional guarantees across a cluster.

Trade-offs

Advantages

  • Microsecond latency; extremely high throughput.
  • Atomic operations without app-side locking.
  • Rich data structures that collapse common patterns into single commands.
  • TTLs and eviction built in.

Disadvantages

  • RAM-bound and comparatively expensive per GB.
  • Durability is a trade-off; default configs can lose recent writes on crash.
  • Cluster mode complicates multi-key operations (keys must share a slot).
  • A single hot key can bottleneck one shard.

Redis trades durability and capacity for speed. You choose how durable (none / RDB / AOF everysec / AOF always) against how fast, and RAM cost against dataset size. Cluster gives horizontal scale but sacrifices easy multi-key atomicity. As a cache it's near-perfect; as a database it's viable only when you accept and configure for its durability and memory characteristics.

Redis vs MemcachedRedisMemcached
Data typesStrings, hashes, sets, sorted sets, streamsStrings only
PersistenceOptional (RDB/AOF)None
Replication/HAYes (Sentinel/Cluster)No (client-side sharding)
Best forVersatile: cache, counters, queues, rankingPure, simple, multi-threaded caching

Common mistakes

Watch out for

  • Treating Redis as a durable database and losing data on restart.
  • Big keys / big values that block the single thread (e.g. huge `KEYS` scans).
  • Using `KEYS *` in production instead of `SCAN`.
  • Ignoring eviction policy, so the cache silently drops needed keys.
  • No connection pooling, exhausting connections under load.

Failure thinking

What breaks it

What happens if Redis goes down and you used it as a cache?

Reads fall through to the database, which can be overwhelmed (see cache stampede/cascading failure). Use short timeouts, treat errors as misses, coalesce origin calls, and protect the DB with a circuit breaker. If Redis held the only copy of something (a queue, a session), you lose it unless AOF/replication was enabled — which is why Redis-as-source-of-truth needs durability and failover configured.

One key becomes extremely hot (a celebrity's profile). What breaks?

In Cluster mode that key lives on one shard, so all traffic concentrates on a single node and single thread — a hot key bottleneck. Mitigate with client-side/local caching of that key, replicating reads to replicas, or splitting the value across multiple keys. Hot keys can't be solved by adding shards because a key maps to one slot.

Think like a senior

Senior Engineer Insight

Redis being single-threaded is a feature, not a limitation: it's why `INCR`, `SETNX`, and Lua scripts are atomic without distributed locks. Reach for a Lua script or `MULTI` when you need multiple commands to be atomic.

Senior Engineer Insight

The interview trap is 'use Redis' as a hand-wave. Say which data structure and why — a sorted set for windows, a hash for objects, a stream for a durable queue — and address hot keys and failure.

Remember

Redis is single-threaded, so single commands are atomic — no external lock needed.

Remember

In-memory means fast but RAM-bound and only as durable as you configure it.

Interview questions

1

Why is Redis a good fit for rate limiting?

Active recall

Check yourself

Redis · Question 1 / 1Medium

You need an eviction policy for a Redis cache holding hot application data with unknown access patterns. Which is the sensible default?

Practical challenges

Medium1–3 hours

Sliding-window limiter with sorted sets

Implement a sliding-window rate limiter in Redis and compare it to the fixed-window version.

Fixed windows allow bursts at window edges. A sliding window smooths this by counting requests in the trailing period.

Requirements

  • Store request timestamps in a sorted set per key.
  • On each request, drop entries older than the window and count the rest.
  • Allow or deny based on the count, all atomically.

Constraints

  • Use a Lua script or MULTI so the read-modify-write is atomic.
  • Expire idle keys.

Acceptance criteria

  • A burst spanning two fixed windows is correctly limited by the sliding window.
  • Old timestamps are cleaned up so memory doesn't grow unbounded.

Edge cases

  • Clock skew across instances.
  • Very high request rate on one key.

Bonus

  • Add the fixed-window version and demonstrate the edge-burst difference.

Reflection

  • What's the memory cost of storing every timestamp, and how would a token bucket compare?

Architecture challenge

You're asked to use Redis for four things in one product: cache, session store, API rate limiter, and a job queue. For each, choose the data structure and the durability/eviction settings — noting that a cache wants eviction and no durability, while a job queue wants durability and no eviction. How do you keep these conflicting needs from fighting over one instance?

Flashcards

Flashcards1 / 4

Summary

Redis is an in-memory, single-threaded data structure server whose atomic operations and rich types make it ideal for caching, counters, rate limiting, ranking, sessions, and lightweight queues. It trades durability and RAM cost for extreme speed, so treat it as a fast shared surface — durable only when you deliberately configure it to be.

Key takeaways

  • Single-threaded ⇒ single commands are atomic ⇒ great for counters and locks.
  • Pick the right data structure: sorted set for ranking/windows, hash for objects, stream for queues.
  • In-memory ⇒ fast but RAM-bound; set an eviction policy for caches.
  • Durability (RDB/AOF) and HA (Sentinel/Cluster) are opt-in — configure them if Redis holds anything you can't lose.

Your notes

Saved to this device