System designby Learnastra

System-design interview · Core interviews

Design a microblogging service

By Anup Rai

Store each post once, build profiles and home timelines from its ID, and calculate the reads and follower-inbox writes each approach requires. Use resumable fanout for ordinary authors, merge popular authors on reads, and check current visibility before returning posts.

You will learn to

  • Trace one post into an author timeline and follower feeds.
  • Calculate write amplification and distinguish page requests from item impressions.
  • Choose partitioning, cache, and recovery rules that preserve visibility and deletion.

Practice in this chapter

8 interview questions with model answers and follow-ups.

Go to interview practice

Useful foundations: Data partitioning and sharding · Caching: cache hits, misses, write policies and invalidation · Message queues, event logs, delivery guarantees, and backpressure

Workload and timing examples are interview assumptions.

01Problem and scope

A microblogging service publishes short posts and combines eligible posts into home timelines. Store each post body and its media references once; author profiles and viewer inboxes are access paths containing references to that post. For example, post p701 appears in its author’s history and may become a candidate for many followers. The central design choice is how much timeline assembly to perform during publication versus on each read.

Include follows, likes, text, media, replies and reshares, with a chronological first version and a few seconds of feed propagation delay. Use an exercise limit of 500 characters with explicit Unicode validation; this is not a current claim about a named platform. Media upload completes separately before the post can reference it. Ranked feeds can later reorder a bounded eligible candidate set without changing publication or permission authority.

Core scope is posts, follows, likes, profiles, a paginated home feed, replies and reshares. Search, trends, mentions, notifications, recommendations and curated collections are explicit derived extensions. We will explain their data inputs and limits, not pretend one timeline algorithm implements them. The central interview problem is balancing repeated feed reads against writes to follower inboxes, then recovering unfinished fanout when some authors have far more followers than others.

Read amplification is the extra candidate retrieval and comparison needed to assemble one visible page. Write-time fanout moves some of that work earlier by copying a new post's reference into followers' inboxes. It reduces repeated reads but creates more writes, especially for authors with many followers.

02Functional requirements

  1. Publish: Post appears on the author's authoritative profile after accepted commit.
  2. Read the home feed: Eventually includes eligible posts, with no duplicate IDs within a page/session.
  3. Follow/unfollow: Durable relationship; new follow may backfill a bounded recent window.
  4. Like/unlike: One logical like per user/post; repeated action is harmless.
  5. Delete/restrict: Current visibility check prevents a stale candidate from granting access.
  6. Search/mention/trend: Derived results may lag and are independently permission-filtered.

Publication, media and related posts

The author creates an immutable post with request key post-71. A retry returns p701 rather than publishing a duplicate. Media IDs refer only to the author's already verified READY uploads. A reshare stores the original post ID and its own actor/time; it does not copy text that would remain visible after the original is removed. Replies retain a parent/root reference and have their own publication identity.

Freshness, visibility and scope limits

Feeds can be slightly old; deletion and privacy are different promises. A failed ranking service may fall back to recency, while failed authorization cannot fall back to “show everything.” A liker can remove their own like; counts may converge asynchronously and must not be treated as a ledger. A cursor defines page continuity when new posts arrive. We exclude arbitrary retroactive editing of post text and transactional changes to every follower inbox at once. Those exclusions keep publication atomic while allowing derived views to recover independently.

03Non-functional requirements

  1. Latency: Home-feed metadata p95 below 200 ms; post acceptance p95 below 300 ms.
  2. Availability: 99.9% eligible feed availability inside a region. Prefer a slightly older authorized feed to a fast unauthorized one.
  3. Freshness: Ordinary active followers should usually receive a new candidate within five seconds. An accepted post is immediately retrievable from its authoritative endpoint/profile path even if follower inboxes lag.
  4. Durability: Accepted posts survive one node or availability-zone failure through replicated authority.
  5. Regional recovery: Use a separately tested asynchronous recovery point and a one-hour recovery target. During write-authority loss, reject new posts or leave them pending.
  6. Retention: Keep posts for an illustrative five years, subject to deletion policy; media retention and replication cost are separate.
  7. Authorization and revocation: Check current post visibility and private membership before returning metadata. Media tokens last at most 60 seconds; already granted media delivery has that revocation bound, and downloaded content cannot be recalled.

Source and derived-view invariants

Invariant Consequence
One request identity, one post Publication retries do not duplicate the source record.
One post-body authority Feed copies are references, not independent truth.
Idempotent fanout A retry cannot duplicate an inbox identity.
Current eligibility Stale candidates never authorize deleted/private content; cached candidates remain usable only after the required current visibility checks.

Eventual consistency is appropriate for some derived feed work. It is not a blanket permission to treat freshness, deletion and private-media disclosure as equivalent forms of staleness.

04Capacity estimates

Workload assumptions and arithmetic

