YouTube Interview Questions | JiQuest

add

#

YouTube

System design deep dive · HLD

Design YouTube: full high-level design.

Requirements, back-of-envelope capacity estimation, a high-level design diagram, a deeper deployment architecture diagram, sequence diagrams for asynchronous upload/transcoding and for view-counting at scale, and an entity-relationship diagram for videos, views, channels, and comments - with the reasoning an interviewer expects behind every box and arrow.

500 hrsVideo uploaded / minute
~58K/sAverage views ingested
1000:1View : upload ratio
Viewertaps a video Watch servicereturns manifest View counterbuffered increment CDNstreams segments Recommenderup-next feed adaptive bitrate playback

1. Clarify requirements before drawing any box

YouTube's hardest problem is not any single feature - it's that upload, playback, view counting, comments, and recommendations all have wildly different consistency and latency needs, and mixing them up in one datastore would break all of them at once.

Functional requirements

Upload & processCreators upload a raw file; it is asynchronously transcoded into a playable rendition ladder before going live.
Watch & count viewsViewers stream video and each qualifying watch increments a view counter, resistant to bot inflation.
Comment & engageViewers post threaded comments, likes, and replies under a video.
RecommendA personalized home feed and an "up next" queue are generated per viewer from watch history and video metadata.

Non-functional requirements

Playback availabilityWatching a video must stay up even if comments or the recommender is degraded.
Eventually-consistent countersView and like counts can lag by seconds; they must never block the watch path to stay exact.
Upload durabilityA creator's raw upload must never be lost, even if transcoding fails and must be retried.
Extreme read fan-outA single viral video can be watched by tens of millions in hours; reads must scale independently of writes.
Explicitly out of scope Live streaming ingestion, monetization/ad auction mechanics, and content moderation ML pipelines are called out as extensions rather than core requirements, so the core design stays focused on upload, watch, counting, comments, and recommendations.

2. Back-of-the-envelope capacity estimation

These numbers decide whether view counting can ever be a synchronous database increment (it cannot), how large the transcoding fleet needs to be, and how comments must be partitioned to avoid hotspotting under a viral video.

MetricAssumptionResulting estimate
New uploads500 hours of video uploaded per minute~720,000 hours/day ≈ ~30,000 concurrent transcoding jobs assuming ~1hr avg processing time per hour of source
Video views~5 billion views/day globally~58,000 views/sec average, ~180,000 views/sec peak (prime-time regions overlapping)
View-count incrementsEvery view is a counter write, batchedNaive per-view DB writes at 180K/s would saturate any single database; must be buffered and aggregated
Comments posted~0.2% of views produce a comment~58,000 × 0.002 ≈ 116 comment writes/sec average - far lighter than the view path
Storage growth720,000 hours/day × ~1.5GB/hr average across the rendition ladder~1.08 PB/day of new encoded video, all going to durable, replicated object storage
Why this matters The three-orders-of-magnitude gap between views (~58,000/sec) and comments (~116/sec) is the number that justifies treating view counting as an approximate, buffered, eventually-consistent pipeline while comments can afford a more conventional, immediately-consistent write path.

3. High-level design (HLD)

The HLD separates four independent paths that only share the video's metadata record: the upload/transcode pipeline, the watch/streaming path, the view-counting pipeline, and comments - each scaled and consistency-tuned for its own workload.

Creatoruploads raw file Upload servicechunked, resumable Transcode workersasync, queue-driven Video storage + CDNrenditions, thumbnails Viewerwatches a video Watch servicemetadata + manifest Video metadata DBsharded Recommender svcpersonalized feed View event streamKafka View counter aggregatorwindowed, bot-filtered Comments serviceown sharded store
Stateless servicesBuffered / aggregated infraDurable storage & edgeAsync / metadata

What each box owns

Upload service & transcode workers

The upload service accepts chunked, resumable uploads so a spotty connection doesn't force a creator to restart a multi-GB file from zero. Once fully received, the raw file is handed to a queue-driven pool of transcode workers that produce the rendition ladder (multiple resolutions/codecs) and thumbnails asynchronously - the creator gets an immediate "processing" confirmation, not a synchronous wait for encoding to finish.

Watch service & video metadata

