Skip to content
advancedPhase 52 · HLD Case Studies

News Feed

Design a news feed generation system with fanout.

2h
0 problems
Topic Progress0%

Requirements & Scope

Functional Requirements

Core features of a Facebook/LinkedIn-style news feed:

  • Create Posts: Users publish text, images, videos, links, or status updates
  • View Feed: Users see a feed of posts from connections/friends, sorted chronologically or by relevance
  • Like/Comment: Users engage with posts through reactions and threaded comments
  • Share/Repost: Users share posts to their own network
  • Follow Connections: Users connect with others to see their posts in feed
  • Notifications: Users receive alerts for interactions on their posts

Non-Functional Requirements

Requirement Target Rationale
Feed Generation Latency < 500ms Users expect instant feed load
Availability 99.99% Social platforms must always be accessible
Consistency Eventual consistency OK A few seconds delay for new posts is acceptable
Throughput 100K posts/sec write, 500K feed reads/sec LinkedIn-scale numbers
Durability All posts must be persisted permanently Users expect data persistence
Media Support Images, videos, links with previews Rich content is essential
Scalability 1B+ registered users, 500M+ DAU Must handle massive scale

Core Entities

User:      { user_id, name, email, profile_pic, created_at }
Post:      { post_id, user_id, content, media_urls, post_type, visibility, created_at }
Like:      { like_id, user_id, post_id, reaction_type, created_at }
Comment:    { comment_id, user_id, post_id, parent_id, content, created_at }
Follow:    { follower_id, followee_id, created_at }
Feed:      { user_id, post_ids[], last_updated }
Share:     { share_id, user_id, original_post_id, commentary, created_at }

Capacity Estimation

Write load: 100M posts/day = ~1,160 posts/sec avg, ~3,000 posts/sec peak
Read load: Each user views feed ~15 times/day = 7.5B reads/day = ~87K reads/sec avg
Storage: 100M posts/day * 2KB avg (including metadata) = 200GB/day = ~73TB/year
Media: 100M posts * 30% have media * 500KB avg = 15TB/day
Comments: ~500M comments/day = ~5.8K comments/sec

Key Design Decisions

  1. Feed ordering: Chronological (simple) vs algorithmic/ranked (engagement-optimized)
  2. Fanout strategy: Push vs pull vs hybrid for feed generation
  3. Media handling: CDN for images/videos, async upload processing
  4. Comment threading: Flat vs nested comment structure
  5. Real-time updates: Long-polling, WebSockets, or periodic polling

Fanout on Write

How Fanout on Write Works

When a user creates a post, the system immediately pushes the post ID to all followers' pre-computed feed caches.

User creates post
    |
    v
Post Service stores post in DB
    |
    v
Publishes "new_post" event to Kafka
    |
    v
Fanout Workers consume event
    |
    +---> Push post_id to Follower 1's feed cache
    +---> Push post_id to Follower 2's feed cache
    +---> Push post_id to Follower 3's feed cache
    +---> ... (all followers)

Implementation

Fanout Worker Logic

def fanout_post(post, author):
    follower_ids = get_follower_ids(author.id)
    
    pipeline = redis.pipeline()
    for follower_id in follower_ids:
        # Add post to follower's feed sorted set (scored by timestamp)
        pipeline.zadd(
            f"feed:{follower_id}",
            {post.id: post.created_at.timestamp()}
        )
        # Trim to keep only last 1000 posts per user
        pipeline.zremrangebyrank(f"feed:{follower_id}", 0, -1001)
        
        # Send notification (async, separate pipeline)
        if is_active(follower_id):
            notify(follower_id, post)
    
    pipeline.execute()  # Single atomic batch

Feed Read Path

def get_feed(user_id, page=1, count=50):
    offset = (page - 1) * count
    
    # 1. Get post IDs from Redis sorted set
    post_ids = redis.zrevrange(f"feed:{user_id}", offset, offset + count - 1)
    
    # 2. Batch fetch full post details from database
    posts = batch_get_posts(post_ids)
    
    # 3. Hydrate with author info, like counts, comment counts
    hydrated = hydrate_posts(posts)
    
    return hydrated