Use one billion registered users, 200 million daily users, 100 million posts/day and 200 follows per account. Each daily user opens two home pages and five profile pages, each displaying twenty posts. Therefore post writes are 100M / 86,400 = 1,157/s; page requests are 200M × 7 / 86,400 = 16,204/s; item impressions are 16,204 × 20 = 324,074/s. Roughly 324,000 item impressions/s is a different unit from the approximately 16,200 HTTP page requests/s that produce them.

Worked estimates

Quantity Worked calculation Implication
Fivefold peak pages 16,204 × 5 ≈ 81,019/s Budget candidate selection separately from loading post records
Text records 100M × 310 B = 31 GB/day About 56.6 TB over five years
New photo/video bytes 20M × 200 KB + 10M × 2 MB = 24 TB/day About 43.8 PB over five years before copies
Likes 200M × 5 = 1B/day 11,574 actions/s average; not a tiny side counter
Follow edges 1B × 200 × 16 B = 3.2 TB raw Both index directions and replication add space
Three days of distinct text 100M × 3 × 310 B = 93 GB More after cache overhead and copies

Capacity implications and limits

Retained storage measures bytes kept over time; egress measures bytes transferred to viewers. A content delivery network (CDN) caches media near viewers so repeated requests need fewer reads from the original media store. It changes which server supplies those bytes, not how many bytes viewers consume.

Assume impression mix matches publication mix: 20% include a 200 KB photo, 10% include a 2 MB video, and one-third of encountered videos play. At 28 billion impressions/day, photo egress is 28B × 0.20 × 200 KB / 86,400 ≈ 13 GB/s; video egress is 28B × 0.10 × (1/3) × 2 MB / 86,400 ≈ 21.6 GB/s. Using 280 displayed text bytes per impression gives about 91 MB/s; the 310-byte storage record includes additional metadata. Different viewing or media mixes require a new estimate. These are illustrative averages excluding protocol/variant changes. CDN hit rate reduces origin bytes, not the total sent to users. The largest ordinary feed cost may be candidate fanout, so measure follower distribution and active-reader reuse instead of trusting the average of 200 follows.

05APIs and contracts

Request and response example

The author sends POST /v1/posts with key post-71 and {"text":"The bridge is open","mediaIds":["media91"],"visibility":"public"}. Success returns 201 {"postId":"p701","createdAt":"..."} after durable commit. Reusing the key with changed text returns 409. The server derives author identity from authentication; it does not accept arbitrary owner IDs in the payload.

Interface contracts

API Contract
GET /v1/feed?cursor=<token>&limit=20 Viewer-scoped bounded snapshot/cursor and visible items
GET /v1/users/u17/posts?before=<time,id> Author/time range, current visibility filtered
PUT /v1/following/u17 / DELETE Idempotent relationship intent
PUT /v1/posts/p701/like / DELETE One user/post relationship; approximate count separate
POST /v1/posts with replyTo or reshareOf Validate referenced post visibility and store relationship
DELETE /v1/posts/p701 Owner tombstone plus derived cleanup event

Validation and response semantics

Cursor tokens include a cutoff/snapshot identity and deterministic time/ID tie-breaker, not a mutable numeric offset over a changing list. The next page avoids newly inserted earlier items shifting every row. Ranking changes require a bounded session snapshot or stable score/version contract. Return 413 for oversized media bodies at the upload API, 400 for text/media validation, 429 for action limits and 503 for unavailable authority. A timeout after submission is resolved using the original request key, not by silently creating another post.

A chronological cutoff with a stable last-seen sort key is keyset pagination, not an immutable snapshot of asynchronously arriving candidates. It prevents an existing item from shifting merely because newer posts arrive, but a late fanout entry older than the cutoff can be missed until refresh. If the product needs a repeatable browsing session, materialize a bounded list of candidate IDs at the first request, bind subsequent cursors to that list and viewer, and expire it explicitly (for example after five minutes). Current deletion and authorization filtering still runs on every page; the snapshot never freezes permission.

06Data model and access patterns

Store source records separately from the feed structures rebuilt from them. Post owns content; Follow and Like own user actions; Inbox holds possible feed entries. The outbox is a durable record of work committed with a post change, allowing downstream workers to recover that change even if the immediate queue send fails.

Record and fields Responsibility / constraint
Post(postId,authorId,createdAt,text,mediaIds,visibility,version,deletedAt,replyTo,reshareOf) Owns the body.
CreateRequest(authorId,key,payloadHash,postId) Owns retry identity.
Follow(followerId,authorId,version) Supports follower-to-author reads and reverse fanout pages.
Like(userId,postId) Unique user/post action.
Inbox(viewerId,postId,sortKey) Stores candidates.
Outbox(eventId,postId,type,version) Records durable publication/deletion intentions.

Use an author/time index (authorId,createdAt DESC,postId DESC) for profiles and celebrity merges. An ID containing time does not let the system find every post by the author without such an access path. Inbox keys support viewer/time range queries; the unique viewer/post identity prevents repeated fanout from creating duplicates. Like records are authoritative user actions, while counts are derived from idempotent change events. A delete may leave like rows temporarily, but a hidden post cannot be exposed merely because a like still exists.