Resolves a video ID to its manifest (available renditions, CDN URLs) and current metadata (title, view count snapshot, channel). This is the highest-QPS read path in the whole system and is backed by a heavily cached, sharded metadata store - it deliberately never touches the view-counting pipeline synchronously.

View counter aggregator

Every watch emits a lightweight view event to a Kafka stream rather than incrementing a database row directly. A windowed aggregator consumes the stream, applies bot/fraud filtering heuristics (e.g. requiring a minimum watch duration, deduplicating rapid repeat views from the same session), and periodically flushes batched increments to the metadata store - trading exactness for the ability to absorb 180,000 events/sec without falling over.

Comments service & recommender

Comments live in their own sharded store (sharded by video ID) so a comment storm under one viral video can't degrade writes for unrelated videos. The recommender consumes watch history and video metadata offline/near-real-time to produce a personalized ranked feed per viewer, served from a precomputed cache rather than computed synchronously on every home-page load.

4. Detailed architecture diagram

The architecture diagram shows how the view-counting pipeline is deliberately decoupled and buffered, how transcoding is sharded across an elastic worker pool, and how comments are sharded to survive a single video going viral.

Edge layer CDN edge (video bytes) API gateway + L7 LB Rate limiterper-key upload throttling Auth / session svc Upload & transcode pipeline Upload svc ×20 pods Job queue (priority-aware) Transcode workerselastic, 1000s of podsscales with upload volume Watch path (read-optimized) Watch svc ×60 pods Metadata cache (Redis) Video metadata DBsharded by video_idread replicas per shard View-counting pipeline (buffered) Kafka (view events) Windowed aggregator flushes batched counter deltas every few seconds, not per-view Comments store Comment svc ×16 pods Sharded by video_id a viral video's comment shard scales independently of others
DecisionChoiceReasoning
View countingStream + windowed aggregation, batched flush180,000 events/sec of synchronous per-row increments would saturate any relational database; batching absorbs bursts and tolerates a display lag of a few seconds.
Metadata sharding keyHash of video_idEvery watch, comment, and view-count update is keyed by video_id, so sharding on it keeps almost all queries single-shard.
Comments isolationSeparate sharded store from video metadataA comment storm under a viral video must not compete for capacity with the metadata store that every playback request depends on.
Transcode worker scalingElastic pool, priority queue by channel size/verificationUpload volume is bursty; a large creator's time-sensitive upload shouldn't wait behind a backlog of low-priority re-encodes.

5. Sequence diagrams for the two critical flows

The upload flow shows how transcoding is fully decoupled from the client response; the view-counting flow shows exactly why a "view" is never a synchronous database write.

5.1 Video upload & asynchronous transcoding

Creator Upload svc Job queue Transcode workers Metadata DB 1. PUT chunk 1..N (resumable) 2. 202 Accepted, status=processing 3. enqueue transcode job 4. dequeue, priority-ordered 5. encode ladder + thumbnails 6. status=live, notify webhook 7. push notification: video is live

Step 2 returns immediately after the raw bytes are durably stored, well before encoding starts - the creator's upload experience is never gated on transcoding time. Steps 4-5 can take anywhere from minutes to hours depending on queue depth and source length, which is exactly why the response in step 2 is a 202 Accepted with a polling/webhook status rather than a synchronous "video ready" response.

5.2 View counting at scale

Player Watch svc Kafka Aggregator DB 1. GET /watch?v=abc123 2. manifest + cached view count 3. after 30s watched: emit view event 4. consume, dedupe/bot-filter 5. window 5s → batch increment 6. UPDATE view_count += N 7. cache picks up new count on next TTL refresh

Step 3 is fire-and-forget from the player's perspective and only fires after a minimum watch duration threshold - a 2-second drive-by click never counts as a view. Steps 4-6 batch potentially thousands of individual view events into a single UPDATE per window per video, which is what makes 180,000 events/sec survivable; the visible view count on screen (step 7) is therefore always a few seconds stale by design, not a bug.

6. Entity-relationship (ER) diagram and schema

The schema has to answer: how is a channel's video list retrieved without a scan, how are views recorded without write-amplifying the hot videos row, and how are threaded comment replies modeled.

