Concept
Every other topic in this domain covered one mechanism in isolation, load balancing, caching, queues, sharding, rate limiting, real-time delivery, CAP tradeoffs. Real system design interviews (and real systems) require combining several of these into one coherent design, where the mechanisms interact and constrain each other. This closing topic works through three realistic case studies end to end, applying the Frontend System Design Framework's five steps to each, explicitly showing which earlier topics' mechanisms get reached for and why.
Case study 1: a news feed with infinite scroll
1. CLARIFY:
- Functional: chronological or algorithmically-ranked feed,
infinite scroll, new-posts-since-last-visit indicator.
- Scale: read-heavy, orders of magnitude more feed VIEWS than
posts CREATED (a classic read/write asymmetry).
- Latency: initial feed load should feel instant; subsequent
pages can tolerate slightly more latency.
2. DATA MODEL: a Post { id, authorId, content, timestamp,
engagementCounts }. Feed = an ORDERED, paginated sequence of
post IDs (fetching full post data separately, or joined, per
the API design step).
3. API / DATA FLOW:
- Cursor-based pagination (not offset-based), new posts
inserted at the top would shift offsets under an
in-progress scroll, exactly the reasoning covered in the
Frontend System Design topic.
- Feed generation itself: for a chronological feed, straightforward
query against a database, likely SHARDED by userId (Database
Design topic) once user count is large enough that a single
feed-serving database becomes a bottleneck.
4. FRONTEND-SPECIFIC:
- CDN caching for feed-adjacent static content (images, avatars), the CDN & Caching topic's core use case.
- Read-heavy load naturally suggests READ REPLICAS (Database Design)
for feed-serving queries, keeping the write path (creating a new
post) on a separate, unblocked path.
- Virtualized rendering for the feed list itself (only mount DOM
nodes for currently-visible posts), the same technique from
Frontend System Design's live-comments example, here applied to
an unboundedly-growing feed.
- "New posts available" indicator: a lightweight, low-frequency
check (short polling, or a lightweight WebSocket event) rather
than a full feed re-fetch, an explicit example of the Real-Time
Systems topic's fallback-ladder reasoning, choosing the CHEAPEST
mechanism that satisfies the actual requirement (a count/notice,
not full live-streaming of every post).
5. TRADE-OFFS:
- Choosing eventual consistency (AP, per the CAP topic) for feed
content specifically, a feed that's a few seconds stale after
a new post is a fully acceptable, common trade-off, given the
alternative (blocking on strict consistency for every feed read)
would meaningfully hurt the read-heavy, latency-sensitive core
experience.
- At 10x scale, the feed-generation step itself (especially for an
ALGORITHMICALLY ranked, not purely chronological, feed) may need
to move from "compute at request time" to "precompute and cache
per-user feed contents asynchronously" (a queue-driven background
job, per the Message Queues topic), flagged explicitly as a
scaling path, not built from day one.Case study 2: a real-time collaborative document editor
1. CLARIFY:
- Functional: multiple users editing the same document
concurrently, seeing each other's changes live, cursor
presence, permission-gated edit access.
- Scale: likely far fewer CONCURRENT editors per document (tens,
not thousands) than the news feed's readers, but the
consistency requirements are much stricter.
- Latency: edits should propagate to other viewers within
roughly 100ms-1s to feel "live."
2. DATA MODEL: a Document as a sequence of operations (inserts/
deletes with position info), not just a single content blob, this is what makes concurrent-edit merging tractable.
3. API / DATA FLOW:
- WebSocket connection per active editing session, scoped to a
per-document channel, directly the Real-Time Systems topic's
pub/sub-backed fan-out pattern, so an edit from one user's
server instance reaches every other connected editor regardless
of which server instance holds THEIR connection.
- Initial document load: a standard REST/GraphQL fetch of current
document state plus recent operation history.
4. FRONTEND-SPECIFIC:
- Optimistic UI: a user's own keystrokes render IMMEDIATELY,
locally, before server confirmation, waiting for a round trip
on every keystroke would feel unusably laggy.
- Conflict resolution: Operational Transformation or CRDTs merge
concurrent edits from different users into a convergent final
state, this is squarely a CAP-theorem-flavored decision (per
Case study 3: a cross-channel notification system
1. CLARIFY:
- Functional: a single triggering event (e.g. "someone commented
on your post") needs to reach the user via potentially MULTIPLE
channels, a web push notification, a mobile push notification,
and/or an email, depending on user preferences and channel
availability.
- Scale: bursty, a popular post getting many comments in a short
window can trigger a large batch of notifications nearly
simultaneously.
- Latency: web/mobile push should feel near-real-time; email is
explicitly tolerant of being somewhat delayed.
2. DATA MODEL: a NotificationEvent { type, targetUserId, payload,
triggeredAt }, decoupled from the actual DELIVERY mechanism,
which is decided per-channel based on user preference.
3. API / DATA FLOW:
- The triggering action (posting a comment) PUBLISHES a
notification event rather than directly calling three separate
delivery mechanisms inline, directly the Message Queues &
Pub/Sub topic's fan-out pattern: one event, multiple independent
subscribers (a web-push service, a mobile-push service, an
email service), each reacting in its own way.
- Each channel-specific subscriber is itself backed by a
POINT-TO-POINT queue for its own worker pool (e.g. a pool of
workers actually calling the email-sending provider), the
exact combined pub/sub-plus-point-to-point architecture
described in the Message Queues topic.
Try It
For the news feed case study, the interviewer adds a new requirement mid-discussion: "Users should also see a live count of new posts available since they last refreshed, without a full page reload." Using the mechanisms from earlier topics, sketch the minimal design for this specific feature.
Solution
This is a genuinely small addition to the existing design, and recognizing it as such, rather than treating it as requiring a full architecture change, is itself part of a strong answer.
Design: rather than pushing every new post's full content live (which would essentially turn the whole feed into the Real-Time Systems topic's live-comments pattern, a heavier mechanism than this specific requirement needs), a lightweight, low-frequency signal suffices: either (a) a short-polling check every N seconds asking "how many new posts exist since cursor X," returning just a count, not full post data, or (b) a lightweight WebSocket/SSE event carrying just an incrementing count, published to a per-user (or per-feed-type) channel whenever a new relevant post is created.
Option (b) is generally preferable at meaningful scale specifically because it avoids the wasted-request overhead of polling when nothing has changed (the same reasoning the Real-Time Systems topic gives for preferring push over polling once scale justifies it), but the KEY design insight either way is that this feature needs only a COUNT, not the actual new posts' content, which is a much cheaper thing to compute and deliver than the full feed-diffing this might sound like at first. The actual new posts only get fetched (via the existing paginated feed API) once the user explicitly acts on the indicator, e.g. clicking "10 new posts, tap to view."
This demonstrates the core skill this closing topic is testing: recognizing which EXISTING mechanism (a lightweight pub/sub count, reusing infrastructure the design may already have) fits a new requirement, rather than reflexively reaching for the heaviest available tool (full live-streaming of every new post) when a lighter one satisfies the actual stated need.
Implement It Yourself
A minimal, self-contained simulation tying together three of this domain's mechanisms, pub/sub fan-out, per-channel idempotent delivery, and rate limiting, for the notification-system case study, small enough to reason about end to end:
class NotificationRouter {
constructor() {
this.channels = []; // subscribed delivery channels (web, mobile, email)
this.deliveredIds = new Set(); // idempotency guard per (channel, eventId)
this.userSendCounts = new Map(); // simple per-user rate-limit tracking
}
subscribe(channel) {
this.channels.push(channel);
}
publish(event) {
// Rate limiting: cap notifications per user within this simulated window
const count = this.userSendCounts.get(event.targetUserId) ?? 0;
if (count >=
This small example genuinely combines three separately-covered mechanisms, pub/sub fan-out, per-channel idempotency, and rate limiting, into one coherent flow, which is exactly the kind of synthesis a real case-study interview question is testing for, just at a scale small enough to trace through by hand.
Under the Hood
The optimistic-edit-then-reconcile pattern in the collaborative editor case study depends on the same component-identity matching covered in React Reconciliation, a locally-inserted character needs to be matched against the server-confirmed version of that same edit without the surrounding text visually flickering or losing cursor position, which is a direct, practical consequence of how the rendering layer decides what changed versus what's the same.
Common Mistakes
1. Designing a single mechanism for a case study and stopping there
"For the news feed, we'll use a WebSocket." // ❌ a full case study needs multiple mechanisms combined, not oneA realistic case study genuinely requires combining several mechanisms, caching, read replicas, pagination strategy, and a scoped-appropriately real-time signal, in the feed example, reaching for just one (especially the flashiest-sounding one) and treating that as a complete answer misses the actual point of these questions, which is evaluating whether a candidate can integrate multiple concerns coherently.
2. Reaching for the heaviest available mechanism regardless of actual requirement
"For the 'new posts' count indicator, let's stream full post content over a dedicated real-time pipeline." // ❌ over-engineered for what's actually needed (a count)As shown in Try It, the actual requirement (a count) is much cheaper to satisfy than the heaviest applicable mechanism (full live content streaming), proposing the heaviest tool without first checking whether a lighter one satisfies the actual stated need is a common overengineering mistake, and one interviewers specifically probe for.
3. Applying one CAP/consistency choice uniformly across an entire case study
"The whole document editor system is AP." // ❌ ignores that permission-checking within the SAME system plausibly needs CPAs the CAP topic itself establishes, and as case study 2 makes concrete, different subsystems within the same overall design genuinely warrant different consistency choices, document content (AP) versus permission checking (CP) is exactly this pattern, and treating an entire case study's backend as uniformly one or the other misses a real, important nuance.
Best Practices
- Explicitly name which earlier mechanism you're reaching for and why, rather than describing a new, unnamed piece of infrastructure from scratch, "this is the same read-replica pattern from Database Design, applied here because reads are heavy" demonstrates integrated understanding, not just isolated topic recall.
- Match the weight of the chosen mechanism to the actual requirement, a count needs a count-sized mechanism, not a full live-streaming pipeline; recognizing when a lighter tool suffices is itself a signal of judgment, not just knowledge.
- Make CP/AP (and similar) choices per-subsystem within a single case study, not once for the whole design, a real system routinely has multiple, deliberately different consistency choices coexisting.
- Always run through all five framework steps for a case study, even under interview time pressure, skipping straight to "the interesting part" (usually the real-time or scaling piece) without first covering requirements, data model, and API contract is a common, avoidable gap.
- Name explicit scaling triggers ("this works fine until X, and here's what changes past that point") for at least one part of every case study, this demonstrates the kind of forward-looking judgment interviewers are specifically listening for.
Performance Tips
- Distinguishing a "count/signal" requirement from a "full content" requirement (as in the news-feed indicator) is frequently the single highest-leverage design decision in a case study, it's the difference between a cheap, simple mechanism and an unnecessarily heavy one, and interviewers notice which one a candidate reaches for by default.
- Combining pub/sub fan-out with per-consumer point-to-point queues (as in the notification case study) lets each delivery channel scale its own worker pool independently, a channel experiencing higher load (say, email under a temporary provider slowdown) doesn't block or slow down the others.
- Idempotency and rate limiting, while each individually simple mechanisms, compound in value specifically in a multi-channel system, a bug or a redelivery in one channel shouldn't cascade into duplicate or excessive notifications across every other channel, which is exactly why both mechanisms are applied per-channel, not once globally.