Start with post/request/outbox transactions within the same storage partition, then route by author and logical time bucket when needed. Alternatively hash primary post IDs and maintain the author index explicitly; the choice is workload-dependent. Media objects have their own immutable storage identity and READY status. Search, trends, follow suggestions and curated collections are derived stores fed from committed events. Their availability cannot decide whether p701 exists or whether viewer A is allowed to see it.

The immediate author-profile guarantee requires the owning post partition to maintain its local author/time access path in the same accepted transaction. An asynchronously rebuilt global author index is only a derived candidate source. If primary records are instead hashed by post ID, either make the authoritative author index part of the commit protocol or explicitly add a recent-write overlay / weaken immediate profile visibility. The worked author-owned layout avoids that cross-partition write dependency.

07Basic working design

Publication and pull-on-read feed

One app and one SQL database can implement the core product. The author's transaction inserts p701 and its request result. The feed query reads the viewer’s followed authors, queries their recent posts, merges by (createdAt,postId) and returns twenty. This is fanout on read: the combination work happens when a viewer asks. It avoids writing unused feeds for people who never return.

Verified media and independent derived views

Keep media upload separate and require a verified media reference before publication. A text-only post stays a small transaction. Likes use a unique relationship rather than incrementing a counter blindly; repeats do not manufacture additional likes. Profiles are indexed range reads and can often be served more cheaply than a many-author feed. A reshare points to p701 and is filtered if the original becomes unavailable.

Commit boundary and baseline limits

The baseline acknowledgement is database commit. If the author's response is lost, post-71 returns p701. If viewer A's feed request fails, retrying is a read and need not mutate anything. Backups and restore tests cover post bodies and media pointers. At small traffic and follow counts this design is easier to operate than a fleet of fanout services. We add precomputation only after calculating repeated work and deciding which viewers benefit from it.

architecture · baselinePull followed-author posts on demand

Publication and feed reads are separate paths. Publication checks media readiness before commit; feed reads select eligible posts before reading their media. The SQL database owns posts and follows.

Pull followed-author posts on demandPublication and feed reads are separate paths. Publication checks media readiness before commit; feed reads select eligible posts before reading their media. The SQL database owns posts and follows. client to app: Publish 1. Submit post; app to media: Publish 2. Verify owned media is ready; app to db: Publish 3. Commit p701 + request result; app to client: Publish 4. Return committed post; client to app: Read 1. Request feed; app to db: Read 2. Query followed posts; check visibility; app to media: Read 3. Read permitted media bytes; app to client: Read 4. Return merged page and permitted mediaPublish 1. Submit postPublish 2. Verify owned mediais readyPublish 3. Commit p701 +request resultPublish 4. Return committedpostRead 1. Request feedRead 2. Query followed posts;check visibilityRead 3. Read permitted mediabytesRead 4. Return merged pageand permitted mediaACTORCreators and feedreadersSERVICEPost and feedapplicationSTORESQL posts, followsand likesSTOREVerified mediastoragesync
Read each connection in order
  1. syncPublish 1. Submit postCreators and feed readers → Post and feed application
  2. syncPublish 2. Verify owned media is readyPost and feed application → Verified media storage
  3. syncPublish 3. Commit p701 + request resultPost and feed application → SQL posts, follows and likes
  4. syncPublish 4. Return committed postPost and feed application → Creators and feed readers
  5. syncRead 1. Request feedCreators and feed readers → Post and feed application
  6. syncRead 2. Query followed posts; check visibilityPost and feed application → SQL posts, follows and likes
  7. syncRead 3. Read permitted media bytesPost and feed application → Verified media storage
  8. syncRead 4. Return merged page and permitted mediaPost and feed application → Creators and feed readers

08Find the baseline flaws

Bottleneck / counterexample Evidence and design consequence
Pull-on-read amplification If viewer A follows 200 authors and the baseline pulls twenty recent posts from each, it examines up to 4,000 candidates for a twenty-item page. The workload includes 400 million home-feed opens/day, about 4,630/s average; this policy could examine roughly 18.5 million candidates/s before fivefold peaks. Profiles contribute different work and should not be counted as identical many-author merges. Merely increasing cache memory does not remove all this repeated selection.
Celebrity fanout amplification A naive precomputed feed creates the opposite problem. The author has 300 ordinary followers, so writing references is cheap; a celebrity with fifty million followers creates fifty million writes for one post. At 50,000 inbox inserts/s reserved to that job, it takes 1,000 seconds—over sixteen minutes—far beyond five-second freshness. Average follower count hides this skew.
Lost fanout trigger and stale privacy A correctness failure appears when the post commits but the separate “start fanout” message is lost. p701 exists on the author's profile but never reaches inboxes. Another failure appears if a worker inserts viewer A then crashes before viewer B; acknowledging the whole job early loses remaining work. The evolution needs an outbox and resumable page checkpoints, while the read path must tolerate partial propagation. Global atomic publication across all follower inboxes would be far more expensive than the product's freshness promise requires.

