Design YouTube (Frontend)
Frontend system design for a video streaming product — player, feed, performance, caching, and offline concerns.
- system-design
- video
- performance
- caching
Scope the problem
Frontend system design interviews fail when candidates design the entire Google backend. Lock scope in the first five minutes.
In scope (frontend):
- Home / subscription feed
- Watch page: player, description, comments
- Search results
- Upload entry points (not the full encoder pipeline)
Out of scope unless asked: CDN POP placement, recommendation model training, ad auction internals.
Scale assumptions (state out loud):
- Global users; mobile-heavy
- Videos from seconds to multi-hour
- Adaptive bitrate streaming (HLS/DASH)
- Personalized home feed
High-level UI architecture
┌─────────────────────────────────────────────────────────┐
│ App shell (auth, nav, feature flags, i18n) │
├──────────────┬──────────────────────────┬───────────────┤
│ Route modules│ Shared player runtime │ Design system │
│ home/watch/ │ MediaSession, MSE/HLS │ tokens, a11y │
│ search/lib │ quality, captions │ │
└──────────────┴──────────────────────────┴───────────────┘
Prefer route-based code splitting. The watch page should not download the upload wizard.
Watch page — critical path
Goals
- First frame fast (LCP / time-to-first-frame)
- No layout jump when metadata loads
- Smooth quality switches
- Captions, keyboard, screen reader support
Data dependencies
| Resource | Priority | Notes |
|---|---|---|
| Video manifest + first segment | Highest | Start playback ASAP |
| Title / channel / view count | High | SSR or streamed HTML |
| Related videos | Medium | Below fold; defer |
| Comments | Low | Paginate / virtualize |
Rendering strategy
- SSR/SSG shell for watch URL with title + poster + JSON-LD
VideoObject - Client player mounts after hydration or via progressive enhancement
- Stream secondary data (related, comments) after first paint
User navigates to /watch?v=id
→ HTML shell with poster + meta (SSR)
→ JS player bootstrap
→ fetch manifest
→ append init + media segments (MSE)
→ parallel: related + comments APIs
Player design
VideoPlayer
├── Media element (video)
├── Source controller (HLS.js / native HLS / DASH)
├── UI chrome (play, seek, volume, quality, captions, theater)
├── Keyboard manager
└── Analytics bridge (qos: startup, rebuffer, bitrate)
State machine (simplified): idle → loading → ready → playing ⇄ paused → ended with branches for error and rebuffering.
Expose imperative control via a small API so keyboard shortcuts and Media Session can share one controller.
Feed & virtualization
Home feed is a long list of cards. Use windowing (e.g. only mount ~20 visible cards). Preload thumbnails for the next viewport with loading="lazy" and priority for the LCP image.
Infinite scroll: cursor-based pagination; keep a single cache keyed by feed type + cursor. Abort in-flight requests on rapid filter changes.
Caching
| Layer | What | Strategy |
|---|---|---|
| HTTP cache | Static JS/CSS, thumbnails | Long cache + hashed names |
| Service Worker | App shell, recent watch metadata | Network-first for APIs; cache-first for shell |
| Memory (React Query / SWR) | GraphQL/REST responses | Stale-while-revalidate; keyed by video id |
| IndexedDB | Offline watch progress, drafts | User-scoped |
Do not cache personalized home feed aggressively without revalidation — users notice stale recommendations.
Performance budgets (example)
- JS for watch route: < 200KB gzip initial
- Time to first frame on mid-tier 4G: < 2.5s (target)
- Interaction to seek response: < 100ms UI feedback
Techniques: split player vendor, prefetch manifest on hover of a card, content-visibility for offscreen sections, avoid layout thrash on progress bar updates (use transform).
Accessibility
- Custom controls must be full keyboard operable
- Captions default respect user preferences
- Focus management when opening theater / mini-player
- Reduced motion: limit autoplay animations
Tradeoffs to discuss
- SPA vs MPA for watch — MPA can win first paint; SPA wins sequential watch sessions
- Client vs server personalization of feed
- Third-party player vs in-house
- Comments: live websocket vs polling
Closing structure
End with: requirements recap → architecture diagram → critical path → scaling bottlenecks (comments fan-out, player QoS) → monitoring (RUM for rebuffers, CLS on feed).