11 Case Studies 4 min read 784 words

Case Study: AI-Powered Recommendation Engine

Fifty million users served inside 200 milliseconds by matrix factorization and ANN search, with the LLM confined to writing cached, per-title explanations.

case-studyretrievallatencyapplied
01problem

The Problem

A streaming platform with 50 million users needs to build a recommendation system that combines collaborative filtering with LLM-generated explanations: "Because you enjoyed Inception, you might like Tenet for its mind-bending time mechanics."

Constraints given in the interview:

  • Real-time recommendations (under 200ms p95)
  • Must explain why each recommendation was made
  • Cold-start handling for new users
  • Privacy: cannot leak viewing history between users
  • Daily active: 5M users, each viewing 10+ recommendation sets
02question

The Interview Question

03architecture

Solution Architecture

04design decisions

Key Design Decisions

4.1

1. Why Not Just Use LLM for Everything?

Answer: Scale economics. Calling an LLM for 50M users × 10 recommendation sets/day = 500M LLM calls daily. At $0.001 per call, that is $500K/day. Instead:

ComponentRoleCost per User/Day
Embedding lookupFetch precomputed vector$0.00001
ANN searchFind candidates$0.0001
Cross-encoder rerankScore top 100$0.001
LLM explanationNatural language$0.005
Total$0.006

The LLM is only used for the final explanation, not the ranking itself.

4.2

2. Explanation Caching

Answer: Most explanations can be cached. "Because you watched Inception" applies to thousands of users. We cache explanations at the (content_pair, reason_type) level:

Pythonpython · 7 lines
1234567
cache_key = f"{source_movie}:{target_movie}:{reason_type}"
# Example: "inception:tenet:time_mechanics"

explanation = cache.get(cache_key)
if not explanation:
    explanation = generate_explanation(source_movie, target_movie, reason_type)
    cache.set(cache_key, explanation, ttl=86400)

Cache hit rate: 85%+ after warmup.

4.3

3. Cold-Start Handling

Answer: New users have no history for collaborative filtering. We use a Hybrid Approach:

05explanation challenge

The Personalized Explanation Challenge

The explanation must feel personal, not generic:

Bad: "Tenet is a popular thriller." Good: "Because you enjoyed Inception's mind-bending plot, Tenet offers similar time-manipulation puzzles from the same director."

We achieve this by including user context in the prompt:

Pythonpython · 13 lines
12345678910111213
prompt = f"""
Generate a 1-sentence explanation for why this user would enjoy {target_movie}.

User context:
- Recently watched: {recent_movies}
- Preferred genres: {genres}
- Dislikes: {dislikes}

Source movie that triggered this recommendation: {source_movie}
Reason category: {reason_type}

Explanation:
"""
06budget

Latency Budget

StageTargetActual p95
User embedding lookup5ms3ms
ANN search (top 100)20ms15ms
Cross-encoder rerank50ms45ms
LLM explanation (cached)10ms8ms
LLM explanation (miss)500ms450ms
Total (cache hit)85ms71ms
Total (cache miss)575ms513ms

To meet 200ms p95, we ensure 95%+ cache hit rate for explanations and generate explanations asynchronously for new content pairs.

07follow-up questions

Interview Follow-Up Questions

Q: How do you prevent the LLM from hallucinating facts about movies?

A: The LLM receives a structured fact sheet for each movie (director, cast, themes, awards) as context. It can only use information from this sheet. We also have a post-generation validator that checks claims against our catalog metadata.

Q: What if a user's taste changes rapidly?

A: We use a recency-weighted embedding update. Recent watches are weighted 3x more than older ones. For real-time responsiveness, we maintain a "session embedding" that captures current-session behavior and blends it with the historical embedding.

Q: How do you A/B test recommendation algorithms?

A: We hash user_id to consistently assign users to experiment buckets. Each bucket can have different candidate generation, ranking, or explanation strategies. We track engagement metrics (click-through, watch time, skip rate) per bucket.

08takeaways interviews

Key Takeaways for Interviews

  1. LLMs for explanation, not ranking: use traditional ML for scale, LLMs for personalization
  2. Cache aggressively: explanations for content pairs are reusable across users
  3. Cold-start is a spectrum: new users → content-based; some history → hybrid; full history → collaborative
  4. Latency budgets require cache hit rate targets: design the cache around your latency SLA

Related chapters: Semantic Caching, Cost Optimization