advanced~7h

Case Study: Social Feed Ranking System Design

End-to-end design of a social feed ranking system — the pattern behind Twitter/X, LinkedIn, Facebook News Feed, and Instagram. Covers the fan-out problem, multi-signal ranking with multi-objective optimization, time-decay, diversity, author concentration, and the unique tradeoff between engagement and user trust. Grounded in Khang Pham's feed ranking case study.

3
Subtopics
2
Exercises
1
Projects
5
Quiz Qs
5
Flashcards
📚 Prerequisites(3)

🎓 Learning objectives

  • Explain the fan-out problem in social feeds and describe the push-on-write vs. pull-on-read architecture tradeoff
  • Identify the three categories of signals used in feed ranking: network signals, content signals, and engagement signals
  • Design a multi-task ranking model for social feeds that jointly optimizes for multiple engagement types
  • Describe how time-decay is incorporated into feed ranking and why recency matters differently in social vs. content recommendation
  • Explain the author concentration problem and describe the diversity mechanisms that address it
  • Distinguish between feed ranking for social networks and content recommendation, identifying where they share patterns and where they diverge
  • Design an evaluation framework for feed ranking that balances engagement metrics with trust and well-being metrics

What is it?

A social feed ranking system decides which posts, updates, and content from a user's network (and beyond) to show in their home feed, and in what order. The feed is the primary surface where users consume content from people they follow — and increasingly, from algorithmic recommendations of content they don't follow.

Khang Pham's feed ranking case study (ML Primer) describes the core pattern shared by Twitter/X (now called 'For You'), LinkedIn (home feed), Facebook (News Feed), and Instagram (home + Reels). Despite product differences, all share a common ML architecture:

  1. Candidate fetching — gather posts from people the user follows, plus algorithmic recommendations from beyond their network
  2. Ranking — score each candidate post using user, author, post, and context signals
  3. Re-ranking — apply time-decay, diversity, safety filters, and business rules

Feed ranking is distinct from content recommendation (e.g., YouTube) in several important ways: the content is user-generated (not professionally produced), the network graph matters (who you follow constrains candidates), and the trust + well-being dimension is much more salient.

Why it exists

Without ranking, the feed would be chronological — users with 1,000 follows would see 1,000 posts per hour in raw reverse-chronological order, overwhelming their ability to find content that matters to them.

The original argument for algorithmic ranking: 'We'll show you the best content from your network, not just the most recent.' Users with large networks couldn't read everything chronologically; ranking let them find the highest-value posts without scrolling for hours.

The business argument: users who see engaging content spend more time on the platform. A 1% improvement in feed quality translates to significant engagement increases at scale.

The complexity argument: modern feeds mix content from follows, algorithmic recommendations (beyond the network), ads, promoted content, and stories. A ranking system is the only way to coherently interleave these streams while maintaining a consistent user experience.

The tension: as feeds became more algorithmic, concerns emerged about filter bubbles, misinformation amplification, and addictive scroll patterns. Feed ranking is now one of the most socially consequential ML systems in deployment.

Problem it solves

  1. Volume: a user following 500 accounts generates 2,000+ posts per day — showing all of them chronologically is infeasible.
  2. Relevance: not all posts from followed accounts are equally interesting — a user follows a friend but doesn't care about every reply they make to strangers.
  3. Fan-out at scale: when a celebrity with 10M followers posts, that single event must be reflected in 10M feeds — doing this at query time is impossible.
  4. Algorithmic expansion: if users only see content from their follows, they're trapped in existing networks. The system must surface relevant content from beyond their current connections.
  5. Time-sensitivity: a post about a live sports event is valuable for 2 hours; a post about a year-old article is less time-sensitive. Ranking must handle recency differently per content type.
  6. Multi-objective conflict: maximizing engagement (likes, shares) can conflict with user well-being (showing outrage-inducing content gets engagement but damages trust).

Intuition

Ranking a social feed is like a smart news editor deciding what goes on the front page of a personalized newspaper.

