Back to Case Studies

Facebook/Twitter-like Feed System Design

Overview-

A scalable, eventually consistent social feed service supporting post creation, following, and chronological timeline viewing for up to 2 billion users.

Functional Requirements–

  1. Users should be able to create posts.

  2. Users should be able to follow other users.

  3. Users should be able to view a feed of posts (from other people they follow, in chronological order).

  4. Users should be able to page/scroll through their feed.


Non-Functional Requirements–

  1. The system should be highly available. (It should be eventual consistency, and we can tolerate a ½-minute delay). (Availability).

  2. Posting and viewing feed should be fast within < 500 ms. (Latency).

  3. The system should be able to scale to 2B users. (Scaleability).

  4. Users should be able to follow an unlimited number of people. (Scaleability).


Core Entities—

  1. User.

  2. Follow.

  3. Post.


API:

  1. POST/posts{"content":{""}} 201 {“postId”://}

  2. PUT/users/{id}/followers{“userId”:”userId”} 200

  3. GET/feed?pageSize={size}&cursor={timestamp}


Capacity Estimation–

Assuming 2 billion total users and 10% DAU (200 million):

  • Posts: 3–5 per DAU/day → 600M–1B posts/day (~7–12K write QPS peak)

  • Feed views: 150–250 sessions/DAU/day → 30–50B reads/day (~350–580K read QPS peak)

  • Read:write ratio: 40–80:1

  • Peak QPS: ~500–800K (mostly reads), with potential 3–5x spikes

  • Latency goal: <500 ms p99 for posts and feed loads

  • Storage (text posts, 1-year retention): ~150–400 TB (200–400 bytes/post + ×3 replication) High availability with eventual consistency (tolerate up to ~30s delay for new posts in feeds).


Cache Capacity Estimation–

Using push-on-write model with per-user timelines in Redis sorted sets (post IDs + timestamps):

  • Stored per user: recent 500–800 posts (covers initial 5–10 scroll pages)

  • Size/entry: ~40–60 bytes

  • Per-user footprint: ~25–50 KB

  • Total for 200M DAU: ~5–10 TB raw

  • With ×3 replication, overhead, headroom: 15–30 TB RAM across Redis cluster

  • Optimizations:

    • Warm cache only for active users (last 30 days)

    • LRU eviction + TTL for stale data

    • Cache miss fallback: on-the-fly merge from Post DB + Follow indexes

    • Separate pull model for celebrity/high-follower accounts to prevent fan-out overload.


High Level Design (HLD)—


Trade-offs & Bottlenecks

  • Fan-out on Write (Push Model): Enables fast reads (<500 ms) via precomputed caches but risks write overload for celebrity users (e.g., 1M+ followers → massive queue backlog). Mitigated by hybrid approach (push for normal users, pull for high-follower accounts).

  • Eventual Consistency: Tolerates ~30s delay, which simplifies scaling and availability but may cause brief stale feeds (acceptable per NFR).

  • Hot Keys/Shards: Popular users or viral posts can overload specific DB shards or cache nodes. Solution: Sharding by user ID, consistent hashing, and separate handling for celebrities.

  • Read-Heavy Workload: ~40–80:1 read:write ratio means heavy caching and horizontal scaling of Feed Service + Redis cluster.

  • Storage Bottleneck: Text posts scale to hundreds of TB/year; media (images/videos) would require CDN + object storage (e.g., S3-like) and inflate costs significantly.

Future Improvements / Out of Scope

  • Personalized Ranking: Add ML-based layer (e.g., engagement prediction) to reorder chronological feed → “For You” style.

  • Real-time Updates: Integrate WebSocket / Pub-Sub (Kafka/Redis PubSub) for live push notifications instead of polling.

  • Media Support: Store images/videos in CDN, reference URLs in Post entity.

  • Search & Discovery: Add full-text search (Elasticsearch) for posts/hashtags.

  • Security/Privacy: Rate limiting, abuse detection, private accounts, block/mute features.

Database Choices (Suggested)

  • Posts: Cassandra / ScyllaDB (wide-column, high write throughput, time-series friendly) or MySQL sharded by post ID.

  • Follows: Graph DB (Neo4j) or relational table with indexes on follower/followee.

  • Feed Cache: Redis (sorted sets for timelines) clustered and sharded.

  • Queue: Kafka or RabbitMQ for async fan-out to handle spikes.


© 2026 Mehraj Hosen. All rights reserved.