09Improve the design, step by step

  1. Add replicated authority and a publication outbox. Accepted-post durability and lost fanout triggers motivate a transaction that saves post, request identity and outbox together. A relay publishes committed events and may repeat them. This survives process crashes and separates post acceptance from follower speed. It costs replication latency and event-consumer deduplication. Direct synchronous writes into every inbox are rejected because one slow follower partition would delay the author's post.

  2. Prepare inbox candidates for active ordinary followers. Repeated multi-author merges trigger fanout-on-write. Workers page through followers and insert p701 references. Reads become a bounded inbox range followed by loading the corresponding post records, often called hydration. Costs are write amplification, inbox storage and rebuild logic for dormant users. Pure pull remains better for infrequent readers, new follows and small graphs. Precomputation is a materialized view, meaning a stored answer that can be rebuilt from authoritative posts and relationships.

  3. Keep high-fanout authors on a pull path. The sixteen-minute celebrity calculation triggers hybrid assembly. Store their recent posts once in author lists and merge them into active viewers' inbox candidates at read time. This bounds publication work and avoids many never-read writes. It adds two candidate paths, deduplication and per-reader celebrity merge cost. A fixed threshold is only an initial policy; choose it from active follower reads and measured write/read cost.

  4. Separate media delivery and add partitioned derived services. The 24 TB/day ingress and large egress trigger private object storage with CDN delivery, while metadata caches and logical partitions distribute text/history. Search and trends consume events independently. Media delivery can then grow separately from post storage. The costs are permission checks at caches, delayed indexes, object-store operations and clear responsibility while partitions move. A single replicated SQL cluster remains a valid earlier step; a NoSQL label is not a performance proof.

At each stage, keep a recency fallback and bound per-request candidate work. Faster fanout is useful only if page assembly remains authorized and within its latency budget.

10Detailed architecture

Post request and source authority

The edge routes writes to a post API and reads to a feed/profile API. The post API validates ownership, media readiness and rate limits, then routes to the post's owning partition. The storage group replicates and commits the body, request result and outbox together. Follow and like services own their respective unique relationships and publish changes for derived counts, notifications and feed maintenance.

Durable fanout and derived indexes

The outbox relay feeds a durable event stream. Fanout workers read reverse-follow pages and update viewer inbox partitions; celebrity publication updates a shared author list instead. Index workers build shared author-list caches, title/text search, trend aggregates and notification tasks. The authoritative author/time index is committed with the post; profile reads route there when the derived list has not caught up. A checkpoint describes completed follower pages, not merely an event that was fetched into worker memory.

Current visibility and media delivery

Feed APIs merge ordinary inbox candidates with followed celebrity lists, remove duplicate IDs, load post records in batches and check current visibility and membership. Hot text/author lists can be cached, but the authoritative visibility boundary remains enforced before response. The media edge validates its short-lived grant before returning cached immutable bytes or fetching origin storage.

Routing epochs and replica policy

Logical partition maps are versioned. During migration, the new storage group copies the partition and replays subsequent changes. Storage then rejects writes from the old owner using an ownership version check before the new owner accepts writes. Replicas used for public body reads may lag under a chosen policy; replicas used for current deletion/permission decisions need the protocol's required freshness. This is why adding “read replicas” cannot automatically promise both immediate revocation and arbitrary availability during isolation.

architecture · finalHybrid candidate feeds over one post authority

Outbox events drive recoverable views. Current visibility is checked during hydration; ordinary and celebrity paths merge before media grants are issued.

