Facebook News Feed is the central stream of posts, photos, videos, updates, and recommendations that users see when they open Facebook. It ranks content from friends, groups, pages, and advertisers based on relevance, engagement, and personalization signals.
Product Requirements
Functional Requirements
- Users should be able to create posts
- Users should be able to build their social graph by adding friends or following other users.
- Users should be able to see a timeline/feed containing posts from the people they follow.
- The feed should be ordered in reverse chronological order, with the newest posts shown first.
- Users should be able to paginate through the feed to load older posts.
Non-Functional Requirements
- The system should prioritize availability over strong consistency; eventual consistency is acceptable.
- The system should serve feeds with low latency, targeting under 500 ms response time.
- The system should support massive scale and high throughput, handling approximately 2B daily active users.
- The system should allow users to follow an unlimited number of accounts and also support users with an unlimited number of followers.
Product Design Setup
Data Model
- User represents the one who use this system.
- Follow represents a one-way relationship where one user chooses to receive another user’s posts in their feed.
- Post represents a piece of content published by a user. When a user creates a post, it becomes eligible to appear in the feeds of users who follow that author.
API Design
The API will be the main entry point for clients, so we should define it early. The endpoints should map directly to the core product requirements: creating posts, following users, and reading the feed.
Firstly, users need a way to publish new posts, so we need a POST endpoint
POST /posts { "content": {} }
Secondly, users need to follow other users so their posts can appear in the follower’s feed. PUT /users/{userId}/follow. In this endpoint, the authenticated user is the follower, and userId represents the user being followed.
Using PUT makes the operation idempotent. If the user clicks the follow button multiple times, the final state is still the same: the relationship exists. If we later need to support unfollowing, that can be modeled with: DELETE /users/{userId}/follow
Finally, users need to page through their feeds GET /feed?pageSize={size}&cursor={cursor}
Response:
200 OK { "items": [ // Post objects ], "nextCursor": "..." }
The feed should return posts from followed users in reverse chronological order. Since pagination moves from newer posts to older posts, the cursor can represent the timestamp, or timestamp plus postId, of the oldest item returned in the previous page. For example, the first request returns the newest N posts. The next request uses nextCursor to fetch the next N posts older than that point.