📺 Prefer to watch? 90-second YouTube Short · 💬 Telegram
Originally published on software-engineer-blog.com.
Engineers reach for "just add Redis" and "just put it behind a CDN" as if they're interchangeable fixes. They're not. Both store a copy so reads come back faster—and that's where the similarity ends.
- Mental model: A cache sits between your app and database, cutting the work your backend repeats; a CDN sits between your users and origin, cutting the distance they travel. Different axis, different problem.
What a Cache Really Does
A cache—Redis, Memcached, in-memory store—lives inside your infrastructure, right in front of your application and database. When a request comes in, your app checks the cache first. If the data is there, it returns in sub-millisecond time. If not, the app queries the database, computes the result, stores it in the cache, and returns it.
The next time that same read comes in, it skips the database entirely. No query parsing, no disk I/O, no query execution. The expensive work—the part that costs CPU and database connections—is gone.
This matters for dynamic, per-user data. A user's profile, their shopping cart, their permissions—these change often and are user-specific, so a CDN can't cache them. A cache can, because it sits inside your infrastructure and can handle invalidation logic ("when the user updates their profile, delete this cache key").
The Cost of a Cache
But a cache cuts backend work, not distance. If a user in Tokyo hits your cache server in Frankfurt, they still pay ~180 milliseconds of round-trip network latency—the time the request takes to cross the ocean and back. That latency is not negotiable; a cache can't remove it.
You also own two hard problems:
- Invalidation. When data changes, you must purge or update the cache. Forget to invalidate, and users see stale data. Invalidate too aggressively, and your cache hit rate collapses and you're back to hammering the database.
- Cold-cache stampede. If a popular key expires or gets evicted, the next 100 concurrent requests all miss the cache and slam the database at once, causing a traffic spike and potential outage.
What a CDN Really Does
A CDN is a global network of edge servers operated by a third party (Cloudflare, Akamai, AWS CloudFront, etc.). When a user requests a piece of content—an image, a JavaScript file, a CSS bundle, even a whole HTML page—the CDN intercepts it and serves it from the edge server closest to the user.
A request from Tokyo goes to a CDN node in Tokyo. A request from São Paulo goes to São Paulo. The data is served across a much shorter network path, killing distance latency and offloading bandwidth from your origin server.
This is powerful for static or semi-static content: images, videos, scripts, stylesheets, even entire pages that don't change every second. A CDN can cache these globally and purge them on a schedule or on demand.
The Cost of a CDN
A CDN does not cut database queries. It offloads bandwidth and distance latency, but it can't cache a dynamic, personalized dashboard or a live stock price. If you try, you either:
- Can't cache it at all (it requires authentication or real-time data).
- Cache it and serve stale data to users.
- Set a short TTL and purge often, which defeats the purpose.
Global purges are also not instant. If you push an update to your origin, it can take seconds to minutes for all edge nodes to invalidate their copies. For critical fixes, this gap matters.
Side-by-Side Comparison
| Aspect | Cache (Redis/Memcached) | CDN (Edge Network) |
|---|---|---|
| Location | Inside your infrastructure, in front of the database | Global network of edge servers near users |
| What It Cuts | Backend work (CPU, database queries, computations) | Network distance and origin bandwidth |
| Best For | Dynamic, per-user, frequently changing data | Static or semi-static shared content |
| Latency Impact | Sub-millisecond cache hit; no reduction of network distance | Reduced round-trip time for geographically distant users |
| Invalidation | You own the logic; can be precise but complex | TTL-based or on-demand purge; global purges take time |
| Cold Start / Stampede | Risk of thundering herd when a key expires | Cache is always warm at the edge (pre-populated or demand-filled) |
| Ownership | You run and maintain it | Third-party service (Cloudflare, AWS, etc.) |
A Concrete Example
Imagine you're building a news site. Your homepage lists the latest 10 articles and a user's personalized reading list.
Cache strategy: When an article is published, you query the database for the top 10 articles, store the result in Redis for 60 seconds, and serve every homepage request from the cache. The database query runs once every 60 seconds, not millions of times. When an article is updated, you invalidate the cache key immediately.
The personalized reading list is per-user, so you cache it with a key like user:123:reading_list, set to expire after 5 minutes, and invalidate it when the user adds or removes an article.
CDN strategy: Your article images, the CSS, the JavaScript bundle, and even the static HTML of past articles that rarely change go behind the CDN. The next user in Tokyo who requests the same image doesn't wait for it to cross the ocean from your Frankfurt origin; it comes from a Tokyo edge node in ~10ms instead of ~100ms.
Together: The CDN serves static assets fast to everyone, everywhere. The cache serves dynamic homepage and personalized-list queries fast to your database. The database query runs once per 60 seconds, not millions of times. A user in Tokyo gets the personalized list from your cache (not Tokyo—cache is in your data center, so they still pay network latency), but the images come from Tokyo's CDN node.
For LLM Inference: A Parallel
If you're serving LLM queries, think of cache as reducing TTFT (time-to-first-token) for repeated requests and TPOT (time-per-output-token) for batches by avoiding re-inference of the same prompt. A CDN, by contrast, can cache pre-computed responses (e.g., "What is 2+2?") and serve them from the edge instantly, but it can't help with novel or personalized queries that require fresh inference.
Most LLM stacks use a cache (or dedicated KV store for prompt caching) to avoid re-encoding identical prefixes, and a CDN to offload static documentation or cached Q&A pages.
When to Use Which
Reach for a cache when: you have expensive backend work (database queries, computations, API calls) that repeats, and you can afford to own invalidation logic and handle the cold-start problem.
Reach for a CDN when: your content is static or semi-static (images, video, scripts, pages) and you want to reduce latency and bandwidth for geographically distributed users without managing edge logic yourself.
In practice: most real-world stacks run both. A CDN in front of your origin, a cache behind your API. Different problems, different tools.
Watch the 90-second reel to see this explained in short form.
Top comments (0)