Skip to content

FRONTEND SYSTEM DESIGN

Design a Social-media feed

Design an infinite, ranked feed with real-time updates, optimistic interactions, and smooth scroll performance.

Social-media feed architecture diagram

THE INTERVIEW SEQUENCE

How to drive this discussion

01

Clarify scope

02

Set requirements

03

Draw data flow

04

Defend trade-offs

Start with the smallest coherent design. After the main path works, introduce failure, scale, accessibility, observability, and release strategy one constraint at a time.

01Concrete scale assumptions

Cursor-paginated ranked feed with millions of users and bursty read traffic.

First page targets fast server delivery; later pages load progressively.

Likes and follows are optimistic but must reconcile authorization and rate limits.

Real-time insertions must not move content while the user is reading older items.

02Architecture decisions and rationale

Cursor pagination

Opaque ranking cursors survive insertions better than numeric pages and let the server evolve ranking internals.

Normalized entity cache

Feed entries reference post ids so one like update changes every visible occurrence consistently.

Controlled real-time buffer

Incoming items collect behind a New posts affordance instead of being inserted above and shifting the viewport.

Window long sessions

Virtualization limits DOM size while scroll restoration anchors to stable post ids.

03Client contracts and data boundaries

Feed page and optimistic action

Cursor and mutation ids define deduplication and reconciliation boundaries.

TypeScript
type FeedPage = { entries: { postId: string; rankToken: string }[]; nextCursor: string | null };type ReactionCommand = { mutationId: string; postId: string;  reaction: 'like' | 'none'; baseVersion: number; };

04Failure-mode analysis

Duplicate post across pages

Impact: The feed repeats content and keys collide.

Mitigation: Deduplicate by stable post id while advancing the cursor independently.

Optimistic reaction rejected

Impact: Count and viewer state diverge.

Mitigation: Reconcile the canonical version and announce a recoverable error without duplicating actions.

Media shifts after load

Impact: Reading position jumps.

Mitigation: Reserve aspect ratio and dimensions and avoid inserting live posts automatically.

Ranking cursor expires

Impact: Next-page request cannot continue.

Mitigation: Offer refresh from a new first page while preserving the current reading context until the user accepts.

05Observability and operations

  • Measure first-page latency, next-page failures, duplicate rate, scroll jank, media errors, optimistic rollback, and new-post buffer depth.
  • Trace page cursor hashes and request ids without logging private ranking features.
  • Measure long tasks and rendered node count during long sessions.
  • Experiment with ranking presentation behind cohort flags and guard user-control regressions.

06Security and accessibility boundaries

  • Authorize every reaction and content visibility server-side; never rely on hidden controls.
  • Sanitize user text and restrict media/URL rendering.
  • Use semantic articles and headings, meaningful media alternatives, labelled actions, and non-color reaction state.
  • Provide Load more and New posts controls with announcements instead of scroll-only discovery.

ANSOne full answer, start to finish

Drive the discussion yourself first. This is one strong answer delivered the way you would say it in the room — a model, not the only correct design.

A feed answer is really three sub-problems: getting pages of ranked content, keeping scrolling smooth no matter how far someone goes, and handling likes and new posts without the screen jumping around. Address them in that order and be explicit that the ranking itself is the server's job, not the client's.

  1. Step 1 · Clarify

    Ask: 'Is the feed ranked by an algorithm or chronological? How often do new posts arrive at the top? Roughly how long is a typical scrolling session? And what interactions — just likes, or comments and shares too?' Assumptions: 'Algorithmically ranked, new posts arrive frequently, sessions can be very long, and interactions are like, comment, and share.' Long sessions push you toward virtualization; frequent new posts push you toward a 'new posts' banner instead of auto-insert.

  2. Step 2 · Requirements

    User-facing: an endless feed that loads more as you scroll, instant feedback when you like something, and a non-disruptive way to see new posts. Hidden: the client must not re-rank or dedupe incorrectly, the DOM must stay bounded however far you scroll, and a like shown in one place must update everywhere that post appears.

  3. Step 3 · Paging with a cursor

    'The initial load fetches the first page of ranked posts plus a cursor. Scrolling near the end fetches the next page using that cursor. I use a cursor, not a page number, because the ranked list shifts as new content is inserted — an offset page would show duplicates or gaps. Pages are merged into the store by post id so a post returned on two pages is not rendered twice.'

  4. Step 4 · A normalized store keyed by post id

    'Posts are stored once, by id. A component rendering the feed, and a notification that says someone liked your post, both point at the same record. So when a like count changes in one place it is correct everywhere, because there is only one copy of the truth.'

  5. Step 5 · Virtualized rendering

    'Only the posts near the viewport are actually in the DOM; as you scroll, rows enter and leave. This keeps the node count flat whether you have scrolled past 20 posts or 2,000. It has to preserve stable keys, keep focus working, and anchor the scroll position so nothing jumps.'

  6. Step 6 · Optimistic likes and the 'new posts' banner

    'A like updates the local count and the liked state immediately, sends the request, and reconciles — or rolls back with a message — on the response. For new content, a lightweight poll or push checks whether there are posts newer than the current top, and if so shows a New posts button. I do not silently prepend them, because that shoves the content you are reading down the screen.'

  7. Step 7 · What loads first, and what to measure

    'Per post: text and the primary media's dimensions or a preview first, so nothing shifts; comments, adjacent media, and analytics follow. After launch I would watch page-fetch latency, duplicate rate, rollback rate on optimistic actions, layout shift from media, and interaction delay, alongside the engagement numbers.'

