You deploy a new version of your JavaScript bundle. Users on cached CDN nodes still see the old version. CDN cache invalidation is how you force cached content to be replaced before its TTL expires. It’s more complex than database cache invalidation because the content lives in hundreds of PoPs around the world that must all be notified.
Why CDN Invalidation Is Hard Cache invalidation in a single Redis instance: delete the key.
A CDN has 300 PoPs. Each PoP independently caches content. On a cache miss, each PoP fetches from origin. For a popular asset that isn’t yet cached: 300 PoPs, each with a cache miss, all simultaneously fetching from origin. That’s 300 concurrent origin requests for one piece of content. Origin shield solves this: a second caching tier that sits between all edge PoPs and origin, collapsing those 300 origin fetches into one.
Generating a thumbnail is a one-time cost. Serving it is a continuous cost. For a platform with a billion photos, every profile picture load, every post thumbnail, every image preview is a serve request. Getting the serving architecture right determines whether your image infrastructure is a background cost or a constant fire drill.
URL Structure as Cache Key Every image variant needs a stable, unique URL. The URL structure defines the cache key for the CDN.
When you pan across Google Maps, you’re not downloading one giant image. You’re downloading hundreds of small squares stitched together by your browser. Each square is a tile. The tile system is what makes maps feel fast.
The Tile Grid The world map is divided into a grid at each zoom level. At zoom 0, the entire world is one 256x256 pixel tile. At zoom 1, it splits into 4 tiles.
Reading from cache is easy. Writing is where it gets complicated.
Three strategies, each with a different answer to the question: when does the cache get updated relative to the database?
Write-through updates the cache and the database synchronously on every write. The cache is always consistent with the DB. The downside is that every write pays double the cost: serialize the object, write to cache, write to DB, all in the same request path.
Redis is single-threaded per instance. One key receiving 50,000 reads per second will pin a single CPU core and nothing else on that shard gets processed fast.
This is the hot key problem. Unlike a database where you might add replicas or indexes, a single Redis key is owned by a single shard. Traffic concentration on that key concentrates CPU on that node.
Detection is straightforward: redis-cli --hotkeys scans keyspace and reports access frequency.
Cache fills up. Something has to go. The question is: which thing?
LRU (Least Recently Used) evicts whatever was accessed longest ago. Simple, intuitive, fast to implement with a doubly-linked list and hash map. LFU (Least Frequently Used) evicts whatever was accessed least often. More accurate in theory, more expensive in practice.
The LFU decay problem tripped me up: new items start with zero frequency. A fresh key that’s about to become hot looks identical to a stale key nobody cares about.
Your origin server is in us-east-1. Your user is in Mumbai. That’s 200ms of latency before a single byte transfers. CDNs put your content on a server down the street.
User opens the app. Show the nearest 10 coffee shops. Sounds simple until you realize ’nearest’ means computing distance against millions of locations in under 100ms.
Cache expires. 10,000 requests hit the database simultaneously. Your DB collapses. How request coalescing and probabilistic expiration prevent the stampede.
There are only two hard things in computer science: cache invalidation and naming things. Here’s why invalidation is so tricky, and what actually works.