Social Media Backend (Feed, Comments, Likes)
Part of the Backend Developer Roadmap
In short
Feeds, likes and comments look simple on screen. Behind them sit some of the most interesting backend trade-offs: precompute or compute on demand, exact counts or fast counts.
A backend for a social app — posts, a feed, comments, likes and follows — practice for modeling highly connected data and building an efficient feed-generation strategy.

Think of it like this
The morning newspaper round
The hawker drops a paper at every subscriber's door before they wake up, so reading is instant. The alternative is everyone walking to the stall and picking up papers themselves. Feeds face the same choice.
Watch it happen
Building the home feed
Fan-out on write
- New post copied into followers' feeds
- Reading the feed is very fast
- Celebrities with crores of followers hurt
Fan-out on read
- Feed built when the user opens it
- Posting is cheap
- Reading is slower for users following many
Many real systems mix both: push posts from normal users, and pull posts from very popular accounts at read time.
The big ideas
What you need to know
Follows and posts
Users, follows, posts, comments and likes tables, with indexes on who follows whom and on posts by author and time.
Feed generation
Start with fan-out on read using a simple query. Add precomputed feeds in Redis once reads get heavy.
Likes that can't double
A primary key on (user_id, post_id) makes a double tap harmless. Keep a cached like_count for display.
Cursor pagination
Infinite scroll uses "posts older than this one", not OFFSET, so page 50 is as fast as page 1.
See it in code
Walk through the code
1CREATE TABLE likes (2 user_id BIGINT NOT NULL REFERENCES users(id),3 post_id BIGINT NOT NULL REFERENCES posts(id),4 created_at TIMESTAMPTZ NOT NULL DEFAULT now(),5 PRIMARY KEY (user_id, post_id) -- one like per user per post6);7 8-- Liking twice (double tap, retry) is harmless9INSERT INTO likes (user_id, post_id) VALUES (7, 42)10ON CONFLICT DO NOTHING;11 12-- Cursor pagination for the feed: no OFFSET, stays fast deep down13SELECT id, author_id, body, created_at FROM posts14WHERE author_id = ANY($1) AND created_at < $215ORDER BY created_at DESC16LIMIT 20;1/3The composite primary key allows only one like per user per post.
$1 is the list of followed user IDs and $2 is the created_at of the last post on screen. Add id as a tie-breaker in real code.
Save yourself the pain
Common mistakes
Oops
Running SELECT COUNT(*) FROM likes for every post in the feed.
Do this instead
Keep a like_count column or Redis counter, updated when likes change, and recount occasionally to fix drift.
Oops
Using OFFSET 2000 for infinite scroll.
Do this instead
The database still reads and throws away 2,000 rows. Use a cursor on created_at and id.
Your mission
Milestone 1: a working feed
Quick check
A celebrity with 5 crore followers posts. Why is pure fan-out on write a problem here?
Go deeper
- 1Design a feed-generation strategy (fan-out on write vs fan-out on read) and justify your choice.
- 2Implement likes and comments with correct concurrent-update handling — no lost updates.
- 3Add pagination to the feed that performs well even as the dataset grows large.
More projects at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.