Hybrid candidate feeds over one post authorityOutbox events drive recoverable views. Current visibility is checked during hydration; ordinary and celebrity paths merge before media grants are issued. client to edge: 1. Publish or request page; edge to postapi: 2a. Route authenticated actions; edge to feed: 2b. Route feed/profile reads; postapi to media: 3. Verify READY owned media; postapi to authority: 4. Commit post + request + outbox; authority to replicas: 5. Replicate accepted post; postapi to graph: 6. Unique follow or like change; authority to events: 7. Relay committed changes; graph to events: 8. Relationship change events; events to fanout: 9. Process resumable jobs; fanout to graph: 10. Page follower list; fanout to views: 11. Upsert candidates and indexes; feed to views: 12. Merge inbox and author lists; feed to cache: 13. Load cached immutable post fields; feed to authority: 14. Current visibility check; feed to graph: 15. Validate private membership; feed to client: 16. Page and media grants; client to cdn: 17. Authorized media request; cdn to media: 18. Miss: fetch immutable object1. Publish or request page2a. Route authenticatedactions2b. Route feed/profile reads3. Verify READY owned media4. Commit post + request +outbox5. Replicate accepted post6. Unique follow or like change7. Relay committed changes8. Relationship change events9. Process resumable jobs10. Page follower list11. Upsert candidates andindexes12. Merge inbox and authorlists13. Load cached immutablepost fields14. Current visibility check15. Validate privatemembership16. Page and media grants17. Authorized media request18. Miss: fetch immutableobjectACTORCreators and readersSERVICEEdge and actionlimitsG1SERVICEPost and relationshipAPIsG1SERVICEFeed and profile APIG1STOREPost partitions andvisibility authorityG2STOREAuthoritative replicasG2STOREFollow and likeauthorityG2QUEUEOutbox relay andevent streamG3WORKERFanout and indexworkersG3STOREInbox, author andextension indexesG3CACHEHot post and authorcacheG3STOREPrivate verifiedmedia storeG4CACHEAuthorized mediaedge / CDNG4syncreplicationasyncG1 Synchronous user pathsG2 Authoritative facts and durabilityG3 Recoverable candidate viewsG4 Media storage and delivery
Read each connection in order
  1. sync1. Publish or request pageCreators and readers → Edge and action limits
  2. sync2a. Route authenticated actionsEdge and action limits → Post and relationship APIs
  3. sync2b. Route feed/profile readsEdge and action limits → Feed and profile API
  4. sync3. Verify READY owned mediaPost and relationship APIs → Private verified media store
  5. sync4. Commit post + request + outboxPost and relationship APIs → Post partitions and visibility authority
  6. replication5. Replicate accepted postPost partitions and visibility authority → Authoritative replicas
  7. sync6. Unique follow or like changePost and relationship APIs → Follow and like authority
  8. async7. Relay committed changesPost partitions and visibility authority → Outbox relay and event stream
  9. async8. Relationship change eventsFollow and like authority → Outbox relay and event stream
  10. async9. Process resumable jobsOutbox relay and event stream → Fanout and index workers
  11. sync10. Page follower listFanout and index workers → Follow and like authority
  12. async11. Upsert candidates and indexesFanout and index workers → Inbox, author and extension indexes
  13. sync12. Merge inbox and author listsFeed and profile API → Inbox, author and extension indexes
  14. sync13. Load cached immutable post fieldsFeed and profile API → Hot post and author cache
  15. sync14. Current visibility checkFeed and profile API → Post partitions and visibility authority
  16. sync15. Validate private membershipFeed and profile API → Follow and like authority
  17. sync16. Page and media grantsFeed and profile API → Creators and readers
  18. sync17. Authorized media requestCreators and readers → Authorized media edge / CDN
  19. sync18. Miss: fetch immutable objectAuthorized media edge / CDN → Private verified media store

11Write path and acknowledgement

Publication commits one authoritative post and a recoverable fanout event. The example uses request post-71, post p701, event e701, and follower IDs viewerA and viewerB to demonstrate checkpoint ordering.

  1. The author authenticates and submits post-71 with media91. The API validates text length, permitted media ownership and READY media state.
  2. At the author's post owner, a transaction checks the request identity, assigns p701, inserts the post and outbox event e701, and records the result. Commit replication completes before returning accepted.
  3. The outbox relay publishes e701. If it crashes after publish but before recording progress, it publishes e701 again; consumers use its durable identity.
  4. A fanout job records p701, the chosen ordinary-author policy and a follower-page cursor. It retrieves a bounded page containing viewer A and viewer B, considering current active-user eligibility.
  5. It inserts (viewerA,p701) and (viewerB,p701) with a stable sort key using conditional uniqueness. A repeated insert observes the same candidate rather than adding another row.
  6. Only after all writes in the follower page complete does the job persist the next checkpoint. A failed page is repeated. A terminal checkpoint means all pages under the chosen scan policy were processed.
  7. Search, notifications and trend workers independently consume e701. Their failure does not roll back the accepted post. The author's profile can read the authority while follower and search views catch up.

Follower membership can change while pages are scanned. Define new-follow backfill separately and recheck follow/privacy rules on reads. Do not claim the fanout traversed a globally frozen social graph unless the implementation actually supplies such a snapshot.

12Read and delivery path

Home-feed reads merge bounded candidate sources and recheck current visibility. This example returns up to twenty items while retaining a stable continuation boundary.

Each candidate source is already ordered. A heap, used here as a priority queue, keeps the next available item from each source and selects the newest one; after selecting it, the merge adds that source's following item. This avoids sorting every source's entire history, while still requiring explicit limits on how many sources and candidates the request examines.

  1. Viewer A requests a twenty-item page under a viewer-scoped cursor. The API loads a bounded recent inbox range; a dormant or newly registered viewer may trigger a bounded rebuild from followed author histories.
  2. Read recent lists for viewer A's followed high-fanout authors and merge them with inbox candidates. A heap can merge sorted lists efficiently, but candidate and author limits still matter for a user following many celebrities.
  3. Deduplicate p701 if it arrives through more than one route or reshare policy. Reshares can retain their actor context while referencing one original body; the product defines whether both activities appear.
  4. Batch-load the candidate post records, check current deletion/visibility and private membership, and discard ineligible IDs. A stale search/inbox/cache reference cannot override this check.
  5. Apply recency ordering or a bounded ranker, return the first twenty and a stable continuation token. Reserve enough extra candidates to tolerate filtering without unbounded loops. A shorter page is preferable to exceeding the latency budget indefinitely.
  6. Return scoped media grants and let the client fetch bytes through the delivery edge. Emit page and item-impression telemetry separately.

