Full Stack • Java • System Design • Cloud • AI Engineering

Facebook News Feed System Design - 1 Hour Interview Guide

Design a scalable personalized news feed system like Facebook. Covers requirements, capacity estimation, social graph, post creation, fan-out strategies, feed ranking, EdgeRank, database design, caching, and trade-offs for a 1-hour system design interview.


1-Hour Interview Roadmap

Time Topic
0 – 5 min Requirements clarification
5 – 10 min Capacity estimation
10 – 18 min High-level architecture + social graph
18 – 28 min Post creation + fan-out strategy
28 – 40 min Feed retrieval + ranking
40 – 48 min Database design + caching
48 – 55 min Scaling + multi-region
55 – 60 min Trade-offs + failure scenarios

What Are We Building?

A personalized news feed that shows each user a ranked, continuously updated stream of posts, photos, videos, and stories from their friends, followed pages, and groups — ordered not by time alone but by relevance.

Scale reference: Facebook has 3 billion monthly active users, 2 billion daily active users, 500 million posts per day, and every user's feed must be assembled and ranked in under 200ms.

The key difference from Instagram: Facebook's feed is ranked by relevance (engagement signals, relationship strength, content type), not just reverse-chronological time order. This makes feed generation significantly more complex.


Step 1 — Requirements

Functional Requirements

# Requirement
1 Users see a personalized, ranked feed on their home page
2 Feed contains posts, photos, videos, links, and shares from friends and pages
3 Posts appear based on relevance score — not strictly newest first
4 Feed updates continuously as friends post (near real-time)
5 Users can like, comment, share, and react to posts
6 Users can create text, photo, video, and link posts
7 Users can follow friends, pages, and groups
8 Feed can be paginated — "Load more" or infinite scroll
9 Users receive notifications for interactions on their posts

Non-Functional Requirements

# Requirement
1 Feed assembly latency < 200ms (p99)
2 Post creation must be acknowledged < 500ms
3 High availability — 99.99% uptime
4 Feed is eventually consistent — a new post may take up to 10 seconds to appear
5 Ranking must be computed at scale — 2B users × personalized scores
6 System must handle extreme skew — pages with 500M followers
7 Read-heavy — feed reads vastly outnumber post writes

Out of Scope

  • Ads and sponsored content ranking
  • Video transcoding pipeline details
  • Marketplace, Events, Groups feed
  • Privacy and content moderation

Step 2 — Capacity Estimation

Assumptions

Metric Value
Daily Active Users (DAU) 2 billion
Monthly Active Users (MAU) 3 billion
Posts created per day 500 million
Average friends per user 200
Average pages followed per user 50
Feed loads per user per day 15
Posts shown per feed load 20
Average post size (text+meta) 1 KB
Read-to-write ratio ~300:1

Write Volume

500 million posts/day
= ~5,800 posts/second (sustained)
= ~18,000 posts/second (peak)

Feed Read Volume

2B DAU × 15 feed loads/day = 30 billion feed reads/day
= ~347,000 feed reads/second (sustained)
= ~1,000,000 feed reads/second (peak)

Fan-out Volume

Average user: 200 friends + 50 pages they follow
Average fan-out per post: ~200 feed writes

500M posts/day × 200 = 100 billion feed writes/day
= ~1.16 million fan-out writes/second

Key Insight

The fan-out write volume (1.16M/sec) is the biggest design challenge. A public page with 500M followers posting once generates 500 million fan-out writes — this cannot be done synchronously. Feed ranking adds another layer of complexity on top of the raw assembly problem.


Step 3 — High-Level Architecture

