Redis Caching in Node
Introduction
Redis is an in-memory data store used for caching, session storage, rate limiting, and lightweight queues. Node apps use clients like ioredis or redis to get/set keys with TTL (time-to-live). This chapter complements databases and message queues.
Prerequisites
When to Cache
Cache expensive or slow results:
- Heavy database aggregations
- Third-party API responses allowed to be slightly stale
- Rendered HTML fragments
Do not cache personalized secrets without careful key design and TTL.
Connect to Redis
bash
npm install ioredisjavascript
// redis-client.mjs
import Redis from "ioredis";
export const redis = new Redis(process.env.REDIS_URL ?? "redis://127.0.0.1:6379");
redis.on("error", (err) => console.error("Redis error", err.message));Run Redis locally via Docker:
bash
docker run -d -p 6379:6379 redis:7-alpineSet and Get with TTL
javascript
// Cache JSON for 60 seconds
const key = "user:42:profile";
await redis.set(key, JSON.stringify({ id: 42, name: "Ada" }), "EX", 60);
const cached = await redis.get(key);
if (cached) {
console.log("hit", JSON.parse(cached));
} else {
console.log("miss");
}EX 60 expires the key automatically.
Cache-Aside Pattern
javascript
async function getUserProfile(userId) {
const key = `user:${userId}:profile`;
const hit = await redis.get(key);
if (hit) return JSON.parse(hit);
const profile = await loadFromDatabase(userId);
await redis.set(key, JSON.stringify(profile), "EX", 300);
return profile;
}
async function loadFromDatabase(userId) {
return { id: userId, name: "From DB" };
}
console.log(await getUserProfile(1));
console.log(await getUserProfile(1));On update, invalidate cache: await redis.del(key).
Rate Limiting (Simple Counter)
javascript
async function allowRequest(ip) {
const key = `rl:${ip}`;
const count = await redis.incr(key);
if (count === 1) await redis.expire(key, 60);
return count <= 100;
}
console.log(await allowRequest("203.0.113.10"));##Hashes and Sets (Brief)
javascript
// Hash — object-like
await redis.hset("session:abc", "userId", "7", "role", "admin");
const role = await redis.hget("session:abc", "role");
// Set — unique members
await redis.sadd("tags:post:1", "js", "web");
const tags = await redis.smembers("tags:post:1");Mini Example: Memoize API Fetch
javascript
async function fetchPostsCached(userId) {
const key = `posts:${userId}`;
const cached = await redis.get(key);
if (cached) return JSON.parse(cached);
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts?userId=${userId}`
);
const posts = await res.json();
await redis.set(key, JSON.stringify(posts), "EX", 120);
return posts;
}FAQ
Redis vs database?
Redis is fast volatile memory—primary data still lives in PostgreSQL/Mongo with Redis as cache layer.
Cache stampede?
Many misses at once—use locking, early expiry jitter, or prewarm.
Production hosting?
Managed Redis (ElastiCache, Upstash, Redis Cloud) with TLS and auth.