How to close

'So: ranked feed, long sessions, frequent new posts. Cursor pagination merged into a normalized post store keyed by id, so shared posts are deduped and a like updates everywhere. Virtualized rendering keeps the DOM bounded at any scroll depth. Likes are optimistic with rollback; new posts surface through a user-controlled banner, never auto-inserted. First metric after launch: duplicate-post rate and layout shift, because those are the two things that quietly ruin a feed.'

QAInterview questions and model answers

A server ranking cursor is stable across insertions and hides ranking internals better than offset pages that shift under new content.

Primary references

DESIGN CHECKLIST

Build your answer from first principles

Use this checklist to rehearse the case without reading the worked answer above.

CLARIFYING QUESTIONS

Do not design yet. Use these questions to make hidden assumptions explicit and prevent solving the wrong problem.

  1. 01

    Chronological feed or ranked/personalized?

  2. 02

    How real-time do new posts/likes need to feel — instant, or a periodic refresh is acceptable?

  3. 03

    What's the expected scroll depth and session length (affects virtualization priority)?

  4. 04

    Are media-heavy posts (video, multiple images) in scope?

FUNCTIONAL REQUIREMENTS

These are the user-visible capabilities the design must support. They define the first version's scope.

  1. 01

    Infinite scroll through a feed of posts, paginated from the server.

  2. 02

    Like/comment/share with instant visual feedback (optimistic UI).

  3. 03

    Surface new posts published since the feed loaded, without disrupting the user's current scroll position.

  4. 04

    Render media (images/video) without blocking text content from appearing first.

NON-FUNCTIONAL REQUIREMENTS

These qualities shape the architecture even though users do not click them directly: latency, resilience, accessibility, consistency, and scale.

  1. 01

    Smooth scroll performance even with thousands of posts loaded in a long session.

  2. 02

    Interactions (like/comment) must feel instantaneous regardless of network latency.

  3. 03

    Feed must recover gracefully from a failed page fetch without losing already-loaded content.

ARCHITECTURE

Now assign responsibilities to clear boundaries. Each part should have one reason to change and an explicit contract with the next part.

  1. 01

    A virtualized list rendering only posts near the viewport, so DOM node count stays bounded regardless of scroll depth.

  2. 02

    A normalized client-side store keyed by post id, so a like/comment count update in one place (e.g. a notification) reflects everywhere that post is rendered.

  3. 03

    An optimistic-update layer for interactions: apply locally immediately, reconcile with the server response, and roll back with feedback on failure.

  4. 04

    A 'new posts' banner fed by a lightweight poll or push channel, rather than silently prepending content and disrupting scroll position.

DATA FLOW

Trace one important user action from input to rendered result. This exposes ownership, race conditions, retries, and stale-data paths.

  1. 01

    Initial load fetches the first page of ranked/chronological posts; scrolling near the end triggers the next page fetch, appended to the normalized store.

  2. 02

    A like tap updates the post's local like count and 'liked' state immediately, fires the request, and reconciles (or reverts) based on the response.

  3. 03

    A background channel checks for newer posts than the feed's current top; when found, it surfaces a non-intrusive 'New posts' affordance instead of auto-inserting them.

TRADE-OFFS

There is no perfect architecture. State what each choice optimizes, what it costs, and the signal that would make you revisit it.

  1. 01

    Virtualization is close to mandatory for scroll performance at scale, but it complicates maintaining scroll position across data changes (e.g. a new post appearing above).

  2. 02

    Optimistic interactions maximize perceived responsiveness but require a well-designed rollback/error path so failures don't feel like silent data loss.

  3. 03

    Auto-inserting new posts keeps the feed 'live' but risks disorienting a user mid-read; a manual 'show N new posts' control trades a bit of liveness for predictability.

SCALING

Scale the measured bottleneck rather than every box. Frontend scaling includes payload size, main-thread time, rendering work, cacheability, and release safety.

  1. 01

    Rank/personalize feed content server-side (or in an edge layer) so the client only ever deals with an already-ordered page of posts.

  2. 02

    Cache media aggressively and serve responsively sized variants so image-heavy posts don't dominate bandwidth and jank scroll.

  3. 03

    Bound the client-side normalized store's size (evict posts far outside the current scroll window) for very long sessions.

COMMON PITFALLS

Interviewers often probe these failure modes. Name them before being prompted and explain the guardrail you would add.

  1. 01

    Rendering every post's full DOM tree without virtualization, causing scroll jank that gets worse the longer the session runs.

  2. 02

    Storing the same post's data in multiple disconnected places, so a like updates one copy but not the others rendered elsewhere.

  3. 03

    Auto-scrolling or auto-prepending new content, which yanks the viewport and disorients a user mid-scroll.

Your closing summary

Restate the critical user flow, the most important quality target, the architecture boundary that protects it, and the trade-off you accepted. Then name the first metric you would watch after launch.

Back to all cases →