CDNs & Redis in Practice

intermediate caching cdn redis edge in-memory

In theory caching is one idea; in practice we reach for two specific tools over and over. A CDN for caching content close to users, and Redis for caching data close to our app. Let’s make both concrete.

CDN — caching at the edge

A CDN (Content Delivery Network) is a fleet of servers spread across the globe that cache copies of our content near the people requesting it. In simple language — instead of every user in Tokyo fetching an image from our server in Virginia, the CDN keeps a copy on a machine in Tokyo and serves it from there.

The win is distance. Bytes travel at a fixed speed, so a request that stays in-city is dramatically faster than one crossing an ocean. Those nearby servers are called edge locations (or PoPs, points of presence).

Without a CDN
User (Tokyo)
↓ ~9,000 km, every time
Origin (Virginia)
slow + origin does all the work
With a CDN
User (Tokyo)
↓ ~10 km
Edge (Tokyo) — HIT
↓ only on a miss
Origin (Virginia)
fast + origin barely touched

What does the CDN cache? Mostly static assets — images, JS, CSS, videos, fonts — anything identical for every user. We control it with Cache-Control headers on our responses. This is the shared language between our origin and the CDN (and the browser):

Cache-Control: public, max-age=31536000, immutable

public means any cache may store it, max-age=31536000 says “fresh for a year,” and immutable promises it’ll never change (so don’t even revalidate). That combo is how we cache hashed asset files like app.9f2c.js forever — a new build just gets a new hash, so a new URL.

Redis — caching in memory

Redis is an in-memory key-value store. We hand it a key, it hands back a value, and it lives entirely in RAM — which is why it answers in well under a millisecond. It’s the default choice for an application cache and for session storage.

Why is it so fast? Everything is in memory (no disk seek on the read path), it’s single-threaded for commands (no lock contention), and it speaks a tiny, efficient protocol. The catch is that RAM is smaller and pricier than disk, so we cache the hot subset, not everything.

The GET/SET basics look exactly like you’d hope:

SET user:42 "Manish" EX 300   # store, expire in 300 seconds
GET user:42                    # -> "Manish"  (a HIT)
TTL user:42                    # -> 287        (seconds left)
DEL user:42                    # invalidate on write

Redis isn’t just strings, either — that’s the other reason we love it. It ships real data types: hashes (objects), lists (queues), sets and sorted sets (leaderboards, rate limiters), and more. So a session or a “top 10 today” list is a native structure, not something we serialize by hand.

On persistence: Redis is memory-first but can save to disk so it survives a restart — RDB takes periodic point-in-time snapshots, AOF logs every write for finer-grained recovery. For a pure cache we often don’t even need it; for a session store we usually do.

CDN vs Redis — which one?

They cache different things at different layers, so it’s rarely either/or — most stacks run both. But the distinction matters in interviews:

Reach for a CDN
Static, public, identical-for-everyone content — images, JS/CSS, video. Cached at the edge, near users, keyed by URL.
Reach for Redis
Dynamic, per-user, per-query data — sessions, query results, counters. Cached in memory, near the app, keyed by whatever we choose.

Rule of thumb: CDN for content, Redis for data. If it’s the same file for every visitor and travels far, push it to the edge. If it’s computed per request and we just don’t want to recompute it, keep it in Redis next to the app.

Interview soundbite

A CDN caches static assets at edge locations near users to kill network latency, driven by Cache-Control headers — great for images, JS, CSS. Redis is an in-memory key-value store (with real data types and optional RDB/AOF persistence) used as the application cache and session store — sub-millisecond because it’s all in RAM. CDN for content at the edge, Redis for data at the app; big systems use both.