Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save carefree-ladka/54e6559d2dc1190dd9fa9beb160795f2 to your computer and use it in GitHub Desktop.

Select an option

Save carefree-ladka/54e6559d2dc1190dd9fa9beb160795f2 to your computer and use it in GitHub Desktop.
SDE-2 Frontend System Design Interview Prep

SDE-2 Frontend System Design Interview Prep

A structured weekend checklist for mastering large-scale UI system design interviews. Focus: Think in systems, not just code.


Table of Contents

  1. How to Structure Your Answer
  2. Rendering Strategy
  3. Data Fetching Strategy
  4. State Management
  5. Performance Optimization
  6. Caching Strategy
  7. Scalability Considerations
  8. Error Handling & Reliability
  9. Security
  10. Accessibility
  11. Testing
  12. Real Product Design Examples
  13. Example Answer Flow
  14. Must-Know Concepts for SDE-2

1. How to Structure Your Answer

Interviewers at SDE-2 level want to see structured thinking, not just code. Always lead with requirements before diving into implementation.

Functional Requirements

Answer: What does the UI do?

  • Key user flows (e.g., view feed, like/comment, infinite scroll, notifications)
  • Core features in scope vs. out of scope

Non-Functional Requirements

Answer: How well does it do it?

Concern Example Target
Performance Page load < 2s, TTI < 3s
Scalability Handle 1M+ concurrent users
SEO Crawlable content for public pages
Offline Support Works without network (e.g., Gmail offline)
Accessibility WCAG 2.1 AA compliance

Interview tip: Always clarify both functional and non-functional requirements before designing. This signals maturity.


2. Rendering Strategy

One of the most commonly tested topics. Know when to use each strategy and why.

CSR — Client-Side Rendering

The browser downloads a minimal HTML shell and renders everything via JavaScript.

  • Best for: Highly interactive apps with no SEO needs
  • Examples: Dashboards, Gmail, Trello, admin panels
  • Pros: Rich interactivity, seamless navigation after initial load
  • Cons: Slower first contentful paint, poor SEO without extra work

SSR — Server-Side Rendering

The server renders full HTML on each request and sends it to the browser.

  • Best for: SEO-critical, content-heavy pages
  • Examples: E-commerce product pages, blogs, marketing sites
  • Pros: Fast first paint, great SEO, works without JS
  • Cons: Higher server load, slower TTFB under load

SSG — Static Site Generation

HTML is pre-rendered at build time and served as static files.

  • Best for: Rarely-changing content
  • Examples: Documentation sites, landing pages, portfolios
  • Pros: Fastest possible load, CDN-friendly, zero server cost
  • Cons: Stale content between builds, long build times at scale

ISR — Incremental Static Regeneration

Static pages are regenerated in the background at configurable intervals.

  • Best for: Large catalogs that change occasionally
  • Examples: Product pages, news archives
  • Pros: Combines SSG speed with near-fresh data
  • Cons: Users may briefly see stale content

Streaming / Partial Hydration

The server streams HTML progressively; only interactive components are hydrated.

  • Best for: Complex pages where parts load faster than others
  • Examples: Next.js App Router with React Server Components
  • Pros: Faster perceived load, reduced JS bundle
  • Cons: Added complexity, framework-dependent

3. Data Fetching Strategy

Match your data fetching pattern to the freshness and latency requirements of your data.

Polling

Client repeatedly fetches data on a fixed interval.

setInterval(() => fetch('/api/notifications'), 5000);
  • Use when: Near-real-time is acceptable, WebSocket setup is overkill
  • Examples: Notification counts, dashboard metrics

Long Polling

Client makes a request; server holds it open until new data is available.

  • Use when: You need real-time feel without WebSockets
  • Examples: Legacy chat apps, simple notification systems

WebSockets

Full-duplex, persistent connection between client and server.

const ws = new WebSocket('wss://api.example.com/chat');
ws.onmessage = (event) => updateUI(JSON.parse(event.data));
  • Use when: True bidirectional real-time communication is required
  • Examples: Chat, collaborative editors (Google Docs), multiplayer games, trading dashboards

SSE — Server-Sent Events

Server pushes a one-way stream of updates to the client over HTTP.

const es = new EventSource('/api/live-scores');
es.onmessage = (event) => updateScore(event.data);
  • Use when: Server → client updates only (no client → server stream needed)
  • Examples: Live sports scores, stock prices, news feeds

Comparison Cheat Sheet

Method Direction Protocol Best For
Polling Client → Server HTTP Infrequent updates
Long Polling Client → Server HTTP Near-real-time, simple
WebSockets Bidirectional WS Chat, games, collaboration
SSE Server → Client HTTP Live feeds, push notifications

4. State Management

Think about where state lives and who owns it — not just which library to use.

Local State

Component-level state for UI-only concerns.

const [isOpen, setIsOpen] = useState(false);
  • Use for: Modals, dropdowns, form inputs, toggles

Global State

Application-wide state shared across many components.

// Zustand example
const useStore = create((set) => ({
  user: null,
  setUser: (user) => set({ user }),
}));
  • Tools: Redux (large apps), Zustand (lightweight), React Context (simple cases)
  • Use for: Auth session, theme, user profile, shopping cart

