Redis — The Speed Demon
Super-Fast Temporary Storage
Open interactive version (quiz + challenge)Real-world analogy
Your database (MongoDB) is like a filing cabinet — organized, reliable, but takes a few seconds to find things. Redis is like a sticky note on your desk — INSTANTLY readable! You put frequently needed info on the sticky note so you don't keep opening the cabinet.
What is it?
Redis is an open-source, in-memory data store used as a cache, message broker, and database. It stores data in RAM (not disk), making it incredibly fast but limited in size. Think of it as a turbo-charged, temporary storage layer.
Real-world relevance
Twitter uses Redis to cache timelines. GitHub uses it for job queues. Stack Overflow uses it for caching. Almost every high-traffic app has Redis somewhere in its stack.
Key points
- In-Memory Storage — Redis stores data in RAM, not on disk — reads take about 0.1ms vs 10-100ms for disk-based databases. This speed makes Redis perfect for data accessed thousands of times per second with minimal latency.
- Cache Layer — Place Redis between your app and database to cache frequent data. When 100 users request the same page, the DB is queried once — Redis serves the other 99 instantly. Cuts database load dramatically.
- Sessions & Auth — Store session data in Redis so every request quickly verifies who is logged in. Session checks happen on every API call and must be fast. Redis handles millions of lookups per second, ideal for sessions.
- Rate Limiting — Track API requests per user or IP using Redis counters with automatic expiration. If a user exceeds 100 requests per minute, return 429. Atomic increments prevent race conditions and protect against abuse.
- Pub/Sub Messaging — Redis pub/sub lets services broadcast messages to multiple subscribers in real-time. Use it for live chat, notifications, or coordinating between server instances. Publish to a channel and all subscribers get it.
- Data Structures — Beyond simple key-value, Redis offers Lists for queues, Sets for unique collections, Hashes for object-like data, and Sorted Sets for leaderboards. Each type has specialized commands for atomic operations.
- Expiration Keys — Set a TTL on any key: SET key value EX 300 auto-deletes after 300 seconds. Perfect for temporary tokens, OTP codes, cache entries that should refresh, and rate limit counters. No cleanup needed!
- Cache Invalidation — Keeping cached data fresh is critical. Use TTL expiration for simple cases, or actively delete cache keys when data changes. Common patterns: cache-aside, write-through, and write-behind with different tradeoffs.
- Persistence Options — Although in-memory, Redis can persist to disk: RDB snapshots (periodic saves) or AOF logs (append every write). RDB is faster for restarts, AOF offers better durability. Many setups use both for safety.
- Atomic Operations — Redis commands are atomic — they complete fully or not at all, even under heavy load. INCR safely increments counters, SETNX sets values only if absent (great for distributed locks). No race conditions!
Code example
// Without Redis — database gets hammered 😵
// 100 users visit the homepage in 1 minute:
// → 100 database queries (each takes 200ms)
// → Database: "I'm TIRED! 😫"
// With Redis — database chills 😎
// Request 1:
User → Backend → Redis (miss!) → Database (200ms)
→ Store in Redis (cache it!)
// Requests 2-100:
User → Backend → Redis (HIT! 2ms) → "Here's your data!"
→ Database: *sipping coffee* ☕
// Redis in your docker-compose.yml:
services:
redis:
image: redis:7-alpine
ports:
- "6379:6379"
// Using Redis with NestJS:
import { CACHE_MANAGER } from '@nestjs/cache-manager';
@Injectable()
export class CacheService {
constructor(@Inject(CACHE_MANAGER) private cache: Cache) {}
async getProperty(id: string) {
// Check Redis first
const cached = await this.cache.get(`property:${id}`);
if (cached) return cached; // Cache HIT! ⚡
// Cache miss — ask database
const property = await this.prisma.property.findUnique({
where: { id },
});
// Store in Redis for next time (expire in 5 min = 300,000ms)
await this.cache.set(`property:${id}`, property, 300_000);
return property;
}
}Line-by-line walkthrough
- 1. Without Redis — database gets hammered 😵
- 2. 100 users visit the homepage in 1 minute:
- 3. → 100 database queries (each takes 200ms)
- 4. → Database: "I'm TIRED! 😫"
- 5.
- 6. With Redis — database chills 😎
- 7. Request 1:
- 8.
- 9.
- 10.
- 11. Requests 2-100:
- 12.
- 13.
- 14.
- 15. Redis in your docker-compose.yml:
- 16. Docker Compose section definition
- 17.
- 18.
- 19.
- 20.
- 21.
- 22. Using Redis with NestJS:
- 23. Importing required dependencies
- 24.
- 25. Decorator that adds metadata or behavior
- 26. Exporting for use in other files
- 27.
- 28.
- 29.
- 30. Check Redis first
- 31. Declaring a variable
- 32. Conditional check
- 33.
- 34. Cache miss — ask database
- 35. Declaring a variable
- 36.
- 37.
- 38.
- 39. Store in Redis for next time (expire in 5 min)
- 40. Waiting for an async operation to complete
- 41. Returning a value
- 42. Closing block
- 43. Closing block
Spot the bug
async getUser(id: string) {
const cached = await this.cache.get("user:" + id);
if (cached) return cached;
const user = await this.prisma.user.findUnique({ where: { id } });
await this.cache.set("user:" + id, user);
return user;
}Need a hint?
What happens when the cached data gets stale?
Show answer
The cache has no expiration (TTL), so data stays forever even if the user updates their profile. Fix: add a TTL: await this.cache.set('user:' + id, user, 300_000) to expire after 5 minutes (NestJS cache-manager uses milliseconds).
Explain like I'm 5
You have a book report due. Reading the book from the library (database) takes 30 minutes. But if you write important notes on a sticky note (Redis), next time you can read your notes in 5 seconds! Redis is that super-fast sticky note for your app.
Fun fact
Redis can handle over 100,000 operations PER SECOND on a single server. That's like a librarian who can find and return 100K books every second! 📚💨
Hands-on challenge
Build a rate limiter using Redis: track how many API requests each user makes per minute. Use INCR to count requests and EXPIRE to reset the counter after 60 seconds. If a user exceeds 100 requests, return a 429 Too Many Requests response. Bonus: use a Redis sorted set to build a real-time leaderboard!
More resources
- Redis Documentation (Redis Official)
- Redis University (Redis University)
- Redis in 100 Seconds (Fireship)