Pros and Cons

Pros Cons
Feed reads are extremely fast (O(1) lookup) Write amplification: 1 post = N writes (N = follower count)
No computation at read time Wasted work for users who never check their feed
Simple read path, easy to cache Popular users cause massive fanout bursts
Predictable read latency Storage overhead: each user's feed is duplicated

When to Use Fanout on Write

  • Users typically have a bounded number of connections (< 5,000)
  • Read-to-write ratio is high (users read much more than they post)
  • Low latency feed generation is critical
  • System can tolerate some write amplification

Fanout on Read

How Fanout on Read Works

When a user opens their feed, the system dynamically fetches recent posts from all their connections and merges them in real-time.

User opens feed
    |
    v
Feed Service receives request
    |
    v
Get list of followees (who user follows)
    |
    v
Query recent posts from each followee (parallel)
    |
    +---> User A: latest 20 posts
    +---> User B: latest 20 posts
    +---> User C: latest 20 posts
    +---> ... (all followees)
    |
    v
Merge all posts, sort by timestamp
    |
    v
Apply ranking model (optional)
    |
    v
Return top N posts to client

Implementation

Feed Read Logic

def get_feed(user_id, count=50):
    # 1. Get followee list
    followee_ids = get_followees(user_id)  # From graph DB or cache
    
    # 2. Fetch recent posts from each followee (parallel queries)
    all_posts = []
    with ThreadPool(max_workers=20) as pool:
        futures = [
            pool.submit(get_recent_posts, fid, limit=20)
            for fid in followee_ids
        ]
        for future in futures:
            all_posts.extend(future.result())
    
    # 3. Merge and sort by timestamp
    all_posts.sort(key=lambda p: p.created_at, reverse=True)
    
    # 4. Apply ranking (optional)
    ranked_posts = rank_posts(all_posts, user_id)
    
    return ranked_posts[:count]

Database Queries

-- Get recent posts from a specific user
SELECT post_id, content, media_urls, created_at
FROM posts
WHERE user_id = ? AND visibility = 'public'
ORDER BY created_at DESC
LIMIT 20;

-- Get followees of a user
SELECT followee_id
FROM follows
WHERE follower_id = ?;

Pros and Cons

Pros Cons
No write amplification Slow reads: must query all followees
Always shows freshest content Latency scales with number of followees
No wasted computation Computationally expensive at read time
Storage efficient (no duplicate feeds) Hard to meet <500ms SLA for users with many connections

Caching Optimizations

  1. Cache followee lists in Redis to avoid graph DB lookups on every read
  2. Cache recent posts per user in Redis to reduce DB queries
  3. Use read replicas for post queries to distribute read load
  4. Pre-warm feeds for high-traffic users during off-peak hours

Hybrid Approach

The Hybrid Strategy

Combine fanout-on-write for normal users with fanout-on-read for high-follower accounts.

User creates post
    |
    v
Post Service stores post
    |
    v
Check author's follower count:
    |
    +-- < 10,000 followers --> Fanout Service pushes to followers' feeds
    |
    +-- >= 10,000 followers --> No fanout; pull at read time

Feed Read with Hybrid

def get_feed_hybrid(user_id, count=50):
    # 1. Get pre-computed feed from Redis (push-based posts)
    pre_computed_ids = redis.zrevrange(f"feed:{user_id}", 0, count * 2)
    pre_computed_posts = batch_get_posts(pre_computed_ids)
    
    # 2. Get followed high-follower accounts
    high_follower_ids = get_followed_high_follower_accounts(user_id)
    
    # 3. Pull recent posts from high-follower accounts
    pull_posts = []
    for hf_id in high_follower_ids:
        posts = get_recent_posts(hf_id, limit=5)
        pull_posts.extend(posts)
    
    # 4. Merge, deduplicate, and sort
    all_posts = merge_and_dedup(pre_computed_posts, pull_posts)
    all_posts.sort(key=lambda p: p.created_at, reverse=True)
    
    # 5. Apply ranking
    ranked = apply_ranking_model(all_posts, user_id)
    
    return ranked[:count]

Threshold Design