New posts do not shift a numeric offset because this API uses either stable keyset positions or a pinned bounded candidate list. A cutoff alone does not prevent late fanout from changing the candidate population; refresh includes such arrivals, or the repeatable-session option pins the candidate IDs. A refresh starts a new snapshot. Deletions may remove items between pages; the API must handle them without leaking bodies or replaying already seen IDs endlessly. Prefetching the next bounded page is an optional latency optimization, not a requirement to materialize the user's entire history.

13Correctness deep dive

Checkpoint after certified writes

Event Required durable effect Recovery consequence
p701 commit Post plus e701 outbox in one transaction Relay can recover a missed queue send
Worker receives follower page P No progress claim yet Crash simply replays page P
Insert viewer A, then crash Unique (viewerA,p701) exists Retry detects it and continues with viewer B
Complete every write in P Persist checkpoint for next page Only then may P be skipped
Delete p701 during fanout Authoritative tombstone and cleanup event Read filtering prevents stale candidate disclosure

Repeated follower-page interleaving

At t0 worker A inserts viewer A. At t1 it loses its lease and worker B repeats the same page. B's viewer A insert is a no-op, viewer B's insert succeeds, and B advances the checkpoint. A may wake and repeat its writes; because these effects only insert the same immutable candidate identity, duplication does not corrupt the view. Checkpoint updates still use a current job generation or monotonic compare-and-swap so an old worker cannot move progress backward or incorrectly skip a newer page.

Deletion remains a serving-time decision

Celebrity strategy migration

A fanout event for a celebrity never enters this enormous scan. Policy changes are versioned and deduplicated during migration so a post may safely appear via both candidate paths while the threshold changes.

sequence · fanout-replayCheckpoint after all follower writes complete

Advance the follower-page checkpoint only after its conditional inserts complete. Repeating the page is safe.

Checkpoint after all follower writes completeAdvance the follower-page checkpoint only after its conditional inserts complete. Repeating the page is safe. worker to job: Read follower page P; worker to inbox: Insert viewer A / p701; worker to job: Crash before page completion; retry to job: Resume page P; retry to inbox: Repeat viewer A / p701; inbox to retry: Already exists: no duplicate; retry to inbox: Insert viewer B / p701; retry to job: Advance checkpoint after all writesPARTICIPANTFanout worker APARTICIPANTInbox partitionsPARTICIPANTDurable jobcheckpointPARTICIPANTWorker B1. Read follower page P2. Insert viewer A / p7013. Crash before page completion4. Resume page P5. Repeat viewer A / p7016. Already exists: no duplicate7. Insert viewer B / p7018. Advance checkpoint afterall writessyncblockedreturn
Read each connection in order
  1. syncRead follower page PFanout worker A → Durable job checkpoint
  2. syncInsert viewer A / p701Fanout worker A → Inbox partitions
  3. blockedCrash before page completionFanout worker A → Durable job checkpoint
  4. syncResume page PWorker B → Durable job checkpoint
  5. syncRepeat viewer A / p701Worker B → Inbox partitions
  6. returnAlready exists: no duplicateInbox partitions → Worker B
  7. syncInsert viewer B / p701Worker B → Inbox partitions
  8. syncAdvance checkpoint after all writesWorker B → Durable job checkpoint

14Failure and recovery

Failure / trigger User outcome, surviving state and recovery
Post owner crashes after commit the author may see a timeout. The new leader reads post-71 and returns p701. If no commit occurred, retry inserts once. The outbox row survives accepted publication, so a dispatcher outage delays propagation rather than losing the event. During a minority partition, that owner rejects new writes; the single-zone durability promise does not imply zero-loss regional failover.
Viral post overloads hydration Hashing post IDs spreads different posts but one p701 still has one ownership key. Replicate hot immutable body copies, coalesce cache fills and batch current visibility checks with admission limits. Rate-limit scraping. If caches fail, protect authority with a fallback budget rather than forwarding every impression at once. A feed can return a slightly older set of authorized candidates when nonessential ranking is unavailable.
Fanout stream falls behind Track oldest ordinary-author event and active-viewer lag. Add bounded workers where downstream inbox capacity allows; do not increase queue consumers until they overload every partition. Rebuild missing candidate windows from authoritative author lists when safe. Dormant viewers need not receive endless precomputed history.
Media or search outage Text can remain readable while media shows a retryable unavailable state; search may fail independently. Do not delete the post because a transient CDN origin fetch failed. Privacy and deletion checks remain mandatory. Backups must restore bodies, media references, unique request identities and tombstones; reconstructing inboxes cannot recover a lost authoritative post.

15Operations, security, and cost

Traffic, fanout and freshness signals

