Definition
- 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.
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.
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"));
}
}
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.
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.
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.
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.
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.
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
┌──────────────────────────────────────────────────────────┐ │ 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.
---