Trade-offs · Foundations
TTL vs explicit cache invalidation
How to choose between letting cache entries expire and deleting them when data changes, with the stale-read numbers.
Asked at: SDE-1SDE-2
The decision
A cache keeps copies of data. A copy is stale when it no longer matches the database. With a time to live (TTL), each entry expires after a set time, and the next read loads fresh data. With explicit invalidation, the app deletes the entry at the moment the data changes. TTL is simple but allows old data for up to one TTL. Explicit invalidation is fresher, but the code must find and delete every copy.
Choose TTL when
- The data changes rarely compared with the TTL. Changes per TTL are far below 1.
- Old data is acceptable for a known time, such as a description that may be an hour old.
- One fact lives in many keys, and you cannot list them all.
- Changes come from places you do not control, such as admin tools or scripts.
Choose explicit invalidation when
- The data must be fresh within seconds, and a short TTL would overload the database.
- The data changes often, so a TTL would hold stale data for most of its life.
- All changes pass through one piece of code that can also delete the entry.
- You can list every key that holds the fact.
The numbers that change the answer
Assumption: reads and changes arrive at random moments. A change lands at a random point in an entry's life, so on average the entry is stale for half a TTL after it.
- stale share of reads = changes per second x TTL / 2
This works only when changes per TTL are below 0.1. Otherwise the entry is stale for most of its life.
Worked example 1 (Assumption: a product price). One product's price changes once every 2,500 seconds, which is 0.0004 per second. The product page gets 50 reads per second.
- TTL 60 seconds: changes per TTL = 0.0004 x 60 = 0.024, so the formula holds. Stale share = 0.0004 x 60 / 2 = 0.012 = 1.2%. That is 50 x 0.012 = 0.6 stale reads per second.
- Budget: you accept 1% stale. Longest TTL = 2 x 0.01 / 0.0004 = 50 seconds.
- Explicit delete: Assumption: the delete comes 5 ms (0.005 s) after the write. Stale share = 0.0004 x 0.005 = 0.000002 = 0.0002%. That is 1.2 / 0.0002 = 6,000 times better than TTL 60.
Worked example 2 (Assumption: a stock count). It changes every 10 seconds, so with TTL 60 there are 6 changes per TTL. Assumption: 50 reads per second, as before. The formula fails. The first change comes about 10 seconds after the fill, so the copy is stale for 50 of 60 seconds: about 83%. With a delete, stale share = 0.1 x 0.005 = 0.05%. The cost is small. A fresh entry lives 10 seconds and serves 50 x 10 = 500 reads, so the hit rate is 500 / 501 = 99.8%.
Worked example 3 (Assumption: the cost of deletes). A price sits in 4 keys: 1 product page and 3 lists. 20 prices change per second, so deletes = 20 x 4 = 80 per second. The cache takes 100,000 operations per second, so this is 0.08%. Forget the 3 list keys, and they show the old price until their TTL ends.
What breaks with each choice
- TTL: users see old data for up to one TTL. A short TTL sends more reads to the database. Fix: choose the TTL from a business number ("how old may this be?"). Use explicit invalidation for the few fields that need more.
- Explicit: a delete can be lost, or a key can be forgotten. Assumption: 1 delete in 10,000 fails. With 20 changes per second there are 20 x 86,400 = 1,728,000 changes per day, so 1,728,000 / 10,000 = 173 lost deletes per day. Without a TTL, a wrong entry stays until the next change of that product, which could be 30 days for a product that rarely changes. A slow reader can also put an old value back after your delete, and a TTL limits that harm too. Fix: always keep a TTL as a safety net. If one change needs many deletes, put a version number in the key and change the number.
What it costs
- TTL needs no code. You set a number.
- Explicit invalidation needs a list of keys for each fact and tests for every write path. Assumption: 3 to 5 engineer-days for the first fact.
- Changing your mind is cheap in the safe direction. You can add deletes to a TTL cache without any data move. Removing a TTL from a delete-based cache is the risky step.
How each level answers
SDE-1: TTL means the entry expires after a set time. Explicit invalidation means the app deletes the entry when data changes.
SDE-2: I use explicit delete for prices, because they change and users notice a wrong one. I also set a TTL, so a lost delete heals by itself. For product descriptions a one hour TTL is enough.
Senior: With a price that changes every 2,500 seconds and a 1% stale budget, a TTL must be 50 seconds or less. That costs more database reads. A delete gives 0.0002% stale. The failure is a lost delete, 173 per day in my assumption, and the TTL is the fallback. For a stock count that changes every 10 seconds, I delete.
Staff: Freshness is a product decision with a number: how old may a price be on a listing page, and at checkout? Checkout reads the database. The team that owns the write path owns the delete and its tests. I start with TTL only and add deletes for hot fields. I measure the stale share by comparing 0.1% of cache reads with the database. When it stays under the agreed number, I stop adding rules.
Say it in the interview
"For a price I delete the cache entry after the database write, and I keep a TTL as a safety net. With a change every 2,500 seconds, a TTL of 60 seconds alone gives 1.2% stale reads, and the delete gives almost none. For product descriptions a long TTL is enough and needs no code."
Common mistakes
- Using only deletes with no TTL. A lost delete then leaves a wrong value until the next change, which can be weeks.
- Using a long TTL for fast-changing data, such as stock. The entry is stale for most of its life.
- Forgetting copies of the fact in other keys, such as list pages. One product then shows two prices.
Sources
- Microsoft Azure Architecture Center, Cache-Aside pattern (update the data store first, then invalidate the entry; match expiry to the access pattern): https://learn.microsoft.com/en-us/azure/architecture/patterns/cache-aside (opens in a new tab) (checked 26 Oct 2026).
- The stale-share formula is a simple model by Tradeoff, not a measured law. All rates, delays, failure rates and effort are assumptions made for teaching. The arithmetic is calculated from them.
Understand the trade-off. Practise explaining your choice.
In an AI mock interview, the interviewer can push on a choice like this one: it changes a number and asks if your answer still holds.