Follower Count Strategy Fanout Cost Read Cost
< 1,000 Push only Minimal Very fast
1,000 - 10,000 Push only Moderate Fast
10,000 - 100,000 Hybrid (pull this user's posts) N/A for this user Slight delay
> 100,000 Pull only Zero Must pull

Migration Logic

When a user crosses the threshold (e.g., from 9,999 to 10,000 followers):

  1. Stop pushing new posts to followers' feeds
  2. Existing pushed posts remain in followers' caches until they expire
  3. Mark user as "high-follower" in metadata
  4. Followers' read path automatically starts pulling from this user

Benefits of Hybrid

  • 95% of users have <1,000 followers — fanout-on-write works perfectly
  • Top 5% of users (influencers, brands) use pull — avoids massive fanout
  • Feed latency remains <500ms for all users
  • Write amplification stays bounded
  • This is what Facebook, LinkedIn, and Instagram actually use

Ranking & Optimization

Feed Ranking Models

Chronological (Simple)

Sort posts by creation timestamp, newest first. Simple but may show low-quality or irrelevant content.

Engagement-Based Ranking

Predict the probability a user will engage (like, comment, share, click) with each post.

score(post, user) = w1 * recency(post)
                  + w2 * affinity(user, post.author)
                  + w3 * content_quality(post)
                  + w4 * engagement_rate(post)
                  + w5 * post_type_weight(post.type)

Ranking Signal Breakdown

Signal Description Weight
Recency How recent is the post (exponential decay) 0.3
Affinity How often user interacts with author 0.25
Engagement Rate Likes/comments/shares per impression 0.2
Content Quality Text quality, image resolution, spam score 0.15
Post Type Video > Photo > Link > Text (engagement varies) 0.1

ML Ranking Pipeline

1. Candidate Generation: Fetch ~500 candidate posts (pull + push feeds)
2. Feature Extraction: Extract user, post, and interaction features
3. Model Scoring: Run through ranking model (e.g., XGBoost, neural net)
4. Filtering: Remove blocked/muted users, already-seen posts
5. Diversification: Ensure mix of content types, authors
6. Return top 50 posts to client

Optimization Strategies

CDN for Media

Client --> CDN Edge (cached media)
         |
         +--> Cache HIT: serve from edge (< 50ms)
         +--> Cache MISS: fetch from S3 origin, cache at edge
  • Images served from nearest CDN edge location
  • Videos use adaptive bitrate streaming (HLS/DASH)
  • Thumbnails pre-generated and cached

Background Pre-fetching

On app open (background thread):
1. Fetch next page of feed while user reads current page
2. Pre-load images for visible posts
3. Pre-fetch comments for posts near viewport

Async Processing

  • Like/comment counts updated asynchronously via Kafka events
  • Notification delivery is async (separate service)
  • Media processing (thumbnails, transcoding) is async
  • Feed ranking model runs in background, updates cached feed scores

Pagination & Infinite Scroll

GET /api/feed?cursor=<timestamp>&limit=50

Response:
{
  "posts": [...],
  "next_cursor": "2024-01-15T10:30:00Z",
  "has_more": true
}

Use cursor-based pagination (not offset) for consistent results during concurrent writes.

Handling Viral Content

When a post gets millions of views/engagements in minutes:

  1. Rate limit comments to prevent database overload
  2. Cache hot post at CDN edge and application cache
  3. Queue comment writes through Kafka to smooth out spikes
  4. Shard post data across multiple partitions if needed
  5. Degrade gracefully: show cached like counts, delay real-time updates

Practice Problems

0/2solved
Design Post Visibility Control

Implement a post visibility system that supports public, friends-only, custom lists, and audience restrictions for posts in the news feed.

Design Comment Threading

Design a threaded comment system that supports nested replies, real-time updates, and efficient storage for posts with thousands of comments.

Quiz

1. In fanout-on-write, what happens when a user with 100,000 followers creates a post?

Question 1 options

2. What is the main disadvantage of fanout-on-read compared to fanout-on-write?

Question 2 options

3. Why do Facebook, LinkedIn, and Instagram use a hybrid approach for feed generation?

Question 3 options

4. What database is typically used for storing the primary post data in a news feed system?

Question 4 options

5. What is cursor-based pagination and why is it preferred over offset-based pagination for feeds?

Question 5 options

6. In a ranking model for news feed, what does the 'affinity' signal measure?

Question 6 options

7. What is the purpose of the candidate generation step in an ML ranking pipeline?

Question 7 options

8. How does a CDN help optimize news feed performance?

Question 8 options

Flashcards

Question

What is the difference between fanout-on-write and fanout-on-read in a news feed system?

Answer

Fanout-on-write pushes post IDs to all followers' feed caches when a post is created (fast reads, expensive writes). Fanout-on-read fetches posts from all followees dynamically when the feed is requested (no write amplification, slow reads).

Question

Why is a hybrid fanout approach preferred in production news feed systems?

Answer

It combines push for normal users (fast reads, manageable write cost) with pull for high-follower accounts (avoids massive write amplification). This balances latency and write efficiency — 95% of users have <1K followers, so push works well for them.

Question

What signals does a news feed ranking model typically use?

Answer

Recency (exponential time decay), affinity (interaction frequency with author), engagement rate (likes/comments/shares per view), content quality (spam score, text analysis), and post type weight (video > photo > link > text).

Question

Why is cursor-based pagination preferred over offset-based pagination for infinite scroll feeds?

Answer

Cursor-based pagination uses the last item's timestamp/ID as a bookmark. When new posts are added, it avoids skipping or duplicating posts. Offset-based pagination breaks under concurrent writes, causing inconsistent feed results.

Question

What are the three main steps of an ML-based feed ranking pipeline?

Answer

1) Candidate Generation: fetch ~500 candidate posts with simple heuristics. 2) Scoring: run ML model (XGBoost/neural net) on candidates. 3) Filtering and Diversification: remove blocked/muted content, ensure variety, return top N posts.

