Feed concept
The activity feed displays posts from users that the authenticated user follows. Posts are ordered by creation time (most recent first) and paginated using cursor-based pagination.How it works
- Query retrieves all users the requesting user follows
- Fetch posts created by those followed users
- Order posts by creation time and post ID (descending)
- Return paginated results with cursor for next page
Feed query
Retrieve the activity feed for a user.Cursor-based pagination
The feed uses cursor (keyset) pagination instead of offset pagination for better performance and consistency.Why cursor pagination?
- Stable performance at scale: Avoids scanning/skipping rows like OFFSET does
- Consistency under writes: New posts don’t cause duplicates or missing items during pagination
- Predictable query cost: Each page query has similar performance regardless of depth
Request parameters
cursor(string, optional) - Encoded cursor from previous response. Omit for first page.limit(int, optional) - Number of posts per page. Defaults to 20.
Response structure
Posts(array) - Array of post objects with full detailsCursor(string, nullable) - Encoded cursor for next page, ornullif no more postsHasMore(boolean) - Whether more posts are available
Cursor workflow
Fetching the first page
To get the first page, make a request without a cursor parameter:- First 10 posts
- A
Cursorvalue (if more posts exist) HasMore: true(if more posts exist)
Fetching the next page
Use theCursor value from the previous response:
CreatedAt- Timestamp of the last post from previous pagePostID- ID of the last post from previous page
Cursor format
Cursors are Base64 URL-safe encoded JSON:eyJkYXRlVGltZSI6IjIwMjYtMDMtMDRUMTg6MzA6MDBaIiwibGFzdElkIjoxMjM0NX0=
Query logic
The feed query uses this WHERE clause for pagination:limit + 1 posts to determine if more pages exist, then removes the extra post before returning.
Full pagination example
Step 1: Request first page
Step 2: Request next page with cursor
At scale, consider implementing a fan-out strategy where posts are pre-populated into each user’s
FeedContent table when followed users create posts. This trades write complexity for faster read performance.Feed generation strategy
The current implementation uses a pull model where the feed is generated on-demand by querying posts from followed users.Current approach (Pull model)
- Feed is assembled at query time
- Queries all followed users’ posts
- Filters and sorts in the database
- Simple to implement, no background processing needed
Alternative approach (Fan-out model)
For higher scale, consider using theFeedContent table:
- When a user creates a post, insert a
FeedContentrecord for each follower - Feed queries simply read from
FeedContent(already filtered and sorted) - Trades write amplification for faster reads
- Better for users with many followers and active feeds