Measure accepted posts/s, page QPS, item impressions/s, feed p95/p99, candidate counts, fanout age, fraction of active readers whose inbox lacks recently eligible posts, cache byte/object hit ratios and celebrity merge cost. Keep freshness and latency separate: a 50 ms response containing yesterday's feed is not a successful five-second propagation result. Quotas cover posts, likes, follows and fanout-inducing actions, with account reputation and media validation to contain abuse.

Measured push-versus-pull cost

A rough push/pull decision compares recipient writes W with repeated merge reads R over the useful post window. If one reference write costs one unit and merging that author's candidate costs one unit per feed request, pushing to ten million mostly inactive followers can cost more than the hundred thousand actual reads it saves. Conversely, a small active community refreshing often benefits from precomputation. Measure both costs and cache effects before choosing a threshold.

Algorithms for derived features

Extended features consume committed events but need separate algorithms. Search builds an inverted index and ranks retrieved visible posts. Trends aggregate hashtags, queries, reshares or likes over explicit windows and update intervals; anti-abuse and unique-user signals prevent one bot from dominating raw frequency. Mentions/replies generate authorized notification tasks. Follow suggestions can explore bounded friends-of-friends candidates and rank mutual connections or interests, with privacy constraints. Curated “moments” group related recent posts/articles through classification or clustering and editorial policy; they are not the same as raw hashtag counts.

Fault tests and index rollout

Test fanout crashes, threshold changes, delete-during-hydration, stale replicas and replayed like events. Build a new index beside the live one and compare their query results. Then switch readers to the new version, retaining the old version for rollback. The authoritative post schema and privacy checks should not depend on a successful ranking experiment.

16Decision ledger and limitations

Choice Benefit Cost / consequence Change trigger
Pull recent author lists Cheap publication, no inactive inbox writes Repeated merge cost Many active repeat readers favor push
Push ordinary-author IDs Bounded common feed reads Amplified writes and recovery checkpoints Celebrity/low-activity audience favors pull
Hybrid with read authorization Handles uneven follower counts while checking current permissions Two candidate paths and authority checks Stronger availability may require negotiated staleness
Author/time indexes Local profile and celebrity range reads Extra write/index storage Access patterns justify a different primary layout
Immutable media plus CDN Reduces origin delivery work Retention and token/invalidation policy Immediate media revocation needs current edge checks

Identifier design is related to display ordering but does not replace storage layout. Including time can make IDs sortable; including a generator and sequence can distinguish concurrent allocations. Those fields still need allocation rules, and profile queries still need the author access path described above.

A timestamp/generator/sequence ID scheme needs unique generator assignment, overflow handling and a clock-rollback policy. An ID format with 31 timestamp bits measured in seconds and 17 sequence bits has a finite time horizon and per-second allocation limit; odd/even generators remain safe only while failover preserves disjoint allocation. Standard UUID or allocated ranges are alternatives, with sorting/index tradeoffs. No identifier scheme eliminates the database uniqueness rule or every secondary index. Three days of text may be 93 GB logically, but strings, object overhead, indexes and replicas make actual cache allocation larger.

17Interview closing

“I designed one authoritative post and multiple recoverable views. A post commits with its retry identity and outbox before acceptance. Profiles read author history; home feeds combine ordinary-author inbox references with high-fanout author lists. That asymmetry follows the workload: 16,000 average page requests per second are different from 324,000 item impressions, and fifty million recipient writes cannot meet a five-second freshness target.

“Fanout is resumable by follower page and safe to repeat through unique inbox keys. Candidate lists may lag, but current visibility filtering prevents stale IDs from authorizing deleted or private posts. Media is stored and delivered separately because its byte volume dominates text. Search, trends and recommendations are downstream products with their own quality and abuse controls.

“I accept extra derived indexes and two feed paths to avoid worst-case publication amplification. My next measurement is the push-versus-pull cost for active audiences, plus a cache-failure test on a viral post.”

If the interviewer asks for globally strict chronological order, distinguish a deterministic display sort from real-time total order across all writers. A global sequencer would add coordination and failure dependence that this feed does not require. Agree on the actual visible ordering contract before adding that bottleneck.

Practise the interview questions

Say your answer aloud before opening the model answer. Then answer the follow-up and compare the reasoning.

Foundation · Question 1

How would you build the first working home feed?

Reveal a model answer

I would query recent posts from each followed author through an author/time index, merge a bounded set by time and post ID, filter current visibility, and return one page. That is fanout on read. It gives a correct baseline without preparing unused inboxes; repeated merge cost determines when precomputation becomes worthwhile.

What the answer must demonstrate: Do not start with a queue without explaining its job.

Applied · Question 2

Why not push every post into every follower inbox?

Reveal a model answer

It buys fast reads, but the cost is proportional to followers. A 50-million-follower post can occupy the fanout pipeline while ordinary posts wait. I would read that author from a shared timeline and merge it with precomputed entries.

What the answer must demonstrate: Name the skew and the transition behavior.

Applied · Question 3

Your design serves 28 billion daily impressions. Is that the API QPS?

