Meta System DesignSystem Design

Designing Facebook News Feed

Build a personalized feed system that ranks and delivers billions of posts to hundreds of millions of concurrent users.

Feed RankingCachingFan-outReal-timeMachine Learning

Problem Statement

Design a News Feed system that displays a personalized stream of posts from friends, pages, and groups. The system must handle billions of posts, serve hundreds of millions of daily active users, rank content by relevance, and deliver updates in near real-time.

Why This Problem Matters

  • News Feed is Meta's flagship product and a canonical system design question that tests understanding of fan-out strategies, ranking systems, and caching at scale.
  • Demonstrates ability to balance latency, consistency, and personalization in a read-heavy system.
  • Reveals trade-offs between push (fan-out on write) and pull (fan-out on read) architectures.

Thought Process

Clarify requirements and scale

Start by establishing the scale: ~2B daily active users, each with ~500 friends on average, posting several times per week. A user's feed might aggregate from thousands of potential sources. Clarify if "real-time" means seconds or minutes, and whether feed includes ads, stories, and reels.

Identify core operations

The two main operations are publishing a post (write path) and fetching the feed (read path). Publishing involves storing the post and notifying followers. Fetching involves aggregating posts from all sources, ranking them, and returning the top N.

Choose between push and pull models

Pure push (fan-out on write) pre-computes feeds when a post is created—fast reads but expensive writes for popular users. Pure pull (fan-out on read) fetches and ranks on demand—fast writes but slow reads. The hybrid approach pushes for regular users and pulls for celebrities (users with millions of followers).

Design the ranking system

Ranking is not just chronological. Factors include affinity (how often you interact with the author), post type (photo vs text), engagement signals (likes, comments), recency, and user preferences. An ML model scores each candidate post, and the top-K are returned.

Plan caching and storage

Cache pre-computed feeds in Redis/Memcached clusters. Store posts in a distributed database like TAO (Meta's graph store). Media goes to a CDN. Consider tiered caching: L1 (co-located with app servers), L2 (regional), and L3 (global).

Step-by-Step Reasoning

  1. Post Creation: User creates a post → Write to Posts DB → Store media in blob storage → Trigger fan-out service.
  2. Fan-out Service: For regular users, push post ID to followers' feed caches. For celebrities, mark as "pull-on-read" candidate.
  3. Feed Generation: When user requests feed, fetch pre-computed feed from cache → Merge with pull-on-read candidates → Score with ranking model → Return top N posts.
  4. Ranking: Fetch candidate features → Run through ML ranker → Apply diversity rules (avoid 5 posts from same friend) → Apply ads interleaving.
  5. Real-time Updates: Use long-polling or WebSocket to push new post notifications → Client fetches updated feed.

Dry Run

Alice posts a photo (Alice has 300 friends)

Fan-out service pushes Alice's post ID to all 300 friends' feed caches in parallel. Takes ~50ms total with batched writes.

Bob opens Facebook (Bob follows Alice and 2 celebrities with 10M followers each)

Feed service fetches Bob's cached feed (includes Alice's post) + queries recent posts from the 2 celebrities → Ranks all candidates → Returns top 50.

Celebrity posts (10M followers)

Post stored in DB but NOT fanned out. Marked as pull-on-read. Each follower's feed fetch includes a query for this celebrity's recent posts.

Complexity Analysis

Time

Write: O(1) for celebrities, O(followers) for regular users. Read: O(sources) for candidate generation, O(n log k) for top-k ranking.

Space

O(users × feed_size) for cached feeds, O(posts) for post storage. Estimated: ~500 post IDs per user × 2B users = 1 trillion entries.

Why

Hybrid fan-out limits write amplification while caching keeps reads fast. Ranking is bounded by candidate pool size (~1000 posts).

Annotated Solution

// Simplified Feed Service pseudocode
public class FeedService {
    private FeedCache feedCache;
    private PostStore postStore;
    private FollowGraph followGraph;
    private Ranker ranker;

    public List<Post> getFeed(String userId, int limit) {
        // 1. Get cached feed (pre-computed post IDs)
        List<String> cachedPostIds = feedCache.get(userId);

        // 2. Get pull-on-read candidates (celebrities user follows)
        List<String> celebrities = followGraph.getCelebrities(userId);
        List<String> pullPostIds = postStore.getRecentPosts(celebrities);

        // 3. Merge candidates
        Set<String> allCandidates = new HashSet<>();
        allCandidates.addAll(cachedPostIds);
        allCandidates.addAll(pullPostIds);

        // 4. Fetch full post objects
        List<Post> posts = postStore.batchGet(allCandidates);

        // 5. Rank and return top K
        return ranker.rank(posts, userId, limit);
    }

    public void publishPost(String authorId, Post post) {
        // Store post
        postStore.save(post);

        // Fan-out decision
        int followerCount = followGraph.getFollowerCount(authorId);
        if (followerCount < CELEBRITY_THRESHOLD) {
            // Push to followers' caches
            fanOutService.pushToFollowers(authorId, post.getId());
        }
        // Celebrities: post will be pulled on read
    }
}

This pseudocode shows the hybrid fan-out approach. Regular users' posts are pushed to followers' caches, while celebrity posts are pulled on demand during feed generation.

Common Pitfalls

  • Pure push model breaks down for celebrities—writing to millions of feed caches creates thundering herd problems and delays.
  • Stale feeds: cached feeds can become outdated. Use TTL + background refresh to balance freshness vs load.
  • Hot partitions: popular posts or users can overwhelm single nodes. Use consistent hashing with virtual nodes and replication.
  • Privacy: deleted posts must be purged from all caches. Implement async deletion with eventual consistency.

Follow-Up Questions

  • How would you implement "See less of this" functionality? (Store negative signals, adjust ranking model features)
  • How do you handle feed for a new user with no friends? (Cold start with trending/suggested content)
  • How would you A/B test a new ranking model? (Shadow scoring, percentage rollout, engagement metrics)

Key Takeaways

Hybrid fan-out (push for regular users, pull for celebrities) balances write cost and read latency.
Ranking is critical—chronological feeds are outdated. Use ML models with engagement, affinity, and recency signals.
Caching is essential for read-heavy workloads. Use tiered caching with TTL-based invalidation.
Design for failure: posts can be delayed, feeds can be stale, but the system should degrade gracefully.