Back to Scenarios & Design Questions
Q11Question 11 of 67

How would you design a recommendation system

Key Concepts
  • Start with simple baselines (trending, popular, recent activity, category rules) before any machine learning.
  • Collaborative filtering recommends based on behavior patterns: users who liked X also liked Y.
  • Content-based filtering recommends items with similar attributes to what the user already liked.
  • Offline precomputation generates candidate sets; a lightweight online ranker re-orders with fresh context.
  • Event tracking (impressions, clicks, conversions) closes the feedback loop for continuous improvement.
  • Cold-start for new users: popularity plus onboarding signals; for new items: content attributes plus exploratory exposure.
  • Blend collaborative and content-based into a hybrid; inject exploration to avoid filter bubbles.

Definition

Start with popularity and rules, add collaborative and content-based filtering, precompute candidates offline and rank in real time, close the loop with event feedback, and handle cold-start with popularity and attributes.
  • Start simple – Trending, popular, recent activity, and category rules deliver most value cheaply and serve as the fallback.
  • Collaborative filtering – Recommends based on behavior patterns: users who liked X also liked Y.
  • Content-based – Recommends items with similar attributes; works for new items and gives explainable results.
  • Two-stage – Offline batch precomputes candidate sets; a lightweight online ranker re-orders with fresh context.
  • Feedback loop – Track impressions, clicks, and conversions to retrain models; A/B test before rolling out.
  • Cold-start – New users see popular items plus onboarding signals; new items use content attributes.

When Rajesh logs into National Bank of India's app, it suggests products. The simplest version shows the most popular products this month (trending). A smarter version notices customers like Rajesh often took a home loan (collaborative filtering). Another angle sees Rajesh has a fixed deposit and suggests similar savings products (content-based). The bank prepares suggestions overnight (offline) and re-orders them when Rajesh opens the app (real-time ranking).

Understanding the Concepts

Why start simple before ML?

Simple baselines deliver most of the value cheaply, need no training, are easy to reason about, and give a baseline to beat. You only add ML when simple methods plateau.

JAVA
package com.bank.recommend.simple;

import java.util.List;

public class SimpleRecommender {

    public List<String> trendingProducts() {
        // Most engaged with in the last 7 days
        return List.of("Home Loan", "Fixed Deposit", "Credit Card");
    }

    public List<String> categoryRules(String currentProduct) {
        // If customer has a savings account, suggest FD
        if ("Savings Account".equals(currentProduct)) {
            return List.of("Fixed Deposit", "Recurring Deposit");
        }
        return trendingProducts();
    }
}

How does collaborative filtering work?

Recommend based on behavior patterns across users. At scale, factorize the sparse interaction matrix into latent vectors.

JAVA
package com.bank.recommend.collaborative;

import java.util.*;

public class SimpleCollaborativeFilter {

    // User-item interaction matrix (simplified)
    private final Map<String, Set<String>> userProducts = Map.of(
        "Rajesh",  Set.of("Savings", "FD"),
        "Priya",   Set.of("Savings", "FD", "Home Loan"),
        "Pankaj",  Set.of("Savings", "Credit Card")
    );

    public List<String> recommend(String userId) {
        Set<String> myProducts = userProducts.getOrDefault(userId, Set.of());
        Map<String, Integer> scores = new HashMap<>();

        for (var entry : userProducts.entrySet()) {
            if (entry.getKey().equals(userId)) continue;
            // Find similar users (overlap in products)
            long overlap = entry.getValue().stream()
                .filter(myProducts::contains).count();
            if (overlap > 0) {
                // Recommend products they have that I do not
                entry.getValue().stream()
                    .filter(p -> !myProducts.contains(p))
                    .forEach(p -> scores.merge(p, (int) overlap, Integer::sum));
            }
        }

        return scores.entrySet().stream()
            .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
            .map(Map.Entry::getKey)
            .toList();
    }

    public static void main(String[] args) {
        SimpleCollaborativeFilter cf = new SimpleCollaborativeFilter();
        System.out.println("Recommendations for Rajesh: " + cf.recommend("Rajesh"));
    }
}
TEXT
Recommendations for Rajesh: [Home Loan, Credit Card]
# Priya has Savings+FD like Rajesh, and also has Home Loan -> recommend it
# Pankaj has Savings like Rajesh, and also has Credit Card -> recommend it

How does content-based filtering work?

Recommend items whose attributes are similar to items the user already liked.

JAVA
package com.bank.recommend.contentbased;

public class ContentBasedFilter {

    // Each product has attributes: category, risk, tenure
    // Rajesh likes FD (savings, low-risk, medium-tenure)
    // -> Recommend: Recurring Deposit (savings, low-risk, short-tenure)
    // -> Do NOT recommend: Equity Fund (investment, high-risk)

    public String explainRecommendation(String userId, String product) {
        return "Recommended because you hold a Fixed Deposit " 
            + "and " + product + " has similar savings attributes.";
    }
}

How does offline precomputation and real-time ranking work?

Heavy candidate generation runs in batch. A lightweight ranker re-orders with fresh context at request time.

JAVA
package com.bank.recommend.pipeline;

import java.util.List;

public class TwoStageRecommender {

    private final OfflineCandidateStore candidateStore;
    private final RealTimeRanker ranker;