The editor has several constraints (analogous to the ML system):

  • The newspaper is personalized to each of the millions of readers
  • Stories come from thousands of sources (the accounts the user follows)
  • Some stories are time-sensitive (breaking news = posts about live events)
  • The reader has limited attention (can only read the top 20 stories)
  • The editor also has business goals (include some promoted content)

The bad editor (chronological feed): prints every story in order of arrival. A celebrity's post about breakfast arrives while an important update from a close friend scrolls off the bottom. The reader misses what matters.

The good editor (ranked feed): considers: Is this story from someone the reader often engages with? Is it timely? Is it about a topic the reader has shown interest in? Has the reader been shown too many stories from this author already?

The excellent editor (full system): does all of the above, but also: doesn't fill the front page with stories from just 3 authors even if they score highest (author diversity), doesn't promote stories that generate engagement through controversy at the expense of reader trust, and occasionally features a story from outside the reader's usual circles (exploration).

Analogy

A social feed ranking system is like a traffic management system for information.

Imagine a city (the platform) with millions of residents (users), each of whom has signed up to receive deliveries (posts) from hundreds of senders (accounts they follow).

Without ranking (chronological): every delivery arrives at the doorstep in the order it was shipped. A user following 500 senders is overwhelmed by deliveries and can't tell the urgent from the trivial.

With ranking: a smart delivery dispatcher decides the order. Packages from frequent senders (close friends) get prioritized. Time-sensitive packages (perishables = live events) go to the front. The dispatcher doesn't let any single sender monopolize the doorstep.

The fan-out problem: when a major retailer (celebrity) ships to 10 million customers simultaneously, the dispatcher can't handle all 10M at query time — they pre-stage deliveries (fan-out on write) or assemble them on demand (fan-out on read), depending on the retailer's scale.

The engagement trap: the dispatcher notices that controversial packages (outrage content) get the most interaction when delivered — users complain about them loudly. Optimizing for 'interaction with the package' surfaces increasingly controversial content, which eventually damages trust in the delivery service.

Technical explanation

STEP 1 — PROBLEM FRAMING:

Key questions to clarify:

  • Network type: symmetric (Facebook friends) or asymmetric (Twitter follows)?
  • Feed scope: only network posts, or also algorithmic recommendations beyond follows?
  • Primary content format: text posts, images, videos, mixed?
  • Scale: number of users, average follows per user, posts per day?
  • Latency SLA: how fast must the feed render?

Standard scale assumption: 300M users, average 500 follows, 50 posts/day/user = 15B posts/day, 50K feed requests/second.

Success metrics:

  • Primary: sessions per user per day, time in feed
  • Secondary: like rate, reply rate, share rate
  • Guardrail: 'report' rate (users reporting posts as harmful), survey satisfaction
  • Tension: engagement metrics and well-being metrics often conflict

STEP 2 — THE FAN-OUT PROBLEM:

When a user posts, their followers need to see it in their feed. With 500M followers (celebrity case), you cannot distribute one post to 500M feeds at write time.

Fan-out on write (push model): When a post is created, immediately write it to each follower's feed index Pros: feed read is fast (pre-assembled) Cons: write amplification for high-follower accounts (1 post → 10M writes) Best for: regular users with < 10K-100K followers

Fan-out on read (pull model): At feed request time, fetch posts from all accounts the user follows Pros: no write amplification; always fresh Cons: slow read (merge N timelines at query time); hard to scale Best for: celebrity accounts with millions of followers

Hybrid (production standard): Regular users: fan-out on write → pre-built feed cache High-follower accounts: fan-out on read at query time Threshold: typically 100K-1M followers

STEP 3 — RANKING SIGNALS:

Three signal categories (Khang Pham, ML Primer):

Network signals (who posted):

  • User-author interaction affinity: how often does this user engage with this author? Feature: liked/replied to / shared from this author in last 90 days
  • Closeness: mutual friends, mutual follows, DM history
  • Author quality: author's historical spam/violation rate, account age

Content signals (what was posted):

  • Topic match: embed post text → cosine similarity with user interest embedding
  • Content type: users often prefer specific types (video-heavy vs. text-heavy)
  • Post quality: length, grammar, link credibility, media quality
  • Language: post language matches user's primary language?