Server State

Remote data with its own lifecycle: loading, stale, error, revalidating.

// React Query example
const { data, isLoading } = useQuery(['posts'], fetchPosts, {
  staleTime: 60 * 1000, // 1 minute
});
  • Tools: React Query, SWR
  • Handles automatically: Caching, background refetch, deduplication, pagination

Interview tip: Distinguish server state from global state. Fetched data is not the same as app state — treat them separately.


5. Performance Optimization

This section differentiates SDE-2 candidates. Know all three layers.

Bundle Optimization

Reduce the amount of JavaScript the browser must download and parse.

  • Code splitting: Break app into async chunks loaded on demand
  • Lazy loading: Defer non-critical components
const ProductPage = React.lazy(() => import('./ProductPage'));
  • Tree shaking: Remove unused exports at build time
  • Vendor splitting: Separate third-party libraries into their own chunk (changes less often → better cache hits)

Asset Optimization

Reduce network payload for images and static assets.

  • Image formats: Prefer WebP or AVIF over PNG/JPEG (30–50% smaller)
  • Responsive images: Use srcset to serve size-appropriate images
  • CDN: Serve assets from edge nodes close to the user
  • Compression: Enable gzip or Brotli on the server

Runtime Performance

Keep the UI fast after the page loads.

  • Virtualization: Render only visible rows in long lists
import { FixedSizeList } from 'react-window';
// Renders only ~10 visible items even for 100,000-row lists
  • Memoization: Prevent unnecessary re-renders
const MemoizedCard = React.memo(Card);
const sortedList = useMemo(() => sort(items), [items]);
const handleClick = useCallback(() => doSomething(id), [id]);
  • Debounce / Throttle: Limit high-frequency event handlers (search input, scroll, resize)

Critical Rendering Path

Optimize what the browser does before first paint.

  • <link rel="preload"> for critical fonts and above-the-fold images
  • <link rel="prefetch"> for likely-next-page resources
  • async / defer on non-critical scripts to unblock HTML parsing
  • Minimize render-blocking CSS; inline critical CSS

6. Caching Strategy

Always discuss multiple caching layers — not just the application layer.

Browser Cache

Controls how long the browser stores static assets locally.

Cache-Control: public, max-age=31536000, immutable  // for versioned assets
Cache-Control: no-cache                              // for HTML pages

CDN Cache

Caches responses at edge servers geographically close to users.

  • Dramatically reduces latency for global users
  • Cache-bust by versioning asset filenames (e.g., main.abc123.js)

Application Cache (React Query / SWR)

Keeps fetched data in memory and serves it instantly on repeat visits while revalidating in the background.

useQuery(['user', userId], fetchUser, {
  staleTime: 5 * 60 * 1000,   // serve from cache for 5 minutes
  cacheTime: 10 * 60 * 1000,  // keep in memory for 10 minutes after unmount
});

LocalStorage / IndexedDB

Persist data across sessions in the browser.

  • LocalStorage: Small key-value data (tokens, preferences) — synchronous, 5MB limit
  • IndexedDB: Large structured data — asynchronous, good for offline-first apps
  • Examples: Gmail offline, Google Docs offline draft storage

Interview tip: Mention cache invalidation strategy — what happens when data changes? Stale-while-revalidate, TTL, manual invalidation on mutation.


7. Scalability Considerations

How does the UI hold up as data volume and user count grow?

Pagination & Infinite Scroll

Load data in pages instead of all at once.

  • Cursor-based pagination is preferred over offset for large, frequently-updated datasets (avoids duplicate/missing items)
  • Infinite scroll with virtualization = best of both worlds for feeds

Virtualization

Render only the DOM nodes visible in the viewport.

// 100,000-row table — only ~20 DOM nodes at any time
<FixedSizeList height={600} itemCount={100000} itemSize={50}>
  {Row}
</FixedSizeList>

Micro-Frontends

Split a large frontend into independently deployable modules owned by separate teams.

  • Use when: Multiple teams, large codebase, independent deployment cycles
  • Examples: Amazon, Spotify, IKEA
  • Approaches: Module Federation (Webpack 5), iframes, Web Components

Feature Flags

Ship code to production without exposing it to users yet; roll out gradually.

  • Enables A/B testing, canary releases, and instant rollback
  • Tools: LaunchDarkly, Unleash, custom flag service

8. Error Handling & Reliability

Production-grade UIs anticipate failure.

Retry Logic

Automatically retry failed requests with exponential backoff.

async function fetchWithRetry(url, retries = 3, delay = 500) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fetch(url);
    } catch (err) {
      if (i === retries - 1) throw err;
      await new Promise(res => setTimeout(res, delay * 2 ** i));
    }
  }
}

Error Boundaries

Catch rendering errors in a component subtree and show a fallback UI.

<ErrorBoundary fallback={<ErrorMessage />}>
  <FeatureComponent />
</ErrorBoundary>

Fallback UI

  • Show skeleton screens while loading (better UX than spinners for layout-heavy pages)
  • Show cached/stale data with a "refresh" prompt rather than a blank screen

