Caching Strategies
Part of the Full Stack Developer Roadmap
In short
The fastest request is the one that never reaches your database. A full stack app can cache in four or five places, and knowing which layer answered is half of debugging stale data.
Deciding what to cache and where — browser cache, CDN, server-side cache (Redis), and client-side query cache (React Query) — across your whole request path.

Think of it like this
Bag, room shelf, library
Need a textbook? First you check your bag. If it's not there, the shelf in your hostel room. Then the college library. Only if the library lacks it do you order from the publisher. Each stop is slower, so you keep favourites close.
Watch it happen
Where does GET /api/products/7 get answered?
1/5The browser checks its HTTP cache. With max-age=60 and a fresh copy, nothing leaves your phone.
The big ideas
What you need to know
Every cache needs an expiry
Pick a TTL per layer. Short for prices and stock, long for images and blog posts.
Plan how to clear it
When data changes, delete the Redis key, invalidate the React Query key, and purge the CDN if needed.
Never share private data
Personal responses must be Cache-Control: private or no-store, or a CDN may serve your cart to a stranger.
Cache close to the user
A hit in the browser beats a hit in Redis, which beats any database query. Cache as high up as is safe.
See it in code
Walk through the code
1app.get("/api/products/:id", async (req, res) => {2 const key = `product:${req.params.id}`;3 const cached = await redis.get(key);4 if (cached) {5 res.set("Cache-Control", "public, max-age=60, s-maxage=300");6 return res.type("json").send(cached);7 }8 9 const product = await db.product.findUnique({ where: { id: req.params.id } });10 if (!product) return res.status(404).json({ error: "Not found" });11 await redis.set(key, JSON.stringify(product), { EX: 300 });12 res.set("Cache-Control", "public, max-age=60, s-maxage=300");13 res.json(product);14});15 16// When an admin edits the product: await redis.del(`product:${id}`);1/4Look in Redis first. On a hit, send the stored JSON without touching the database.
Cache-aside with Redis on the server, plus Cache-Control so browsers and the CDN can cache too. One route, three cache layers.
Save yourself the pain
Common mistakes
Oops
Adding a cache and never deciding how it gets cleared.
Do this instead
Write the invalidation code in the same pull request: what event clears which key, at which layer.
Oops
Putting Cache-Control: public on /api/me or /api/cart.
Do this instead
Use private or no-store for anything tied to a logged-in user.
Your mission
Find the layer that answered
Quick check
You changed a product price, the database shows ₹499, but users still see ₹599 for a few minutes. Most likely cause?
Go deeper
- 1Map every place your full-stack app currently caches data, if any.
- 2Add one deliberate caching layer to a slow, frequently-requested piece of data.
- 3Design your invalidation strategy alongside the cache itself, not as an afterthought.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.