Caching Without Stale Data
A cache keeps a copy of a result somewhere fast so you do not have to compute or fetch it again. It is one of the cheapest ways to make a slow backend feel quick, and one of the easiest ways to show users wrong data. In the Cache Factory, Cache the operator keeps shelves of ready-made answers, and the hard part of the job is knowing when a shelf is out of date.
What is worth caching
Caching pays off when two things are true: the data is read much more often than it changes, and producing it is expensive (a slow query, a call to another API, a heavy calculation). A product catalogue page viewed 10,000 times an hour but edited twice a day is a great candidate. A user's shopping cart, which changes on every click, is not.
When a request finds its answer in the cache, that is a hit. When it does not and has to go to the real source, that is a miss. The share of hits (the hit rate) tells you whether the cache is earning its keep.
Cache-aside in JavaScript
The most common pattern is cache-aside: the application checks the cache first, and on a miss it loads from the database and stores the result for next time.
async function getProduct(id) {
const key = 'product:' + id;
const cached = await cache.get(key);
if (cached) return JSON.parse(cached); // hit
const product = await db.findProduct(id); // miss: go to the source
await cache.set(key, JSON.stringify(product), { ttlSeconds: 300 });
return product;
}
The cache here could be Redis, shared by all your servers, or a simple in-memory Map if you run one process and can accept losing it on restart.
TTL: how long a copy is trusted
A TTL (time to live) tells the cache to throw an entry away after a set time. It is your safety net: even if you forget to clear something, it can only be wrong for at most that long.
Choose the TTL by asking how stale the data can be before it hurts. A list of blog posts can be a few minutes old. A stock level on a checkout page probably cannot be more than a few seconds old. A long TTL means more hits and more risk of stale data; a short one means fresher data and more load on the database.
Invalidation and the stale-data bug
Here is the classic bug: an admin changes a product's price from $20 to $15, the database updates, but the cache still holds the old product for another five minutes. Customers see $20, add it to the cart, and get charged $15, or the other way round.
The fix is to invalidate on write: whenever you change the data, delete the cached copy so the next read loads the new version.
async function updatePrice(id, price) {
await db.updateProductPrice(id, price);
await cache.del('product:' + id); // next read is a miss and loads fresh data
}
Delete after the database write succeeds, not before, or a read that slips in between can put the old value straight back. Deleting is usually safer than writing the new value into the cache yourself, because two updates racing each other can leave the older one in the cache. Keep the TTL as a backstop for any path you miss, such as someone editing the database by hand.
When the cache is full: LRU eviction
Cache memory is limited. When it fills up, the cache must drop something to make room. The usual rule is LRU, least recently used: throw away the entry nobody has asked for in the longest time. Popular items stay because they keep getting read; forgotten ones fall out.
This means a missing entry is normal, not an error. Your code must always be able to fall back to the real source, which cache-aside does naturally.
Never share a key across users
The most damaging caching bug is not staleness but leaking data. If you cache the result of /me or "my orders" under a key like 'current-user', the first user's data is saved there, and the next person who asks gets it.
Anything that depends on who is asking must include that in the key, like 'orders:' + userId. And think twice before caching secrets such as tokens or personal details at all; data you never cached cannot leak from the cache. When a page is the same for everyone, cache it freely. When it differs per user, the key must say so.
Resources
Curated resources for this node are on the way. Use what you already know how to search for, and check back soon.