What it is
A cache keeps a copy of data you use a lot somewhere faster than where it normally lives, usually in memory with something like Redis or Memcached. Reads get quicker and your database gets a break. Things get tricky when the original data changes.
How it works
The usual setup is called cache-aside. Your app checks the cache first, and fills it when the data's not there.
| Strategy | How it works | Watch out for |
|---|---|---|
| Cache-aside | App fills on read, clears on write | Stale data right after a write |
| Write-through | Write to the cache and database together | Slower writes |
| Write-back | Write to the cache, database later | Losing data if the cache dies |
Trade-offs
You're always trading freshness for speed. A short expiry means fresher data but more trips to the database. When you run out of memory, an eviction policy like LRU decides what gets dropped.
In an interview
- Say why you need it: how many reads versus writes, and how stale the data can be.
- Be specific about what you're storing, what the key is, and how things get removed.
- Talk about what happens if the cache is empty or down.
Worked example
Caching product pages
A store serves 50,000 product page views a second, and each one needs the product's details from the database. The database is comfortable at about 5,000 reads a second. Prices change a few times a day.
- Without a cache, the database is 10 times over its limit. With cache-aside, the app checks Redis for product:123 first.
- Traffic is lopsided: the top 10% of products get most of the views. With a 95% hit rate, only 2,500 reads a second reach the database, which is fine.
- Each entry gets a 10-minute expiry. Even if you forget to clear something, it's never more than 10 minutes stale.
- When a price changes, the update writes the database and then deletes product:123 from the cache. The next read fills it again with the new price.
- A big sale page goes live and its cache entry expires. Thousands of requests miss at once. A lock lets only one request rebuild it, and the rest wait briefly or get the old copy.
- If Redis goes down, every request hits the database at 10 times its limit. So you'd want Redis replicas, and a limit on how many requests can fall back to the database at once.
Follow-up questions
Things interviewers tend to ask once you've brought this up.
- Delete the cache entry or update it on write?
- Deleting is safer. If two writes race and each updates the cache, the older one can land last and stick around. Deleting means the next read gets the latest value from the database.
- How do you decide the expiry time?
- From how stale the data can be. Prices that must be right at checkout can be re-checked there, so the product page can be a few minutes stale.
- Where else can you cache?
- In the browser, at a CDN for static or public content, in the app's own memory, and in a shared cache like Redis. Closer to the user is faster but harder to clear.
- What do you do about one key that gets huge traffic?
- Keep a copy in each app server's memory for a few seconds, or make several copies of the key in Redis so the load spreads across nodes.
Common mistakes
- Adding a cache without saying what it's for or how stale it can be.
- Caching data that changes on every request, so the hit rate is near zero.
- Not planning for a cold or failed cache.
- Forgetting to clear entries when the data changes.
- Caching per-user data under a key that isn't per user, so people see each other's data.