flowchart TD
    Client --> AG[API Gateway\nAuth + Rate Limiting]

    AG --> POS[Post Service]
    AG --> FES[Feed Service]
    AG --> USS[User & Graph Service]
    AG --> RES[Reaction Service]
    AG --> NOS[Notification Service]

    POS --> KF[Kafka\npost.created events]
    KF --> FO[Fan-out Service]
    KF --> NW[Notification Workers]

    FO --> FDB[(Feed Store\nRedis + Cassandra)]
    FO --> RANK[Ranking Service\nScore Computation]
    RANK --> FDB

    FES --> FC[(Feed Cache\nRedis)]
    FC -->|miss| FDB
    FDB -->|miss| PDB[(Post Store\nCassandra)]

    USS --> SG[(Social Graph\nTAO / Cassandra)]
    POS --> PDB
    RES --> PDB

    NW --> FCM[FCM / APNs]
    NW --> NDB[(Notification Store)]

Component Responsibilities

Component Responsibility
API Gateway JWT auth, rate limiting, routing
Post Service Create, edit, delete posts; publish fan-out events to Kafka
Fan-out Service Consume post events; write post IDs to followers' feed stores
Ranking Service Compute relevance scores for posts per user; sort feed by score
Feed Service Assemble and return ranked feed from cache or store
User & Graph Svc Manage friendships, page follows, group memberships (TAO/social graph)
Reaction Service Handle likes, reactions, comments; update engagement signals
Notification Svc Async delivery of interaction notifications
Social Graph The friendship + follow relationship store — core of fan-out and feed assembly

Step 4 — Social Graph

Why the Social Graph Is Central

Every fan-out decision requires answering: "Who are all the followers of this user?"

At Facebook's scale, each user has ~200 friends on average, but pages can have 500M followers. The social graph must support:

  • GET followers(user_id) — return all followers (for fan-out)
  • GET following(user_id) — return all accounts this user follows (for feed assembly)
  • Sub-millisecond reads — called on every post and every feed load

Facebook's TAO (The Associations and Objects)

Facebook built a custom graph storage system called TAO to serve the social graph:

flowchart LR
    CLIENT["Client App"]

    CACHE["TAO Cache Layer"]

    DB["MySQL Social Graph DB"]

    RESPONSE["Response"]

    CLIENT --> CACHE

    CACHE -->|cache hit| RESPONSE
    CACHE -->|cache miss| DB
    DB --> CACHE
    CACHE --> RESPONSE
Layer Technology Role
Hot cache TAO in-memory Sub-ms reads for popular users / pages
Warm tier Memcached / Redis Region-local cache of graph edges
Cold tier MySQL / Cassandra Persistent storage of all friendships and follows

For interview purposes: Cassandra is a good answer — partition by user_id, cluster by friend_id, supports fast range reads of all friends.

Social Graph Schema (Cassandra)

Table: followers
  user_id      BIGINT   (the followed account)
  follower_id  BIGINT
  created_at   TIMESTAMP
  edge_type    VARCHAR  (FRIEND | FOLLOW | GROUP_MEMBER)
  PRIMARY KEY (user_id, follower_id)

Table: following
  user_id      BIGINT   (the user who follows)
  followed_id  BIGINT
  created_at   TIMESTAMP
  strength     FLOAT    (interaction frequency — used for ranking)
  PRIMARY KEY (user_id, followed_id)

The strength field on the following table captures how often two users interact — used by the ranking service as a signal.


Step 5 — Post Creation Flow

sequenceDiagram
    participant User
    participant PS as Post Service
    participant PDB as Post Store (Cassandra)
    participant KF as Kafka
    participant FO as Fan-out Service
    participant FDB as Feed Store (Redis/Cassandra)

    User->>PS: Create post {text, media_url, privacy}
    PS->>PS: Validate + assign post_id (Snowflake)
    PS->>PDB: Persist post
    PDB-->>PS: OK
    PS-->>User: ACK {post_id, status: PUBLISHED}

    PS->>KF: Publish post.created {post_id, author_id, timestamp}

    KF->>FO: Consume event
    FO->>SG: GET followers(author_id) — paginated
    loop For each follower batch (1000 at a time)
        FO->>FDB: Append post_id to follower's feed
    end