Reveal a model answer

No. With 20 items per response it corresponds to 1.4 billion page requests per day, about 16,204 requests per second. Loading post records and delivering media create different workloads.

What the answer must demonstrate: Units must match the component being sized.

Follow-up · Question 4

A worker stops after updating half the followers. How does it recover?

Reveal a model answer

The durable fanout job retains a follower-page checkpoint. It resumes or repeats a page, and unique reader/post entries prevent duplicate effects. I measure job age so an accepted post cannot remain invisibly stuck.

What the answer must demonstrate: A queue alone is not a recovery specification.

Foundation · Question 5

Would you put a timestamp in the post ID?

Reveal a model answer

Possibly, if time locality is useful. I still need an author/time index for profiles and reader/time entries for feeds. A timestamp ID alone does not answer those queries.

What the answer must demonstrate: Do not claim clocks guarantee uniqueness.

Follow-up · Question 6

The feed cache still contains a deleted post. Is eventual consistency acceptable?

Reveal a model answer

New-post freshness and deletion have different promises. This design checks current authoritative post visibility and private membership before returning metadata; an old inbox ID is only a candidate. Media grants have a separate maximum 60-second lifetime, so previously issued grants have that stated revocation bound. I would fail the authorization path closed rather than silently serve a stale permission decision.

What the answer must demonstrate: Explain the interleaving, not only the phrase cache invalidation.

Foundation · Question 7

A feed page returns twenty posts, but the baseline pulls twenty posts from each of 200 followed authors. Which workloads must you size?

Reveal a model answer

One page may examine up to 4,000 candidates before selecting twenty displayed items. I therefore size page-request rate, candidate merge and permission-check work, returned-item hydration and media bytes separately. At the assumed 4,630 home-feed opens per second, the naive candidate workload is about 18.5 million candidates per second. That repeated work is a concrete reason to precompute active-reader inboxes.

What the answer must demonstrate: Keep the unit attached to every rate.

Follow-up · Question 8

A worker saved its checkpoint before finishing the last follower writes. What can happen?

Reveal a model answer

After a crash, the replacement starts at the next page and permanently omits the unfinished followers. I save progress only after all writes covered by that checkpoint complete, and make each viewer/post insert idempotent so replaying an earlier page is harmless.

What the answer must demonstrate: A checkpoint certifies completed effects, not work merely scheduled in memory.

Blank-page exercise · 45 minutes

Build the answer yourself

Design posts, profiles and a paginated home feed. Calculate write, page, impression and media workloads; choose a push/pull policy for ordinary and 50-million-follower authors; recover partial fanout without duplicate or unauthorized results.

  • Build the single-server pull feed first.
  • Separate posts, pages, impressions, and media bytes.
  • Trace one post through a partial fanout failure.
  • Choose a celebrity policy and stable pagination.
  • Explain deletion visibility and ID-generation failures.

Check that each component and design decision follows from your requirements and workload.

Recall the key ideas

Answer from memory before opening each card. Explain why the choice works and what it costs. Revisit missed cards tomorrow.

Design a microblogging serviceWhat is fanout on write?Recall first, then reveal

Insert a post reference into recipient inboxes when the author posts, shifting work from later reads to the write pipeline.

One post, many inbox references.

Return to lesson
Design a microblogging serviceWhy is a celebrity special?Recall first, then reveal

Follower count makes one post create a huge burst of recipient writes; merge their shared timeline during reads instead.

Count recipients, not only posts.

Return to lesson
Design a microblogging serviceWhat is 28 billion daily impressions measuring?Recall first, then reveal

Items displayed across 1.4 billion feed pages at 20 items per page.

A page contains many impressions.

Return to lesson

Final revision

Summary and interview notes

A microblogging service commits one authoritative post and builds recoverable timelines and other views from it. Hybrid fanout precomputes ordinary-author candidates for active readers while reading high-fanout authors from shared lists; current visibility remains a separate read-time decision.

Remember these points

  • Page QPS, candidate work, displayed impressions and media egress are different units and must be estimated separately.
  • Post, retry identity, authoritative profile access path and outbox commit before publication is accepted.
  • Save fanout progress after the follower writes finish; unique viewer/post keys make repeating those writes safe.
  • A celebrity can make push amplification exceed the freshness target even when average follower count looks small.
  • A chronological cutoff is not a frozen candidate snapshot; repeatable sessions need pinned candidate IDs and current authorization.

Interview tips

  • Calculate one celebrity burst and one ordinary-reader merge before choosing push, pull or hybrid.
  • Trace a worker crash after some inbox inserts but before checkpoint persistence.
  • Explain which views may lag and which deletion or membership checks must be current.

Important qualifications

  • The 60-second media-grant revocation limit is separate from metadata authorization and cannot recall downloaded bytes.
  • Immediate profile visibility depends on an authoritative author/time path, not an asynchronous search or feed index.
  • The workload and viewing mix are interview assumptions, not measured traffic of a named platform.

Technical references

Practice marks stay in this browser.