Engagement signals (how the world is reacting):

  • Early velocity: likes/shares/replies in first 30 minutes (viral signal)
  • Like rate: global like rate for this post normalized by impressions
  • Reply rate: high reply rate = discussion-generating content
  • Negative signals: report rate, 'not interested' signals, block rate

STEP 4 — RANKING MODEL (MULTI-TASK):

Input: concatenation of [user_features, author_features, post_features, user_author_interaction_features, context_features]

Shared bottom → multiple prediction heads: Head 1: P(like) — most common positive signal Head 2: P(reply) — deeper engagement, discussion Head 3: P(repost/share) — virality signal Head 4: P(click on link) — for link posts Head 5: P(not_interested) — soft negative Head 6: P(report) — strong negative, safety signal

Combined score = w1×P(like) + w2×P(reply) + w3×P(repost) + w4×P(click) - w5×P(not_interested) - w6×P(report)

Weight tuning: weights are tuned by policy teams, not just by ML metrics. P(report) penalty weight is often set very high to avoid surfacing harmful content even if it would be engaging.

STEP 5 — RE-RANKING ADJUSTMENTS:

Time-decay: feed_score = ranking_score × time_decay(post_age) time_decay(hours) = 1 / (1 + alpha × hours) — hyperbolic decay OR: decay = exp(-lambda × hours) — exponential decay alpha/lambda tuned per content type: breaking news decays faster; evergreen content (tutorials, recipes) decays slower

Author diversity: Max N posts per author in a single feed load (typically N=2-3) Even if top-10 posts are all from the same author, cap at 3 Why: users following a high-volume author shouldn't have their feed dominated

Content type mixing: Avoid showing 15 videos in a row if the user's feed is mixed Interleave text, image, and video posts to match historical consumption pattern

Deduplication: Same article shared by 5 accounts → show once (highest engagement version) Identify duplicates: URL matching, near-duplicate text detection (MinHash)

STEP 6 — EVALUATION:

Offline: AUC on (user, post, engaged/not) pairs from historical feed logs NDCG@10 treating top-engaged posts as ground truth

Online A/B test metrics: Primary: sessions per day, feed scroll depth, time spent in feed Secondary: like rate, reply rate, share rate Guardrail: report rate (must not increase), user survey satisfaction Negative signals: unfollow rate, account deactivation rate

Well-being tension: Engagement-optimized feeds can surface divisive or outrage content because it generates high reply/share rates. Mitigations:

  • Penalize 'outrage engagement' (replies containing negative sentiment)
  • Downweight content with high report rate even if like rate is also high
  • Survey users: 'How do you feel after spending time on this app?'

Architecture

Feed Ranking System — Data Infrastructure:

┌──────────────────────────────────────────────────────────────┐ │ POST INGESTION (real-time) │ │ │ │ User posts → Event stream (Kafka) → Fan-out service │ │ Regular users → Write to follower feed caches (Redis) │ │ High-follower accounts → Flag for read-time pull │ │ │ │ Post features extracted immediately: │ │ • Text embedding (sentence transformer) │ │ • Language detection │ │ • Safety classifier score │ │ • Media type detection │ └─────────────────────────────┬────────────────────────────────┘ │ (async, within seconds) ┌─────────────────────────────▼────────────────────────────────┐ │ FEATURE STORE │ │ │ │ User features (batch, updated daily): │ │ user_id → {interest_emb, language_prefs, content_type_pref}│ │ │ │ User-author affinity (batch + streaming): │ │ (user_id, author_id) → {like_rate_90d, reply_rate_90d} │ │ │ │ Post features (computed at post time, cached): │ │ post_id → {topic_emb, content_type, quality_score} │ │ │ │ Post engagement stats (near-real-time streaming): │ │ post_id → {like_count, reply_count, report_count, age} │ └─────────────────────────────┬────────────────────────────────┘ │ ┌─────────────────────────────▼────────────────────────────────┐ │ ONLINE SERVING (per feed request, < 100ms) │ │ │ │ Fetch: feed cache (pre-assembled) + pull high-follower posts │ │ Filter: seen, muted, blocked, safety violations │ │ Rank: deep model scoring with feature store lookup │ │ Re-rank: time-decay, diversity, deduplication │ │ Inject: ads at positions 3, 8, 15 │ │ Response: top 50 posts │ └─────────────────────────────┬────────────────────────────────┘ │ (log impressions + engagement events) ┌─────────────────────────────▼────────────────────────────────┐ │ TRAINING PIPELINE (daily batch) │ │ │ │ Impression logs + engagement events → training examples │ │ Feature join → model training → evaluation → shadow test │ │ Progressive rollout: 1% → 5% → 20% → 100% │ └──────────────────────────────────────────────────────────────┘

