What to cache, and what not to
🎯You'll be able to
Decide whether a piece of data is worth caching, from how often it's read, how often it changes, and how much a stale copy would hurt.
🏠The everyday picture
A tea stall keeps a big kettle of chai ready because hundreds of people want the same thing every hour. It doesn't pre-make a customer's special order "no sugar, extra ginger": nobody else will want that one.
📘What it really is
- A cache keeps a recent answer so the next request for the same thing doesn't redo the work.
-
Good candidates are read often, change rarely, and expensive to compute: a kitchen's menu with counts, a product page, a configuration list.
-
Poor candidates:
- data that must be exact right now: a wallet balance before a payment, stock during checkout;
- data read once: one customer's order receipt;
-
data that is cheap to fetch with a good index (BE3): caching adds complexity for little gain.
-
Measure the hit rate (share of requests answered from the cache). A cache with a 5% hit rate costs more than it saves.
-
Caches sit at several layers: the browser and CDN (
Cache-Controlheaders), the app's memory, and a shared store such as Redis, which every app instance can use. -
First make the uncached path reasonably fast. A cache in front of a 2-second query leaves every miss at 2 seconds.
📝A worked example
TiffinBox data, judged for caching:
| Data | Reads | Changes | Stale for 5 minutes? | Cache? |
|---|---|---|---|---|
| A kitchen's menu with ratings and 30-day counts | thousands an hour | a few times a day | fine for counts; prices must update at once (Lesson 3) | yes, cleared on change |
| A customer's own order list | a few per customer | each order | confusing ("where's my order?") | no |
| Kitchen capacity left today | many at lunch | every order | could oversell | no; read from the database inside the order transaction (BE2) |
| List of 20 kitchens and areas | many | rarely | fine | yes, long expiry |
🌍Where it's used
- Product and menu pages in shopping and delivery apps.
- Configuration and feature flags read on every request.
- Results of slow calls to other services (BE8), such as delivery-time estimates.
📝Case scenario
A team caches each customer's wallet balance for 60 seconds to lighten the database. A customer pays twice within a minute from two devices; both requests see the cached balance, and both payments go through on money that wasn't there. Balances must be read, and changed, inside a transaction in the database; the cache was the wrong tool.
🖱️Try it
List ten TiffinBox reads (from the kit's routes and your own ideas). For each, decide cache or don't cache, and write the reason. Success: every "don't cache" names the harm a stale copy would cause.
⚠️Common mistakes
- Caching data that must be exact. Sign: oversold slots or wrong balances. Fix: read those from the database in the transaction that uses them.
- Caching before fixing the query. Sign: every cache miss is still painfully slow. Fix: make the database path reasonable first (BE3).
- Not measuring hit rate. Sign: a cache that almost never hits. Fix: count hits and misses; remove caches that don't pay.
🛠️For your project
Project 2 caches the menu endpoint only; the order and wallet-style data in Project 1 stay uncached.
✅Quick check
Name two signs that data is a good fit for caching.
Show the answer
It's read much more often than it changes, and it's expensive to compute.
Why shouldn't checkout read remaining capacity from a cache?
Show the answer
A stale copy could let two customers book the last place; capacity must be checked in the database transaction.