channels PK id BIGINT name VARCHAR subscriber_ct BIGINT created_at TIMESTAMP verified BOOLEAN videos PK id BIGINT FK channel_id BIGINT title VARCHAR duration_sec INT status ENUM view_count BIGINT published_at TIMESTAMP manifest_uri TEXT views PK id BIGINT FK video_id BIGINT viewed_at TIMESTAMP watch_secs INT comments PK id BIGINT FK video_id, parent_id BIGINT body, likes TEXT, INT 1N 1N 1N one channel has many videos; one video has many views and comments; a comment may self-reference a parent_id for threaded replies

Key modeling decisions

view_count is denormalized onto videosThe watch page needs it instantly on every load; it's updated in batches by the aggregator, never incremented synchronously per view.
views is append-only, sharded by video_id, time-partitionedRaw view events are kept briefly for fraud analysis and rolled up, then archived - they are not queried per-row at read time.
comments uses a self-referencing parent_idThreaded replies are modeled as an adjacency list; deeply nested threads are flattened to 1-2 levels in the UI to keep queries shallow.
NoSQL for views and comments at scaleBoth are high-volume, sharded-by-video_id, no-cross-row-transaction workloads that fit a wide-column or document store as well as a relational one.
Storage choiceUse whenWatch out for
Relational (Postgres/MySQL) for channels & videosComparatively low write volume, benefits from strong constraints and channel-video joins for the studio dashboard.Not designed for the view/comment write-fan-out of a viral video.
Wide-column/document (Cassandra/DynamoDB) for views & commentsAccess pattern is always "this video's events" at extreme, unpredictable write volume.Cross-video aggregate queries (trending, top creators) need a separate batch/OLAP pipeline.

7. Deep dives interviewers actually probe

Why can't a "view" ever be a direct database increment?

At ~180,000 views/sec peak, a naive UPDATE videos SET view_count = view_count + 1 per view would create row-lock contention concentrated on the handful of currently-viral videos, turning them into hot spots that slow down for everyone watching them at the exact moment they're most popular. Routing views through a stream and aggregating in time windows converts millions of tiny writes into a much smaller number of batched updates, and naturally smooths out bursts.

How do you stop bots and refresh-spam from inflating view counts?

The aggregator applies heuristics before a view counts at all: a minimum watch duration threshold (e.g. 30 seconds or a meaningful percentage of the video), session-level deduplication (the same viewer re-watching within a short window counts once), and signals like IP/device velocity and known bot user agents. None of this needs to be perfectly accurate in real time - it can be refined by an offline batch job that periodically reconciles and corrects counts.

How does a comment section survive a video going viral overnight?

Because comments are sharded by video_id, a flood of comments under one viral video only load-tests that video's shard, not the whole comments fleet. Pagination is cursor-based (by comment ID or timestamp, not offset) so deep pagination on a comment thread with millions of entries doesn't degrade into an expensive scan.

How is the personalized recommendation feed generated without recomputing it on every page load?

Recommendations are precomputed offline/near-real-time by a batch or streaming ML pipeline that consumes watch history and produces a ranked candidate list per viewer, cached and refreshed periodically (e.g. every few minutes to hours). The home page reads this precomputed list rather than running a ranking model synchronously per request, which would be far too slow and expensive at this read volume.

What is the single biggest bottleneck as this scales 10x?

Not playback - CDN edge and read replicas scale that horizontally. The real bottleneck becomes the view-counting aggregation layer during a global viral event (a single video watched by tens of millions within hours): the windowed aggregator for that one video_id's partition can become a hotspot even with batching. The fix is finer sub-partitioning of hot video_ids across multiple aggregator instances with a final merge step, not simply widening the batch window.

8. Summary: what a strong answer covers

Separated upload from playback from countingJustified every number with a calculationMade view counting async, batched, and approximate Sharded comments and metadata by video_idExplained bot/fraud filtering at the aggregatorCompared SQL vs wide-column honestly
Interview tip When asked to design YouTube, the strongest signal is treating "view count" as an approximate, eventually-consistent metric rather than a precise counter - explicitly naming the trade-off (a few seconds of staleness) in exchange for surviving viral-scale write bursts is exactly what separates a strong answer from one that quietly assumes a database can just absorb the load.
No comments
Leave a Comment