Workflow

How to design this system in a 45-minute interview:

Minutes 1-5 — Requirements clarification: Q: Network type? (symmetric like Facebook, or asymmetric like Twitter) Q: Feed scope? (only follows, or algorithmic expansion beyond follows) Q: Primary content format? (text, image, video, links) Q: Scale? (users, average follows, posts/day) Establish: 300M users, average 500 follows, mixed content, 100ms SLA.

Minutes 5-10 — High-level design: Name the problem: ranking, not content creation. Sketch: candidate fetching → filter → ranking → re-ranking → serving. Explain the fan-out problem and name the hybrid solution.

Minutes 10-20 — Candidate fetching and fan-out: Pre-built feed cache for regular users (fan-out on write). Pull-at-query-time for high-follower accounts (fan-out on read). Algorithmic expansion source (two-tower retrieval from global index). Threshold for switching between write and read fan-out.

Minutes 20-30 — Ranking model: Three signal categories: network, content, engagement. Multi-task model: predict like, reply, share, not_interested, report. Combined score with weights (mention policy team sets weights, not just ML). Key features: user-author affinity, topic match, post velocity.

Minutes 30-40 — Re-ranking and evaluation: Time-decay: why it matters, how to implement (hyperbolic or exponential). Author diversity: cap at 3 posts per author per load. Deduplication: same story shared by many accounts. A/B test design: primary metrics, guardrail metrics (report rate, satisfaction). Well-being tension: engagement vs. harmful content.

Minutes 40-45 — Scale and failure modes: Feature store for low-latency feature serving. What happens if the ranking model is down? (fall back to recency sort) What happens if a post goes viral mid-feed-load? (eventual consistency is fine)

Example

