How Do You Design a Friend Recommendation System?
Learn how to design a friend recommendation system: graph-based candidates, offline scoring, and ranking signals.
Expected Interview Answer
A friend recommendation system generates candidates from a user’s social graph (friends-of-friends, mutual connections) using a graph database or precomputed graph traversal, scores those candidates with signals like mutual friend count, shared groups/interests, and interaction history, then ranks and serves the top results through a fast, cached recommendation API.
The core signal is graph proximity: people two hops away in the social graph (friends-of-friends) are far more likely relevant candidates than random users, so the system runs a bounded breadth-first traversal or queries a graph database (or a precomputed adjacency structure in a distributed store) to generate a candidate set efficiently rather than scanning the entire user base. Because computing this live for every request at scale is expensive, large systems precompute candidate lists offline in a batch or streaming pipeline (e.g. daily Spark jobs over the friend graph, or incremental updates via a stream processor) and store the ranked results in a fast key-value store for low-latency reads. Candidates are then scored using features like mutual friend count, shared groups/schools/employers, location proximity, and past interaction signals (profile views, message history), typically via a learned ranking model, before the top-N recommendations are cached and served. Freshness matters less than for a news feed, so heavier batch computation with periodic refresh is an acceptable trade-off for lower serving cost.
- Graph-based candidate generation focuses compute on genuinely likely matches instead of the whole user base
- Offline/batch precomputation keeps the serving path fast and cheap despite expensive graph traversal
- Multi-signal scoring (mutual friends, shared context, interactions) improves recommendation relevance
- Accepting periodic staleness trades a little freshness for dramatically lower serving cost
AI Mentor Explanation
A friend recommendation system is like a club scout who does not evaluate every player in the country, but instead looks at players who train alongside current squad members — teammates of teammates — as the most promising candidates. The scout ranks those candidates by how many shared training partners they have and how often they have played together before, rather than judging every prospect live on match day. This shortlist is prepared well in advance during the off-season and simply refreshed periodically, not recalculated for every single request. That graph-proximity candidate search plus offline scoring is exactly how a friend recommendation system finds good matches efficiently.
Step-by-Step Explanation
Step 1
Generate candidates from the social graph
Run a bounded traversal (or graph database query) to find friends-of-friends within 2 hops, avoiding a full scan of the user base.
Step 2
Precompute in batch
Because live traversal at scale is expensive, compute candidate lists offline via a periodic batch or streaming job and store ranked results in a fast key-value store.
Step 3
Score with multiple signals
Rank candidates using mutual friend count, shared groups/schools/employers, location, and past interaction signals, often via a learned model.
Step 4
Cache and serve top-N
Serve the top-N recommendations from a low-latency cache, refreshing periodically rather than recomputing on every request.
What Interviewer Expects
- Identifies graph proximity (friends-of-friends, mutual connections) as the core candidate-generation signal
- Distinguishes offline/batch precomputation from a live serving path for latency reasons
- Names concrete ranking signals beyond mutual friend count (shared context, interaction history)
- Recognizes that staleness is an acceptable trade-off here, unlike a real-time feed
Common Mistakes
- Proposing a full scan of all users to find candidates instead of graph-based traversal
- Computing recommendations live on every page load instead of precomputing offline
- Only using mutual friend count and ignoring other relevance signals
- Assuming recommendations must be perfectly real-time like a chat message
Best Answer (HR Friendly)
“A friend recommendation system looks at who your friends are already connected to, since people two connections away are much more likely to be someone you know than a random stranger. We compute these suggestions ahead of time in the background using signals like mutual friends and shared groups, then just serve the pre-computed list quickly when you open the app, refreshing it periodically rather than recalculating it every time.”
Code Example
def generate_candidates(user_id, graph, max_hops=2):
visited = {user_id}
frontier = set(graph.neighbors(user_id))
visited |= frontier
candidates = set()
for _ in range(max_hops - 1):
next_frontier = set()
for node in frontier:
for neighbor in graph.neighbors(node):
if neighbor not in visited:
candidates.add(neighbor)
next_frontier.add(neighbor)
visited |= next_frontier
frontier = next_frontier
return candidates
def score_candidate(user_id, candidate_id, graph, interactions):
mutual_friends = len(set(graph.neighbors(user_id)) & set(graph.neighbors(candidate_id)))
shared_groups = len(get_shared_groups(user_id, candidate_id))
interaction_score = interactions.get((user_id, candidate_id), 0)
return mutual_friends * 2 + shared_groups * 1.5 + interaction_score
def precompute_recommendations(user_id, graph, interactions, top_n=20):
candidates = generate_candidates(user_id, graph)
scored = [(c, score_candidate(user_id, c, graph, interactions)) for c in candidates]
scored.sort(key=lambda x: x[1], reverse=True)
recommendation_store.set(user_id, [c for c, _ in scored[:top_n]])Follow-up Questions
- How would you avoid recommending someone the user already blocked or previously dismissed?
- How would you scale friend-of-friend traversal for users with an extremely large friend count?
- How would you incorporate a learned ranking model instead of a hand-tuned scoring formula?
- How often should the batch job refresh recommendations, and what drives that trade-off?
MCQ Practice
1. Why does a friend recommendation system focus on friends-of-friends rather than the entire user base?
Graph proximity focuses compute on genuinely likely matches instead of scanning every user, improving both relevance and efficiency.
2. Why do large-scale friend recommendation systems typically precompute results in batch rather than live?
Offline batch computation keeps the serving path fast and cheap, accepting some staleness in exchange for much lower serving cost.
3. Besides mutual friend count, what is another common scoring signal for friend recommendations?
Real systems combine multiple signals — shared context and interaction history alongside mutual friend count — for better relevance.
Flash Cards
What is the core candidate-generation signal? — Graph proximity — friends-of-friends within 1-2 hops of the user in the social graph.
Why precompute recommendations offline? — Live graph traversal at scale is expensive; batch precomputation keeps the serving path fast and cheap.
Name scoring signals beyond mutual friends. — Shared groups/schools/employers, location proximity, and past interaction history.
Why is staleness acceptable here? — Friend recommendations do not need real-time freshness like a feed, so periodic batch refresh is a good trade-off.