Question

How does a CDN optimize media delivery in a news feed?

Answer

CDN caches images, videos, and thumbnails at edge locations worldwide. When a user loads their feed, media is served from the nearest edge (< 50ms latency) instead of the origin server. This reduces load times and bandwidth costs significantly.

Question

What is write amplification and why is it a concern in fanout-on-write?

Answer

Write amplification occurs when one logical write (creating a post) triggers multiple physical writes (pushing to N followers' caches). For a user with 50K followers, one post = 50K Redis writes. This can overwhelm the write path and cause cascading failures.

Question

What storage system is best for pre-computed feed caches and why?

Answer

Redis sorted sets are ideal. They provide O(log N) retrieval of the most recent items, support time-based scoring, allow atomic batch writes, and operate from memory with sub-millisecond latency. ZREVRANGE fetches the latest N posts instantly.

Question

How should you handle viral content that suddenly gets millions of views?

Answer

1) Cache the hot post at CDN and application layers. 2) Rate-limit comments to prevent DB overload. 3) Queue writes through Kafka to smooth spikes. 4) Shard post data across partitions if needed. 5) Degrade gracefully — show cached counts, delay real-time updates.

Question

What role does Kafka play in a news feed architecture?

Answer

Kafka serves as the event backbone: new posts, likes, comments, and follows are published as events. Fanout workers consume post events to update feed caches. Async processing decouples write-heavy operations from the main request path, improving reliability and throughput.

Revision Notes

Key Takeaways

  • 1.News feed systems must balance fast feed generation (<500ms) with efficient write operations at massive scale
  • 2.Fanout-on-write gives fast reads but suffers from write amplification; fanout-on-read avoids writes but is slow
  • 3.The hybrid approach (push for normal users, pull for high-follower accounts) is the production standard used by Facebook, LinkedIn, and Instagram
  • 4.Feed ranking transforms chronological feeds into engagement-optimized feeds using recency, affinity, engagement rate, and content quality signals
  • 5.ML ranking pipelines use candidate generation followed by model scoring to efficiently rank hundreds of posts
  • 6.Cursor-based pagination ensures consistent feed results when new posts are added concurrently
  • 7.CDN is essential for media delivery — images and videos served from edge locations with <50ms latency
  • 8.Kafka enables async processing of fanout, likes, comments, and notifications, decoupling write-heavy operations from the request path