# Feed ranking: simplified scoring function import math from dataclasses import dataclass from typing import Optional @dataclass class Post: post_id: str author_id: str age_hours: float # hours since posted global_like_rate: float # likes / impressions globally global_reply_rate: float global_report_rate: float topic_similarity: float # cosine sim with user interest emb @dataclass class UserAuthorAffinity: like_rate_90d: float # how often user likes this author's posts reply_rate_90d: float direct_follow: bool # user explicitly follows this author # --- Ranking model output (stub: in production, a deep neural network) --- def predict_engagement(post: Post, affinity: UserAuthorAffinity) -> dict: # Simulate multi-task predictions from features base = 0.5 * affinity.like_rate_90d + 0.3 * post.topic_similarity return { 'p_like': min(1.0, base + 0.2 * post.global_like_rate), 'p_reply': min(1.0, base * 0.5 + 0.3 * post.global_reply_rate), 'p_repost': min(1.0, base * 0.3 + 0.1 * post.global_like_rate), 'p_report': post.global_report_rate, } # --- Combined ranking score --- WEIGHTS = { 'like': 1.0, 'reply': 2.0, # replies signal deeper engagement 'repost': 1.5, 'report': -10.0, # strong penalty for potentially harmful content } def ranking_score(post: Post, affinity: UserAuthorAffinity) -> float: preds = predict_engagement(post, affinity) return ( WEIGHTS['like'] * preds['p_like'] + WEIGHTS['reply'] * preds['p_reply'] + WEIGHTS['repost'] * preds['p_repost'] + WEIGHTS['report'] * preds['p_report'] # negative ) # --- Time-decay --- def time_decay(age_hours: float, alpha: float = 0.1) -> float: """Hyperbolic decay: 1 at age=0, ~0.5 at age=10h with alpha=0.1""" return 1.0 / (1.0 + alpha * age_hours) def feed_score(post: Post, affinity: UserAuthorAffinity) -> float: return ranking_score(post, affinity) * time_decay(post.age_hours) # --- Re-ranking with author diversity --- def rerank_with_diversity(scored_posts: list[tuple[float, Post]], max_per_author: int = 3, final_k: int = 20) -> list[Post]: author_count: dict[str, int] = {} result = [] for score, post in sorted(scored_posts, reverse=True): count = author_count.get(post.author_id, 0) if count < max_per_author: result.append(post) author_count[post.author_id] = count + 1 if len(result) >= final_k: break return result # --- Demo --- posts = [ Post('p1', 'author_A', age_hours=1, global_like_rate=0.12, global_reply_rate=0.05, global_report_rate=0.001, topic_similarity=0.8), Post('p2', 'author_A', age_hours=2, global_like_rate=0.10, global_reply_rate=0.04, global_report_rate=0.001, topic_similarity=0.7), Post('p3', 'author_A', age_hours=3, global_like_rate=0.09, global_reply_rate=0.03, global_report_rate=0.001, topic_similarity=0.75), Post('p4', 'author_A', age_hours=4, global_like_rate=0.11, global_reply_rate=0.04, global_report_rate=0.001, topic_similarity=0.6), Post('p5', 'author_B', age_hours=1, global_like_rate=0.08, global_reply_rate=0.06, global_report_rate=0.005, topic_similarity=0.9), Post('p6', 'author_C', age_hours=0.5, global_like_rate=0.15, global_reply_rate=0.07, global_report_rate=0.0, topic_similarity=0.85), ] affinity_A = UserAuthorAffinity(like_rate_90d=0.4, reply_rate_90d=0.1, direct_follow=True) affinity_B = UserAuthorAffinity(like_rate_90d=0.1, reply_rate_90d=0.05, direct_follow=True) affinity_C = UserAuthorAffinity(like_rate_90d=0.2, reply_rate_90d=0.08, direct_follow=True) affinities = {'author_A': affinity_A, 'author_B': affinity_B, 'author_C': affinity_C} scored = [(feed_score(p, affinities[p.author_id]), p) for p in posts] final_feed = rerank_with_diversity(scored, max_per_author=3, final_k=5) print('Final feed order:') for post in final_feed: score = feed_score(post, affinities[post.author_id]) print(f' {post.post_id} (author={post.author_id}, age={post.age_hours}h) → score={score:.3f}') # Note: author_A has 4 posts but only 3 will appear (diversity cap)

Real-world usage

  • Twitter/X (2023 open-source ranking system): Twitter released its ranking code in 2023, revealing a multi-task model with ~48M parameter neural network scoring posts on 'positive engagement' (likes, replies, shares) and 'negative engagement' (mutes, blocks, reports). The combined score uses a weighted sum with heavily negative weights for report signals. Includes author network scoring (follows from people you follow → higher score) and real-time engagement velocity.

  • Facebook News Feed (Sculley et al.): pioneered multi-objective ranking for social feeds. Originally optimized for clicks; then shifted to meaningful interactions (comments, shares) after finding click-optimized feed damaged well-being. Introduced the concept of 'meaningful social interactions' as a primary ranking signal in 2018.

  • LinkedIn Feed: uses 'viral score' (rate at which connections are engaging with a post) as a key feature alongside user-author network affinity. Explicitly downweights content with high engagement but low explicit positive signals — reply-heavy posts with negative sentiment are demoted even if total interactions are high.

  • Instagram (Meta): mixes network posts with algorithmic recommendations (Reels from non-follows). Uses a two-stage approach: a lightweight model scores 500 candidates, a heavier model scores the top 150. Public documentation describes the 'suggested posts' ranking as a separate system from 'following posts', each with different optimization targets.

  • Khang Pham (ML Primer): describes the core pattern with emphasis on multi-signal ranking ('no single engagement signal is sufficient — you must predict multiple and combine') and the fan-out architecture as the canonical scalability solution for feed systems.

