Source: answers/day-05-caching-fundamentals-review.md

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 with 1 − (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 × N as a gut check, then you compute 1 − (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