Key points:

  • User gets an ACK as soon as the post is persisted — fan-out happens asynchronously
  • Fan-out is batched — process followers in pages of 1,000
  • Large pages (500M followers) are handled specially — see hybrid fan-out below

Step 6 — Fan-out Strategy

The Core Challenge

Scenario Fan-out writes Problem
Regular user (200 friends) 200 writes Trivial — fan-out on write
Public figure (1M followers) 1M writes Significant — needs async batching
Celebrity page (500M followers) 500M writes Impossible synchronously

Hybrid Fan-out (Facebook's approach)

flowchart TD
    Post -->|author follower count?| FC{Follower\nCount}
    FC -->|< 100K\nRegular user| FW[Fan-out on WRITE\nPush to all feed stores\nasync, batched]
    FC -->|> 100K\nCelebrity / Page| FR[Fan-out on READ\nDo NOT push\nFetch at read time]

    FeedLoad[User loads feed] --> ASS[Feed Assembler]
    ASS -->|Pre-built cache| RegPosts[Regular friends' posts\nfrom Redis feed store]
    ASS -->|Pull live| CelPosts[Celebrity / page posts\nfetch top N from Post DB]
    ASS -->|Merge + Rank| RankedFeed[Ranked Feed]
    RankedFeed --> User

Push model (regular users < 100K followers)

  1. Fan-out Service consumes post event from Kafka
  2. Fetches follower list in batches of 1,000
  3. Appends post_id + raw score to each follower's feed sorted set in Redis
  4. Feed store holds the most recent 1,000 post IDs per user

Pull model (celebrities > 100K followers)

  1. No fan-out writes — celebrity's post is never pushed to individual feeds
  2. When Bob opens his feed, Feed Assembler pulls the top 50 posts from each celebrity he follows
  3. Merges them with his pre-built regular feed
  4. Result is ranked and returned

Why this boundary?

At 100K followers, a single post = 100K Redis writes. At peak (18K posts/sec from high-follower accounts), this is 1.8 billion writes/second — unsustainable. The hybrid model caps fan-out writes to a manageable level.


Step 7 — Feed Ranking

Why Ranking Matters

Facebook's feed is not reverse-chronological. A post from your best friend posted 3 hours ago ranks above a post from a distant acquaintance from 5 minutes ago. This is what keeps users engaged.

EdgeRank — Facebook's Original Algorithm

Facebook's original ranking model was called EdgeRank:

Score(post, user) = Affinity × Weight × Time Decay
Signal Meaning Example
Affinity How close is the user to the post's author? Message history, mutual friends, photo tags
Weight How engaging is the content type? Video > Photo > Link > Status update
Time Decay How recent is the post? Posts from 1 hour ago score higher than 1 week ago

Modern Feed Ranking (ML-based)

Today Facebook uses a multi-stage ML ranking pipeline:

flowchart LR
    FeedStore[Raw Feed\n1000 candidates] --> S1[Stage 1\nLight Scorer\nFilter to 500]
    S1 --> S2[Stage 2\nML Ranker\nNeuralNet\nRank top 100]
    S2 --> S3[Stage 3\nDiversity Filter\nAvoid same-author clusters]
    S3 --> S4[Final Feed\n20 posts]
    S4 --> User
Stage Method Candidates In Candidates Out Latency
Stage 1 Rule-based filter 1,000 500 < 5ms
Stage 2 Lightweight ML model 500 100 < 20ms
Stage 3 Deep neural network 100 20 < 50ms
Stage 4 Diversity + dedup 20 20 (reordered) < 5ms

Total ranking budget: ~80ms out of the 200ms total latency budget.

Ranking Signals

Signal Category Examples
Author signals Affinity score, mutual friends, interaction history
Content signals Media type, post length, link domain quality
Engagement signals Early likes/comments in first 30 minutes, shares, reaction type
User signals Time of day, device type, recently liked content type
Recency Time since post was created

Pre-computed vs Real-time Ranking

Approach When Pros Cons
Pre-computed Fan-out on write Fast feed load Stale scores; heavy compute
Real-time At feed load time Fresh signals Expensive at 1M req/sec
Hybrid Store raw candidates; rank at read time Balance of both Standard production approach

Chosen approach: Store post IDs (without scores) in feed store during fan-out. Rank the top 1,000 candidates at feed load time using pre-computed affinity scores from a separate user-affinity store.


Step 8 — Feed Retrieval Flow

sequenceDiagram
    participant Bob
    participant FS as Feed Service
    participant FC as Feed Cache (Redis)
    participant FDB as Feed Store (Cassandra)
    participant RANK as Ranking Service
    participant PDB as Post Store

    Bob->>FS: GET /feed?page=1
    FS->>FC: GET feed:{bob_id}
    alt Cache hit
        FC-->>FS: [post_id_1, post_id_2, ..., post_id_1000]
    else Cache miss
        FS->>FDB: Query timeline:{bob_id}
        FDB-->>FS: [post_id list]
        FS->>FC: Populate cache
    end

    FS->>RANK: Rank candidates (top 1000 post IDs, bob's context)
    RANK-->>FS: Top 20 ranked post IDs

    FS->>PDB: Batch fetch post details (top 20)
    PDB-->>FS: Post objects

    FS-->>Bob: Ranked feed (20 posts + pagination cursor)

Feed Pagination

Cursor-based pagination (not offset-based):

First load:  GET /feed
Response:    { posts: [...20 posts], next_cursor: "post_id_XYZ" }

Next page:   GET /feed?cursor=post_id_XYZ
Response:    { posts: [...20 more posts], next_cursor: "post_id_ABC" }

Why cursor over offset? With offset pagination, new posts inserted at the top shift all positions — users see duplicate or skipped posts. Cursor-based pagination is stable across writes.


Step 9 — Database Design

Database Selection

Data Database Reason
Users & authentication PostgreSQL Structured, ACID, strong consistency
Social graph Cassandra / TAO Wide rows — billions of edges; fast range reads
Posts & media metadata Cassandra Write-heavy, time-ordered, append-only
Feed timeline (raw) Cassandra Wide rows per user — time-ordered post IDs
Feed cache (hot) Redis Sub-ms feed assembly for active users
Affinity scores Redis + offline store Pre-computed per (user, friend) pair — queried at ranking time
Reactions & comments Cassandra High write volume, time-ordered
Notifications Cassandra Append-only, high volume

Post Table (Cassandra)

Table: posts

Partition key:  author_id     BIGINT
Clustering key: post_id       BIGINT (Snowflake — time-ordered)

Columns:
  content_type   VARCHAR       (TEXT | PHOTO | VIDEO | LINK | SHARE)
  text_body      TEXT
  media_urls     LIST<TEXT>    (CDN URLs)
  link_url       TEXT
  privacy        VARCHAR       (PUBLIC | FRIENDS | CLOSE_FRIENDS | ONLY_ME)
  like_count     COUNTER
  comment_count  COUNTER
  share_count    COUNTER
  created_at     TIMESTAMP
  is_deleted     BOOLEAN

Feed Timeline Table (Cassandra)

Table: feed_timeline

Partition key:  user_id       BIGINT
Clustering key: score         FLOAT DESC    (pre-computed raw score)
                post_id       BIGINT        (time-ordered tiebreaker)

Columns:
  author_id     BIGINT
  inserted_at   TIMESTAMP

Query pattern: SELECT post_id FROM feed_timeline WHERE user_id = ? LIMIT 1000

Wide rows — one partition per user, containing up to 1,000 post IDs ordered by raw score descending.

Reaction Table (Cassandra)

Table: reactions

Partition key:  post_id       BIGINT
Clustering key: user_id       BIGINT
                reacted_at    TIMESTAMP

Columns:
  reaction_type  VARCHAR  (LIKE | LOVE | HAHA | WOW | SAD | ANGRY)

PRIMARY KEY (post_id, user_id)

Unique per (post_id, user_id) — idempotent upsert prevents double reactions.


Step 10 — Caching Strategy

Redis Cache Design

Cache Key Pattern TTL Contents
Feed cache feed:{user_id} 24 hrs Sorted set — score → post_id (top 1,000)
Post details post:{post_id} 7 days Full post object
User profile user:{user_id} 1 hr Profile + counts
Affinity score affinity:{user_a}:{user_b} 6 hrs Pre-computed relationship strength (0.0 – 1.0)
Reaction count reactions:{post_id} Eventual Counter per reaction type
Celebrity recent posts celeb_posts:{user_id} 5 min Last 50 post IDs — for pull-based fan-out merge
Trending posts trending:{region} 10 min Top 100 post IDs by engagement in last 1h

Hot Post Problem

A viral post receives millions of reactions per minute. A single Cassandra row becomes a hotspot.

Solution:

  1. All reaction increments hit Redis counters only (INCR reactions:{post_id}:LIKE)
  2. Async worker flushes counters to Cassandra in 30-second batches
  3. Post read always goes to Redis first — no DB read under hot conditions

Cold Start Problem

A new user has no feed history and no social graph data.

Solution:

  1. On first feed load, trigger a full pull-based feed assembly from scratch
  2. Show suggested content (trending, popular in region) while personalized feed builds
  3. After the user makes 5+ interactions, affinity scores bootstrap and personalized feed takes over

Step 11 — Scaling

Read Scaling

flowchart TD
    LB[Load Balancer] --> F1[Feed Service Pod]
    LB --> F2[Feed Service Pod]
    LB --> F3[Feed Service Pod]
    F1 & F2 & F3 --> RC[(Redis Cluster\nFeed + Affinity Cache)]
    RC -->|miss| CS[(Cassandra\nFeed Timeline)]
    CS -->|batch fetch| PDB[(Post Store\nCassandra)]
  • Feed Service is stateless — horizontally scalable
  • Redis Cluster shards feed keys across nodes — 347K reads/sec is handled by multiple Redis nodes
  • Cassandra read replicas absorb cache misses

Fan-out Scaling

flowchart LR
    KF[Kafka\npost.created\n100+ partitions] --> FO1[Fan-out Worker]
    KF --> FO2[Fan-out Worker]
    KF --> FO3[Fan-out Worker]
    FO1 & FO2 & FO3 -->|batch writes| RC[(Redis\nFeed Caches)]
    FO1 & FO2 & FO3 -->|async| CS[(Cassandra)]
  • Kafka partitioned by author_id — all fan-out for one author goes to one partition (ordering)
  • Fan-out workers process follower lists in parallel batches of 1,000
  • Redis pipeline writes — batch 1,000 ZADD operations in one round trip

Ranking Service Scaling

2B users × 347K feed reads/sec
Each feed rank takes 80ms of compute

Required: 347K × 80ms = 27,760 core-seconds/sec
= ~28,000 CPU cores for ranking alone

Solution:

  • Pre-compute and cache affinity scores offline (batch jobs every 6 hours)
  • Lightweight online ranking uses pre-computed scores — avoids real-time graph traversal
  • Ranking service is stateless and horizontally scalable

Database Sharding

Database Shard Key Strategy
Post store author_id Consistent hashing — all posts by one author co-located
Feed store user_id Consistent hashing — one user's feed in one shard
Social graph user_id Consistent hashing — all edges for one user together
Reactions post_id Consistent hashing — all reactions per post co-located

Step 12 — Multi-Region Deployment

Facebook operates in every continent. A user in Singapore must not wait for a round trip to a US data center on every feed load.

flowchart TD
    Users --> GLB[Global Load Balancer\nAnyCast DNS]
    GLB -->|APAC users| APAC[APAC Region\nFull Stack]
    GLB -->|EU users| EU[EU Region\nFull Stack]
    GLB -->|US users| US[US Region\nPrimary]

    US -->|async replication| APAC
    US -->|async replication| EU
Strategy Detail
Read local Feed reads served from local region replica — sub-50ms
Write primary Post writes go to primary region first, then replicate async
Eventual consistency A post created in APAC may take 5–10 seconds to appear in EU feeds
Conflict resolution Last-write-wins for post edits; reaction counts eventually converge

Step 13 — Failure Scenarios

Failure Impact Mitigation
Redis (feed cache) down Feed reads fall back to Cassandra Redis Sentinel / Cluster failover; Cassandra is always the source of truth
Kafka down Fan-out and notifications stall Producers buffer locally; Kafka 3-broker cluster with replication
Fan-out workers down New posts don't fan out Kafka retains events; workers catch up after restart
Ranking service down Feed served unranked (reverse-chrono fallback) Graceful degradation — skip ranking, return time-ordered feed
Cassandra node down Partial data unavailable Replication factor 3; coordinator routes to healthy replicas
Hot shard (viral post) Single Redis key overwhelmed Redis counters → async DB flush; local in-process counters on service pods
Social graph service down Fan-out cannot resolve followers Cached follower lists in Redis; stale by minutes — acceptable
Cross-region replication lag Feed shows stale data in remote region Acceptable (eventual consistency); show "X minutes ago" timestamp to manage expectation

Final Architecture

flowchart TD
    Mobile[Mobile / Web Clients] --> GLB[Global Load Balancer]
    GLB --> AG[API Gateway\nAuth + Rate Limiting]

    AG --> POS[Post Service]
    AG --> FES[Feed Service]
    AG --> USS[User & Graph Service]
    AG --> RES[Reaction Service]

    POS --> KF[Kafka Cluster\nauthor_id partitioned]
    KF --> FO[Fan-out Workers × N]
    KF --> NW[Notification Workers]

    FO --> RC[(Redis Cluster\nFeed Cache)]
    FO --> FDB[(Cassandra\nFeed Timeline)]

    FES --> RC
    RC -->|miss| FDB
    FES --> RANK[Ranking Service\nML Scorer]
    RANK --> AFF[(Redis\nAffinity Scores)]
    FES --> PDB[(Cassandra\nPost Store)]

    USS --> SG[(TAO / Cassandra\nSocial Graph)]
    RES --> PDB

    NW --> FCM[FCM / APNs]
    NW --> NDB[(Cassandra\nNotifications)]

    PDB --> CDN[CDN\nMedia Delivery]

Technology Stack

Layer Technology
API Gateway Custom proxy / NGINX / Envoy
Post + Feed services C++ / Python / Go (Facebook uses Hack/C++)
Message queue Apache Kafka
Feed + affinity cache Redis Cluster
Social graph TAO (Facebook-custom) / Cassandra
Posts, feed, reactions Apache Cassandra
User data MySQL / PostgreSQL
Ranking / ML PyTorch models served via Triton inference server
Object storage Facebook's own Haystack + f4 / Amazon S3
CDN Facebook CDN / Cloudflare
Monitoring Scuba + ODS (Facebook internal) / Prometheus+Grafana
Deployment Multi-region data centers (own infrastructure)

Key Trade-Offs

Decision Option A Option B Choice & Reason
Feed ordering Reverse-chronological ML-ranked by relevance ML-ranked — higher engagement; but adds ranking latency budget
Fan-out strategy Push (write) only Pull (read) only Hybrid — push for regular users, pull for celebrities
Fan-out timing Synchronous (block post ACK) Async via Kafka Async — user gets ACK in < 500ms; fan-out happens after
Feed ranking Real-time scoring Pre-computed + cached scores Hybrid — cache affinity scores; light online ranking at read time
Consistency (feed) Strong — user sees post immediately Eventual — up to 10s delay Eventual — acceptable UX; enables async fan-out
Reaction counts Exact DB counts Redis counter + async flush Redis counter — hot posts would lock DB rows under exact counting
Social graph storage Relational DB (MySQL) Distributed graph store (TAO) TAO/Cassandra — billions of edges cannot be joined in SQL at runtime
Pagination Offset-based Cursor-based Cursor-based — stable under concurrent inserts; no duplicate/skipped posts

Facebook News Feed vs Instagram Feed

Dimension Facebook News Feed Instagram Feed
Ordering ML-ranked by relevance ML-ranked (also not chronological)
Content types Text, photo, video, link, share, events Photo and video only
Social model Friends (bidirectional) + Pages + Groups Follow (unidirectional)
Fan-out threshold ~100K followers ~1M followers
Graph complexity High — groups, pages, events, friends Lower — follow graph only
Ranking signals Many — relationship depth, content type Fewer — engagement + recency

Common Interview Mistakes

  • ❌ Designing a purely chronological feed — Facebook's feed is ranked
  • ❌ Not explaining the fan-out problem and the celebrity/page edge case
  • ❌ Doing fan-out synchronously — blocks post creation under load
  • ❌ Using SQL joins to traverse the social graph at read time — too slow at billions of edges
  • ❌ No caching layer — 347K feed reads/sec cannot hit Cassandra directly
  • ❌ Storing reaction counts as row-level DB increments — hotspot problem under viral posts
  • ❌ Offset-based pagination — skips/duplicates posts when new content is inserted
  • ❌ No ranking service — forgetting that Facebook's feed is not time-ordered
  • ❌ No multi-region discussion — Facebook is a global product

Interview Questions

  1. How is Facebook's news feed different from a simple reverse-chronological timeline?
  2. What is EdgeRank and how does it influence feed ranking?
  3. What is the fan-out problem? How do you solve it for users with 500M followers?
  4. Why is fan-out done asynchronously via Kafka rather than synchronously?
  5. How does the hybrid fan-out model work in practice?
  6. How do you rank 1,000 candidate posts in under 80ms?
  7. What affinity signals are used to compute relationship strength?
  8. Why is the social graph stored in a distributed store instead of MySQL?
  9. How do you handle hot posts receiving millions of reactions per minute?
  10. Why is cursor-based pagination better than offset pagination for feeds?
  11. How do you serve the feed for a new user with no social graph (cold start)?
  12. What happens when the Redis feed cache goes down?
  13. How does multi-region replication work for the feed?
  14. How does the feed store in Cassandra support efficient pagination?
  15. What is the ranking pipeline — how many stages and what does each stage do?

Summary

Concern Solution
Feed assembly Hybrid fan-out — push for regular users, pull for celebrities
Feed ranking Multi-stage ML pipeline: rule filter → lightweight ML → deep neural net
Ranking signals Affinity score, content weight, engagement signals, recency, time decay
Social graph Cassandra / TAO — wide rows, billions of edges, sub-ms reads from cache
Post storage Cassandra — partitioned by author_id, clustered by post_id (time)
Feed cache Redis Sorted Set per user — top 1,000 post IDs with raw scores
Reaction counts Redis counters — async flush to Cassandra every 30 seconds
Fan-out timing Async via Kafka — post ACK returned before fan-out completes
Pagination Cursor-based — stable under concurrent writes
Scale Stateless services + Kafka + Redis + Cassandra sharded by key
Multi-region Read local, write primary, async replication, eventual consistency

The core principle: Facebook News Feed is a ranking problem, not just a storage problem. Fast assembly of candidates (fan-out + cache) plus low-latency relevance scoring is what makes it work at 2 billion daily users.