Trade-offs

Fan-out on write vs. fan-out on read: write fan-out produces fast reads but creates write amplification — a celebrity with 10M followers generates 10M feed cache writes per post. Read fan-out is slow for high-follower accounts but avoids write amplification. The hybrid approach (write for regular users, read for celebs) is the standard solution. The threshold (when to switch from write to read) is tuned based on infrastructure cost.

Engagement metrics vs. well-being metrics: content that maximizes reply rate often includes divisive or outrage-inducing posts — they generate discussion. Optimizing purely for engagement amplifies this content. The standard mitigation: add report rate and negative engagement signals (hide, mute, unfollow after seeing) as penalty terms with high weights. But the weights are policy decisions, not ML decisions, and require ongoing tuning by policy and trust-and-safety teams.

Recency vs. quality: time-decay ensures the feed feels fresh but penalizes evergreen content. A tutorial that remains valuable for years may be buried after 48 hours. Many platforms use content-type-specific decay: breaking news decays fast, educational content decays slowly. This requires classifying posts by type (an ML problem in itself) and applying different decay functions.

Network-only vs. algorithmic expansion: a purely network-based feed (only show posts from follows) is predictable and user-controlled but limits engagement for users with small networks. Algorithmic expansion (show content from beyond follows) increases engagement and discovery but reduces user control and raises filter-bubble concerns. Most platforms now offer both modes and let users choose ('Following' vs. 'For You').

Visual explanation

Social Feed Ranking — Full System Architecture:

USER REQUEST (feed refresh) │ ▼ ┌────────────────────────────────────────────────────────────┐ │ CANDIDATE FETCHING (parallel streams) │ │ │ │ Stream A: Network posts │ │ 'Posts from the ~500 accounts this user follows' │ │ Pull from pre-built user's follow-feed index │ │ Limit: last 2,000 posts (time-bounded window) │ │ │ │ Stream B: Algorithmic recommendations │ │ 'Posts beyond the user's follows' │ │ Two-tower retrieval from a global content index │ │ Trending posts in the user's topic interest areas │ │ │ │ Stream C: Ads (sold separately, injected by ads system) │ │ │ │ ────► MERGE + DEDUPLICATE ◄──── ~500-1000 candidates │ └──────────────────────────────┬─────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────────┐ │ LIGHTWEIGHT FILTER (fast, pre-ranking) │ │ • Remove posts already seen by this user │ │ • Remove posts from muted/blocked accounts │ │ • Safety filter: remove policy-violating posts │ │ • Deduplicate near-duplicate posts (same story, many RTs) │ └──────────────────────────────┬─────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────────┐ │ DEEP RANKING MODEL │ │ │ │ For each candidate post, compute: │ │ │ │ Network signals: │ │ • P(user engages with this author) — follow affinity │ │ • Recent interaction rate (user → author) │ │ │ │ Content signals: │ │ • Topic match: post_topic_emb · user_interest_emb │ │ • Content type (text, image, video, link) │ │ • Post quality score (grammar, spam signals) │ │ │ │ Engagement signals: │ │ • Global like rate for this post (early engagement) │ │ • Global share rate │ │ • Global reply rate (discussion signal) │ │ │ │ Combined score (multi-task): │ │ = w1×P(like) + w2×P(reply) + w3×P(repost) │ │ - w4×P(not_interested) - w5×P(report) │ │ │ │ ────► TOP 100 ranked by score │ └──────────────────────────────┬─────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────────┐ │ RE-RANKING + SERVING POLICY │ │ • Time-decay: boost posts < 4h old, penalize posts > 24h │ │ • Author diversity: max 3 posts per author per load │ │ • Content type mixing: balance text, image, video │ │ • Safety final pass: content moderation model │ │ • Ads injection at fixed positions │ └──────────────────────────────┬─────────────────────────────┘ │ ▼ FINAL FEED (20-50 posts) → User

Fan-Out Architecture:

Celebrity posts (>100K followers): Post created → NOT pre-distributed → pulled at query time (fan-out on read: too expensive to push to 10M feeds immediately)