Interview Tips

  • Always start by clarifying scope — ask about scale (100M vs 1B users), features (do we need stories/reels?), and latency requirements
  • Draw the write path and read path separately on the whiteboard — interviewers want to see both flows clearly
  • Proactively mention the celebrity/high-follower problem — it shows you understand real-world scaling challenges
  • Explain WHY you chose each technology — not just 'use Redis' but 'use Redis sorted sets because ZREVRANGE gives O(log N) time-ordered retrieval'
  • When discussing ranking, start simple (chronological) then layer on complexity (ML ranking) — don't jump to the hardest solution first
  • Discuss trade-offs explicitly for every decision — push vs pull, consistency vs availability, real-time vs batch processing
  • Mention failure modes and monitoring — what happens when Redis goes down? How do you detect fanout lag?
  • End with optimization discussion — CDN for media, background pre-fetching, rate limiting for viral content — shows production-minded thinking

Cheat Sheet

News Feed System Design - Cheat Sheet

Functional Requirements

  • Create posts (text, images, videos, links), view feed, like/comment, share, follow connections, notifications

Non-Functional Requirements

  • Feed generation < 500ms, 99.99% availability, eventual consistency OK, 100K posts/sec write, 500K feed reads/sec

Architecture Components

Component Purpose
Post Service Validate, store posts, trigger fanout events
Fanout Service Push post IDs to followers' feed caches
Feed Service Read from cache, pull celebrity posts, apply ranking
Ranking Service Score posts using ML model, return ranked feed
Notification Service Send alerts for likes, comments, mentions
Media Service Upload, transcode, serve images/videos via CDN

Fanout Strategies

Strategy Mechanism Best For Drawback
Push (on-write) Pre-compute feeds at write time Normal users (<10K followers) Write amplification
Pull (on-read) Compute feed at read time Celebrities (>10K followers) High read latency
Hybrid Push + pull combined Production standard Complexity in merging

Storage Choices

Data Store Why
Posts MySQL/PostgreSQL + read replicas Structured, ACID, relational queries
Feed cache Redis Sorted Sets Sub-ms reads, time-ordered, atomic batch ops
Media S3 + CDN Object storage + edge caching
Search Elasticsearch Full-text post search
Graph (follows) Neo4j or adjacency list in MySQL Relationship queries
Events Kafka Async processing, event sourcing

Feed Ranking Signals

Signal Weight Description
Recency 0.3 Exponential time decay
Affinity 0.25 Interaction frequency with author
Engagement Rate 0.2 Likes/comments/shares per impression
Content Quality 0.15 Spam score, text quality
Post Type 0.1 Video > Photo > Link > Text

ML Ranking Pipeline

  1. Candidate Generation (~500 posts from push + pull feeds)
  2. Feature Extraction (user, post, interaction features)
  3. Model Scoring (XGBoost / neural network)
  4. Filtering (blocked users, muted content, already seen)
  5. Diversification (mix of content types and authors)
  6. Return top 50 ranked posts

Optimization Strategies

  • CDN for media delivery (images, videos, thumbnails)
  • Cursor-based pagination for infinite scroll
  • Background pre-fetching (next page, images, comments)
  • Async processing via Kafka (likes, comments, notifications)
  • Rate limiting for viral content

Key Numbers

  • 100M posts/day = ~1,160 posts/sec avg
  • 7.5B feed reads/day = ~87K reads/sec avg
  • Redis feed cache: keep last 1,000 posts per user
  • Celebrity threshold: ~10,000 followers
  • CDN edge latency: < 50ms vs origin: 200-500ms

Interview Flow

  1. Requirements (5 min) - functional + non-functional + capacity estimation
  2. High-level design (10 min) - draw architecture, identify services
  3. Data model (10 min) - schema, storage selection, why each store
  4. Deep dive: Feed generation (15 min) - push, pull, hybrid with tradeoffs
  5. Deep dive: Ranking (10 min) - signals, ML pipeline, real-time vs batch
  6. Scaling & optimization (10 min) - CDN, caching, handling viral content