Monitoring

  • Log errors to services like Sentry or Datadog RUM
  • Track Core Web Vitals (LCP, FID/INP, CLS) in production
  • Set up alerts for error rate spikes

9. Security

Mention these briefly but confidently.

  • XSS Prevention: Never inject raw HTML; use React's JSX escaping; set Content-Security-Policy headers
  • CSP (Content Security Policy): Whitelist trusted script/style sources to block injected malicious scripts
  • Input Sanitization: Strip or escape dangerous characters before rendering user-generated content
  • Secure Cookies: Use HttpOnly, Secure, and SameSite=Strict flags on auth cookies
  • Auth Tokens: Store tokens in memory or HttpOnly cookies — never in localStorage (vulnerable to XSS)

10. Accessibility

Cover this briefly — it signals quality engineering.

  • Semantic HTML: Use <button>, <nav>, <main>, <h1> correctly so screen readers understand structure
  • ARIA: Add aria-label, aria-expanded, role attributes where semantic HTML is insufficient
  • Keyboard Navigation: All interactive elements must be reachable and operable via keyboard
  • Color Contrast: Meet WCAG AA (4.5:1 ratio for normal text)
  • Focus Management: Restore focus after modals close; trap focus within open modals

11. Testing

Show you think about reliability, not just features.

Type What It Tests Tools
Unit Individual functions and components in isolation Jest, Vitest
Integration Component interactions and data flow React Testing Library
E2E Full user flows in a real browser Cypress, Playwright
Visual Regression UI appearance across changes Percy, Chromatic
// Integration test example
test('user can submit a comment', async () => {
  render(<CommentForm />);
  await userEvent.type(screen.getByRole('textbox'), 'Great post!');
  await userEvent.click(screen.getByRole('button', { name: /submit/i }));
  expect(await screen.findByText('Great post!')).toBeInTheDocument();
});

12. Real Product Design Examples

Practice these four. Most SDE-2 frontend design questions are variations of them.

News Feed (Twitter / Facebook)

Key topics to cover:

  • Infinite scroll + cursor-based pagination
  • Feed virtualization with react-window
  • Optimistic UI for likes/retweets
  • Real-time updates via WebSockets or SSE
  • Cache strategy: React Query with stale-while-revalidate
  • Rendering: CSR with SSR for initial load (hybrid)

Collaborative Document Editor (Google Docs)

Key topics to cover:

  • WebSockets for real-time sync
  • Operational Transforms (OT) or CRDTs for conflict resolution
  • Offline support with IndexedDB + sync queue
  • Autosave with debounce
  • Presence indicators (who else is editing)

Video Streaming (YouTube / Netflix)

Key topics to cover:

  • Adaptive bitrate streaming (HLS / DASH) — quality adjusts to bandwidth
  • CDN for video delivery at global scale
  • Lazy loading of video player and recommendations
  • Progressive loading: show thumbnail → load player → buffer video
  • Pre-fetching next episode

Chat Application

Key topics to cover:

  • WebSockets for real-time message delivery
  • Optimistic UI: show message immediately, confirm on server ack
  • Message ordering with sequence numbers or timestamps
  • Retry logic for failed sends
  • Infinite scroll (upward) for history
  • Read receipts and typing indicators

13. Example Answer Flow

When asked "Design a Twitter-like news feed", structure your answer in this order:

1. Requirements
   ├── Functional: view feed, post tweet, like, retweet, infinite scroll
   └── Non-functional: < 2s load, 1M users, real-time updates

2. High-Level Architecture
   └── CDN → Load Balancer → API Gateway → Services → DB

3. Rendering Strategy
   └── SSR for first load (SEO + speed) → CSR for interactions

4. Data Fetching
   └── Initial: SSR fetch → Client: WebSocket for live updates

5. Caching
   └── CDN for assets → React Query for feed data (stale-while-revalidate)

6. Performance Optimization
   └── Virtualized feed list → Lazy-loaded images → Code splitting

7. Scalability
   └── Cursor pagination → Feature flags for new features

8. Edge Cases
   └── Offline mode → Error boundaries → Retry on failure

Tip: Speak out loud as you draw. Interviewers care as much about how you think as what you design.


14. Must-Know Concepts for SDE-2

Be able to explain each of these clearly and concisely — not just name them.

Concept What You Should Know
React Reconciliation How React diffs the virtual DOM and determines minimal DOM updates
React Fiber React's incremental rendering engine; enables time-slicing and Suspense
Virtualization Rendering only visible DOM nodes to handle massive lists efficiently
Code Splitting Breaking bundles into async chunks loaded on demand via dynamic import()
Caching Layers Browser cache → CDN → Application cache → LocalStorage/IndexedDB
WebSockets vs. Polling WS = persistent bidirectional; Polling = periodic HTTP; SSE = server push
CDN Edge servers that serve assets from locations geographically close to users
Service Workers Background scripts enabling offline support, push notifications, and cache control
Critical Rendering Path The sequence browser follows to render a page; optimize by reducing blocking resources
Bundle Optimization Tree shaking, code splitting, vendor chunking, lazy loading to reduce JS payload

Good luck — you've got this. 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment