Stop 22 · Build Backend Portfolio ProjectsProjects · 14/14

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.

The purple blob rides a bicycle and tosses rolled newspapers to doorsteps.

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

sql
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

~45 min

Quick check

A celebrity with 5 crore followers posts. Why is pure fan-out on write a problem here?

Go deeper

  1. 1Design a feed-generation strategy (fan-out on write vs fan-out on read) and justify your choice.
  2. 2Implement likes and comments with correct concurrent-update handling — no lost updates.
  3. 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.

Download
InsideEdge