    public TwoStageRecommender(OfflineCandidateStore candidateStore,
                                RealTimeRanker ranker) {
        this.candidateStore = candidateStore;
        this.ranker = ranker;
    }

    public List<String> recommend(String userId) {
        // Stage 1: Load precomputed candidates (top 200)
        List<String> candidates = candidateStore.getCandidates(userId);

        // Stage 2: Re-rank with fresh context
        return ranker.rank(userId, candidates);
        // Uses: time of day, current session, last viewed product
        // Returns: top 10, final order
    }
}

How does the feedback loop work?

Track events (impressions, clicks, conversions) and use them as training labels.

JAVA
package com.bank.recommend.tracking;

public class EventTracker {

    public void trackImpression(String userId, String productId) {
        // Rajesh was shown "Home Loan" -> impression event
    }

    public void trackClick(String userId, String productId) {
        // Rajesh clicked "Home Loan" -> positive signal
    }

    public void trackConversion(String userId, String productId) {
        // Rajesh opened a Home Loan -> strongest signal
    }

    // Events stream to a pipeline -> become training labels
    // A/B test new model vs current on click-through rate
}

How do you handle cold-start?

New users see popular items plus onboarding signals. New items use content attributes plus exploratory exposure.

JAVA
package com.bank.recommend.coldstart;

import java.util.List;

public class ColdStartHandler {

    public List<String> forNewUser(String demographic) {
        // No history -> show popular + demographic-based
        if ("salaried-25-35".equals(demographic)) {
            return List.of("Credit Card", "Home Loan", "Savings Account");
        }
        return List.of("Fixed Deposit", "Savings Account"); // safe default
    }

    public double forNewItem(String productId) {
        // No interactions -> use content attributes to place near similar items
        // Give exploratory exposure (show to some users regardless of score)
        return 0.1; // exploration boost
    }
}

What are common mistakes?

Jumping to deep learning on day one without a simple baseline. Not having an A/B testing framework. Creating filter bubbles by never showing diverse items.

JAVA
package com.bank.recommend.antipattern;

// WRONG: complex ML model on day one with no baseline
// No way to know if it is better than just showing popular items.
// Start simple, measure, then add ML when simple plateaus.

What are common interview follow-up questions?

How do you handle the filter bubble problem? How do you ensure compliance (not recommending products the user is not eligible for)? How would you implement real-time model serving? What is the difference between implicit and explicit feedback? How do you handle seasonality in recommendations?

Visual Overview

DIAGRAM
┌──────────────────────────────────────────────────────────┐
│           RECOMMENDATION SYSTEM PIPELINE                  │
├──────────────────────────────────────────────────────────┤
│                                                          │
│  Offline (nightly batch):                                │
│  ┌────────────────────────────────────────┐              │
│  │ User-Item Matrix                      │              │
│  │  → Collaborative Filtering (ALS)      │              │
│  │  → Content-Based Features             │              │
│  │  → Generate top 200 candidates/user   │              │
│  └──────────────────┬─────────────────────┘              │
│                     │ store                              │
│                     ▼                                    │
│  ┌──────────────────────────────────────┐                │
│  │ Candidate Store (Redis/DB)          │                │
│  └──────────────────┬───────────────────┘                │
│                     │                                    │
│  Online (request time):                                  │
│  ┌──────────────────▼───────────────────┐                │
│  │ Real-Time Ranker                    │                │
│  │ - Fresh context (time, session)     │                │
│  │ - Business rules (eligibility)      │                │
│  │ - Return top 10                     │                │
│  └──────────────────┬───────────────────┘                │
│                     │                                    │
│  ┌──────────────────▼───────────────────┐                │
│  │ Rajesh's App: "Recommended for you" │                │
│  └──────────────────┬───────────────────┘                │
│                     │                                    │
│  Feedback Loop:     ▼                                    │
│  impression → click → conversion → retrain               │
└──────────────────────────────────────────────────────────┘

Key Takeaway

Pankaj designs a recommendation system as a layered pipeline of fallbacks and a blend, not a single algorithm. At National Bank of India, he deliberately starts with simple baselines: trending products, popular items, recent activity, and category rules like suggesting a fixed deposit to a savings account customer. These deliver most of the value cheaply, need no training, and give a baseline to beat. ML is added only when these plateau.

The two ML approaches are collaborative filtering (users who liked X also liked Y, using the interaction matrix) and content-based filtering (items with similar attributes to what the user liked, using feature vectors). Collaborative discovers non-obvious connections but suffers from cold-start; content-based works for new items and gives explainable results but stays within what the user already likes. Blending them into a hybrid is what real systems do.

For performance, heavy candidate generation runs in nightly batch to produce a candidate set per user, and a lightweight online ranker re-orders with fresh context at request time. The feedback loop tracks impressions, clicks, and conversions, streams them to a pipeline for training labels, and A/B tests new models before rollout. Cold-start degrades gracefully: new users see popular items plus onboarding signals, new items are placed by content attributes with exploratory exposure.

Remember one sentence: Start with popularity and rules, add collaborative and content-based filtering blended into a hybrid, precompute candidates offline, rank cheaply in real time, close the loop with event tracking and A/B testing, and handle cold-start by degrading from collaborative to content-based to popularity.

---

Share
Use ← → arrow keys to navigate