codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
EDU›PostgreSQL in depth + Redis · Kafka›Step 4

Step 4

The five roles of Redis

0 views

The five roles of Redis

Redis is often asked "what is it?" for good reason. It plays five distinct parts.

1. Cache

async function getUser(id: number) {
  const cached = await redis.get(`user:${id}`);
  if (cached) return JSON.parse(cached);
  const u = await db.query("SELECT * FROM users WHERE id=$1", [id]);
  await redis.setex(`user:${id}`, 300, JSON.stringify(u));
  return u;
}

TTL is mandatory.

2. Sessions

const sid = crypto.randomUUID();
await redis.setex(`sess:${sid}`, 3600, JSON.stringify({ userId, role }));
res.cookies.set("session", sid, { httpOnly: true, maxAge: 3600 });

Easy invalidation via DEL; every request hits Redis.

3. Rate limit

const bucket = Math.floor(Date.now() / 60000);
const k = `rl:${ip}:${bucket}`;
const count = await redis.incr(k);
if (count === 1) await redis.expire(k, 120);
if (count > 60) return 429;

4. Pub/Sub

redis.publish("notifications", JSON.stringify({ userId, message }));

const sub = redis.duplicate();
await sub.subscribe("notifications");
sub.on("message", (_, raw) => { /* broadcast via WS */ });

Fan-out events to multiple app instances.

5. Distributed lock

async function withLock(key: string, ttl: number, fn: () => Promise<void>) {
  const acquired = await redis.set(`lock:${key}`, "1", "EX", ttl, "NX");
  if (!acquired) throw new Error("locked");
  try { await fn(); } finally { await redis.del(`lock:${key}`); }
}

6. Separating instances (optional)

  • redis-cache — lossy OK
  • redis-session — losing logs users out
  • redis-queue — job queue

Start with one for MVP.

7. Data structures

Type Use
String cache, counters
Hash field-level object updates
List queue, recent-N
Set unique values (likes, follows)
Sorted Set rankings, timelines
Stream event log (light Kafka alternative)

8. Memory

maxmemory 2gb
maxmemory-policy allkeys-lru

For cache, allkeys-lru evicts the least recently used.

9. Gotchas

  • Missing TTL → memory growth
  • Large values → network/memory waste. Put big blobs in S3.
  • No pool → per-request connect is slow (ioredis handles pool)
  • Pub/Sub treated as persistent queue → messages dropped

10. When you don't need Redis

  • Small traffic, DB is fast enough
  • Single server (no locks / pub-sub required)
  • Next.js unstable_cache + ISR replaces cache

Add Redis when measured bottlenecks demand it.

Closing

Treating Redis as "a fast DB" wastes memory. Pick the role and match the data structure.

Next

  • 05-three-layer-cache

← Step 3

pgvector + HNSW

Step 5 →

3-layer cache strategy