Regular users (<100K followers): Post created → pushed to each follower's feed index immediately (fan-out on write: manageable volume, lower query-time latency)

Advantages

  • Multi-task ranking (predict like + reply + share + report as separate heads) captures different dimensions of post quality that a single engagement prediction misses

  • Author diversity constraints at re-ranking time prevent any single account from dominating the feed, even if that author consistently scores highest

  • Hybrid fan-out (write for regular users, read for celebrities) balances write throughput against read latency without over-engineering for the edge case

  • Time-decay is a simple, tunable mechanism that keeps the feed feeling current without requiring separate recency models

  • Pre-filtering (removing seen posts, muted/blocked accounts, policy violations) before ranking reduces the ranking candidate pool cheaply and protects the user

Disadvantages

  • The fan-out on write approach creates stale feeds: a post from a followed account is pre-written to the feed cache, but if engagement features update, the cache doesn't reflect the change until the next feed rebuild

  • Multi-task ranking with negative signals (report, not_interested) requires large amounts of negative engagement data — negative signals are rare compared to non-engagement, making them hard to predict accurately

  • Time-decay favors recency over quality — a high-quality post from 48 hours ago may rank below a low-quality post from 30 minutes ago once decay is applied

  • Author diversity constraints are static (max N per author per load) and don't adapt to how much the user actually wants to see from that author in this session

  • Feed ranking is one of the most consequential ML systems for societal effects — the engagement vs. well-being tension has no clean technical solution and requires ongoing policy calibration

Common mistakes

  • Not addressing the fan-out problem. Many engineers design the feed ranking pipeline without addressing how posts get into the candidate pool in the first place. A naive implementation that reads all posts from all followed accounts at query time fails at scale: a user following 1,000 accounts at 50 posts/day = 50,000 posts to scan per request. The fan-out architecture must be part of the design.

  • Treating feed ranking as identical to content recommendation. Social feeds have structural differences: the content is user-generated (not curated), network relationships constrain the candidate set, time-sensitivity is different, and the trust/well-being dimension is far more prominent. A design that treats feed ranking as 'just YouTube for posts' misses the fan-out problem, the network signal category, and the engagement-vs-well-being tension.

  • Optimizing engagement without guardrail metrics. Maximizing likes + shares + replies produces feeds heavy with outrage and divisive content — these reliably generate high reply rates. A complete design must include negative guardrail metrics (report rate, unfollow rate, satisfaction survey) that prevent the primary engagement metrics from being optimized in harmful directions.

  • Ignoring deduplication. In a social network, the same news story may be shared by 20 accounts the user follows. Without deduplication (URL matching + near-duplicate text detection), the user sees the same story 20 times. This is a significant quality problem that's easily fixable with MinHash or URL normalization before ranking.

  • Static author diversity caps. Capping at 'max 3 posts per author' is a reasonable default but doesn't adapt to context. If a user has just followed a new author and is actively reading all their posts, the cap becomes frustrating. A more sophisticated system uses session signals ('user has clicked on 3 posts from author X in this session → they clearly want more') to dynamically adjust per-author limits.

🎤 Interview questions

Design a social feed ranking system for a platform with 300M users and asymmetric follow relationships (like Twitter). Walk me through every component from post creation to feed display.

Explain the fan-out problem in social feeds. What is the difference between fan-out on write and fan-out on read? When would you use each?

What signals would you use to rank posts in a social feed, and how would you combine them? What are the risks of optimizing purely for engagement?

A new ranking model increases total likes and replies by 8%, but the report rate also increases by 2% and user survey satisfaction drops. Should you ship it?

📂 Subtopics

📝 Quiz

💬 Deep Dive with AI

Related concepts

fan-out problempush vs. pull architecturemulti-task learningtime-decayauthor diversitynetwork signalsengagement signalscontent signalsfeed cachededuplicationMinHashfilter bubblewell-being metricsuser-author affinityrecommendation-system-componentscase-study-recommendation

Next to learn

recommendation-system-componentscase-study-recommendationai-system-architecture-patternseval-metrics-fundamentals

Next Step

Continue to Case Study: Search and Listing Ranking System Design