Day 5 Review — Caching Fundamentals — 2026-07-26
Score: 7.55 / 9 (84%) Verdict: Strong recovery from Day 4. MCQs perfect, algorithm-mapping perfect, hot-key + news-homepage design near-perfect. One critical miss: Q5 tail-latency amplification — the third time this exact skill has slipped through. Time for a dedicated drill.
Question-by-question
Q1 (MCQ) — Hit rate math ✅ 1.0 / 1.0
C (~82%) — Correct. 10 = h + 50(1-h) = 50 - 49h → h ≈ 0.816. Nice clean arithmetic.
Q2 (MCQ) — Strong-consistency cache strategy ✅ 1.0 / 1.0
B (write-through + distributed + durable) — Correct. Only strategy that gives strong consistency AND no data loss AND cross-server visibility.
Q3 (MCQ) — Cache stampede + mitigation ✅ 1.0 / 1.0
B — Correct. Named it (thundering herd / stampede) AND matched the standard mitigation (single-flight / request coalescing).
Q4 (T/F) — Cache-aside: delete not update ✅ 1.0 / 1.0
True — Correct. Race-safe + doesn't pollute cache with data that may not be re-read.
Q5 (T/F) — Tail-latency amplification with N=50 ❌ 0.0 / 1.0 🚨 CHRONIC GAP
Your answer: True. Correct: False.
Third time this exact skill has slipped: - Diagnostic Q4 — CAP theorem reasoning (related conceptual issue: right answer, imprecise reasoning) - Day 2 Q3 — 100-fan-out amplification → picked 1% instead of 63% (didn't apply the formula) - Day 5 Q5 — 50-fan-out amplification → said True to a 63% claim (didn't verify the claim with the formula)
I even warned you in the Day 5 intro:
"Q5 is a trap I built specifically for you… The question is: will you reach for it and compute with the right N?"
You knew the formula was relevant. You didn't compute. Let's fix this now:
Tail-Amp Recognition Drill
Every one of these takes 10 seconds. Do them out loud right now. The formula: 1 − (1−p)^N where p = probability a single call is slow, N = number of parallel calls.
| Scenario | Formula | Answer |
|---|---|---|
| 10 shards, each P99 = 100 ms (p = 0.01, N = 10) | 1 − 0.99^10 |
~10% of requests hit at least one slow shard |
| 50 shards, each P99 = 200 ms (p = 0.01, N = 50) | 1 − 0.99^50 |
~40% ← this was Day 5 Q5 |
| 100 shards, each P99 = 100 ms (p = 0.01, N = 100) | 1 − 0.99^100 |
~63% ← this was Day 2 Q3 |
| 200 shards, each P99 = 100 ms (p = 0.01, N = 200) | 1 − 0.99^200 |
~87% |
| 50 shards, each P99.5 = 50 ms (p = 0.005, N = 50) | 1 − 0.995^50 |
~22% |
Approximation trick (works when p × N << 1): the answer is roughly p × N. So:
- 10 shards × 1% = ~10% ✓
- 50 shards × 1% = ~50% (actual: 40% — approximation is optimistic; use for gut check)
- 100 shards × 1% = ~100% → obviously not; use the real formula here
The rule I want you to burn in:
See "N in parallel" → immediately compute
p × N, then verify with1 − (1−p)^N. The number 63% is only for N=100 with P99=100ms. For any other N, do the math.
Q6 (Short) — 4 write strategy mappings ✅ 1.0 / 1.0
All 4 correct with clean reasoning: 1. Read-heavy catalog, 5-min staleness OK → cache-aside ✅ 2. Leaderboard counter, high write throughput, some loss OK → write-back ✅ 3. Shopping cart, immediate cross-device consistency → write-through ✅ 4. App talks only to cache, cache handles DB → read-through ✅
Your algorithm-choice muscle from Day 4 Q6 has transferred cleanly to write-strategy choice. This is real fluency.
Q7 (Short) — Hot key problem ✅ 0.95 / 1.0
Excellent structured answer: - Definition: ✓ single key gets disproportionate traffic, CPU spike / latency - Consequence: ✓ one shard saturates while others idle - Mitigation 1: local in-memory caching (client-side layer above Redis) ✅ - Mitigation 2: key splitting with random suffixes ✅
Small nit: technically L1 = CPU cache; what you described is more precisely an "application-level cache" or "in-process cache." L1/L2 terminology from CS courses vs system-design cache layers can get mixed up. Not a real deduction.
Third mitigation you could have added (for completeness): replicate the hot key across N shards and let clients pick one at random. Same effect as splitting, different implementation.
Q8 (Scenario) — News homepage caching architecture ✅ 0.9 / 1.0
Really strong. All four sub-parts hit correctly: - ✅ CDN edge (95%+ absorbed) + Redis (canonical HTML/JSON) — two-layer stack correct - ✅ 60 s TTL + stale-while-revalidate HTTP semantics - ✅ Event-driven purge on editor publish - ✅ Single-flight lock + serve-stale on cache miss during spike
You used the right technical terminology: stale-while-revalidate, event-driven purging, single-flight / mutex pattern. That's real depth.
Small additions for the FAANG-perfect answer: - Mention Layer 3 (individual story lookups → Redis or DB buffer pool) since not all requests are for the same homepage — the app assembles pages from cached fragments. - Explicit rationale: "60 s TTL matches the 60 s freshness SLA; if editors need instant visibility, event-driven purge handles it and TTL is just the backstop for missed purges." - Bonus: pre-warm CDN after purge by having your publish pipeline make an internal request to the URL so the next real user gets a warm cache.
Q9 (Design) — Cold-cache post-mortem ⚠️ 0.7 / 1.0
Root cause diagnosis: correct class of problem (cache stampede / thundering herd).
Fixes — 3 valid ones: - ✅ Request coalescing / single-flight — great - ⚠️ TTL jitter — a fix for simultaneous TTL expiry, not for cold restart (all keys were already gone; there's no expiry variance to help) - ✅ Load shedding + circuit breakers — great DB-side protection
The BIGGEST fix you missed — the one that directly addresses the specific scenario described:
Redis persistence + high availability. - AOF (Append-Only File) persistence → Redis rebuilds cache from disk in seconds after restart, not from Postgres. - Primary + replica HA → a "restart" of the primary doesn't lose the cache; the replica is promoted and continues serving; the old primary rejoins as a replica later.
This is the direct answer to "all cache keys were lost on Redis restart." The prompt described a preventable operational configuration, not a fundamental architecture problem. The three fixes you gave are all things that help after the cold cache happens; the persistence/HA fix ensures it never happens.
Also worth mentioning: - Tiered cache — in-process cache above Redis (Caffeine, LRU) → app cold-start is decoupled from Redis cold-start - Cache-fill rate limiting — cap the DB-refill rate so DB has time to recover - Consistent hashing with N Redis nodes → if you add/remove one, only 1/N of keys need to be re-warmed (not all)
Interview-quality diagnostic framing — try this structure next time:
"Two categories of fix: (1) prevent the cache from going cold in the first place — persistence, HA, tiered cache. (2) survive gracefully when it does — single-flight, load shedding, rate-limited cache-fill."
Summary
| Q | Topic | Score | Notes |
|---|---|---|---|
| Q1 | Hit-rate math | 1.0 | ✅ Clean arithmetic |
| Q2 | Consistency write strategy | 1.0 | ✅ |
| Q3 | Stampede + single-flight | 1.0 | ✅ |
| Q4 | Delete vs update in cache-aside | 1.0 | ✅ |
| Q5 | Tail-latency amplification (N=50) | 0.0 | 🚨 3rd miss on this exact skill |
| Q6 | 4 write-strategy mappings | 1.0 | ✅ Perfect |
| Q7 | Hot-key problem | 0.95 | ✅ Excellent structure |
| Q8 | News homepage caching | 0.9 | ✅ Great; missing Layer 3 + pre-warm |
| Q9 | Cold-cache post-mortem | 0.7 | ⚠️ Named class right; missed Redis persistence/HA (the specific fix for this specific scenario) |
Score progression
| Day | Score | % | Trend |
|---|---|---|---|
| Diagnostic | 71% | baseline | |
| Day 1 | 83% | +12% | |
| Day 2 | 83% | flat | |
| Day 3 | 90.6% | +7.6% ⭐ | |
| Day 4 | 66% | −24.6% ⚠️ | |
| Day 5 | 84% | +18% recovery |
Running average: ~80%. You've stabilized around 80%+ on 4 of 5 days. The Day 4 regression was noise; Days 3 and 5 show your true ceiling is in the 85–90% range.
Two things to lock in
1. Tail-amplification RECOGNITION → COMPUTATION.
The formula is not the skill. The habit is:
Any time you see the words: "N in parallel", "fan out to N", "waits for all N", "aggregates from N shards/replicas/backends" — you STOP, you write
p × Nas a gut check, then you compute1 − (1−p)^N.
Do the drill in the review file above right now. Then whenever a fan-out setup appears in the next 26 days, force yourself to say the numbers out loud.
2. Post-mortem structure: prevention vs survival.
Every operational incident question has two categories of fix: - Prevention — how do we make this event less likely / smaller-blast-radius? - Survival — when it happens, how do we degrade gracefully instead of cascading?
For Q9, you gave 3 survival fixes. You needed at least one prevention fix (Redis persistence + HA). This mental split will fix your incident-response answers for good.
Weak-area queue update
| Concept | Origin | Severity | Re-quiz on Days | Status |
|---|---|---|---|---|
| Tail-amp RECOGNIZE and COMPUTE with actual N | Day 2 Q3, Day 5 Q5 | HIGH | 8, 12, 20, 27 | 🔥 Chronic — needs dedicated drill |
| Bandwidth vs latency — cement this | Day 4 Q5 (from Day 2 Q4) | High | 7, 11, 20 | Escalated |
| Post-mortem: separate prevention vs survival fixes | Day 5 Q9 | Medium | 12, 24 | New |
| Slow-start applies with every algorithm | Day 4 Q4 | Medium | 11, 25 | Pending |
| JWT vs sessions — trade-off articulation | Day 1 Q7 + Day 4 Q7 | Medium | 25 | Improving |
| CAP theorem precise reasoning | Diagnostic Q4 | Medium | 15, 18 | Pending |
| DB trade-off reasoning | Diagnostic Q9 | Medium | 8 | Pending |
| Distributed state (rate limiter) | Diagnostic Q10 | Medium | 17, 23, 27 | Pending |
| DNS failover architecture | Day 1 Q9 | Low | 15 | Pending |
| Bi-directional check for push mechanism | Day 3 Q6.1 | Medium | 7, 28 | Pending |
| Capacity math in architecture answers | Day 3 Q8 | Low | 12, 26 | Ongoing |
| Retry amplification — "retries at one layer only" | Day 4 Q9 | Medium | 21, 24 | Pending |
| Anycast + service mesh in global LB designs | Day 4 Q8 | Low | 26 | Pending |