A key/value cache maps string keys to values and lives in memory, so reads and writes take microseconds instead of milliseconds. It sits in front of slower systems like your database. Think of sticky notes on your monitor versus digging through a filing cabinet. The note is instant, but it's temporary and you can afford to lose it. A cache complements your database; it doesn't replace it: durable data lives in the database, fast and temporary data lives in the cache.
Common reasons you may need one:
- Caching expensive query results so repeat reads skip the database
- Sessions and short-lived auth state
- Rate limiting (counting requests per user per window)
- Short-lived data like one-time passwords
SET writes, GET reads
SET writes a value under a key. GET reads it back. These two operations
are the foundation of almost everything you do with a cache. The most common pattern is
cache-aside: check the cache first; on a miss, load from the database and write
the result back so next time is fast. It's not the only pattern, though:
- Cache-aside (lazy) — the app checks the cache, and on a miss loads from the database and writes the result back. The cache only ever fills with data that's actually been requested.
- Write-through — every write goes to the cache and the database together, so the cache stays warm. Reads never miss on data that's been written, at the cost of writing twice.
- Write-back (write-behind) — writes land in the cache first and are flushed to the database later. Fast, but you can lose data if the cache dies before the flush, so it's used carefully.
How to use it
import { createClient } from "redis";
const cache = createClient();
await cache.connect();
async function getPopularPosts() {
const cached = await cache.get("popular_posts"); // check the cache
if (cached) return JSON.parse(cached); // hit
const posts = await fetchPopularPostsFromDb(); // miss
await cache.set("popular_posts", JSON.stringify(posts)); // fill the cache
return posts;
}
A cache stores strings, not objects. Serialize on the way in with JSON.stringify and
parse on the way out with JSON.parse. A hit means the key was
found; a miss means you fall back to the source.
Collisions
A cache is one shared pool of keys, with no tables or schemas to keep things apart. If two
different pieces of data pick the same key, the second SET silently overwrites the
first. That's a collision. Store a user under 42 and an order under
42, and one clobbers the other. You won't get an error, just wrong data. The fix is
disciplined key naming, which the Namespace Conventions lesson covers in depth.
Exercise
Redis challenge · runs in your browser
SET / GET / DEL — Redis key-value basics
Commands run against an in-browser Redis mock that implements the full ioredis API. Your code works identically against a real Redis instance — just swap in new Redis() from ioredis.