Design problems
Media & streamingHardSDE-2 40 min

Design YouTube

Asked at
AmazonGoogleJioHotstarMetaNetflixShareChat

The interviewer asks

“Design YouTube: creators upload videos of any length, the platform processes them, and billions of viewers around the world watch them smoothly on any device and network. Cover upload, processing, playback and view counts.”

What a strong answer looks like

A strong answer splits YouTube into a write path and a read path with very different shapes. The write path is a resumable upload to object storage followed by an asynchronous processing pipeline: split the video into chunks, transcode them in parallel into a bitrate ladder (144p to 4K, H.264 plus VP9/AV1), package as HLS/DASH segments, run moderation, and publish. The read path is dominated by bandwidth: ~100 Tbps of video served almost entirely from CDN and ISP-embedded caches using adaptive bitrate streaming, while the origin serves only metadata, manifests and cache misses. Metadata lives in sharded MySQL (YouTube built Vitess for exactly this) with heavy caching, and view counts are aggregated in streams rather than incremented per view. The deep dives are the transcoding pipeline, ABR plus CDN tiering, metadata scaling, and view counting.

Concepts to mention

Resumable chunked uploads to object storageSplit into GOP-aligned chunks and transcode in parallelBitrate ladder and multiple codecs (H.264, VP9, AV1)HLS/DASH packaging with CMAF segmentsAdaptive bitrate streamingCDN tiers, ISP caches and origin shieldSigned URLsSharded MySQL (Vitess) with a read-heavy cacheCounters separate from metadataStream aggregation of view events with fraud filteringPopularity-driven encoding

1 Requirements

Functional

  • Creators upload videos (up to 12 hours / 256 GB) with resumable uploads
  • Process uploads into multiple resolutions and formats and generate thumbnails
  • Viewers watch with adaptive quality that adjusts to their network
  • Video page: title, description, channel, likes, view count, comments
  • Search and a home feed of recommendations (high level only)
  • Creators see processing status and basic analytics (views, watch time)

Non-functional

  • Scale: ~500 hours of video uploaded per minute; ~1B hours watched per day
  • Playback start time < 2 s p90; rebuffering ratio < 0.5% of watch time
  • Uploads never lost once acknowledged; processed video durable (11 nines)
  • Standard-definition renditions available within minutes of upload; HD shortly after
  • Video page metadata API < 100 ms p99; 99.99% availability for playback
  • Work on 2G/3G-class networks in Tier-2/3 India (144p/240p, small segments)

Out of scope (say it out loud)

  • Recommendation model internals (treat as a service that returns video ids)
  • Ads insertion and monetisation
  • Live streaming (separate design)
  • Copyright matching (Content ID) internals

2 Estimates

Upload volume~720k hours/day500 hours/min × 1,440 min/day
Raw upload ingest~1.5 PB/day (~140 Gbps)720k hours × ~2 GB/hour average original (phone 1080p is 2-4 GB/hour, many uploads are smaller)
Stored after transcoding~1.5-2 PB/day moreFull ladder (144p-1080p, some 4K) in H.264 and VP9 adds roughly 1-1.5x the original size; AV1 is added later for popular videos only
Transcoding compute~100k+ CPU cores busySoftware encoding at ~1-2 CPU-hours per video-hour per rendition set; 720k hours/day ÷ 24 ≈ 30k video-hours per hour, × several codecs. Hardware encoders (Google uses custom VCU chips) cut this a lot.
Viewing egress~100 Tbps average1B hours × 3,600 s × ~2.5 Mbps ÷ 86,400 s ≈ 1.0 × 10^14 bit/s
Concurrent viewers~40M1B watch-hours/day ÷ 24 hours
Segment requests~10M/s (almost all at CDN)40M viewers ÷ one ~4 s segment each
Metadata reads~100k-300k/s~5B video views/day ÷ 86,400 ≈ 58k/s video pages, plus feed, search and thumbnails metadata; ×3 peak

3 API

EndpointWhat it does
POST/v1/uploadsStart a resumable upload session; returns upload_id and upload URL
PUT/v1/uploads/{upload_id}Upload a chunk with Content-Range; the client resumes from the last acknowledged byte after a drop
POST/v1/videosCreate the video record: title, description, visibility, upload_id
GET/v1/videos/{id}Video page metadata: title, channel, counts, available renditions
GET/v1/videos/{id}/playbackReturns signed manifest URLs (DASH/HLS) and the CDN host chosen for this client
GEThttps://cdn…/{id}/{rendition}/seg_{n}.m4sMedia segment fetched directly from the CDN
POST/v1/events/watchBatched playback events (start, progress every N seconds, quality switches, rebuffer)
GET/v1/videos/{id}/statusProcessing status for the creator

4 Data model

videosMySQL sharded with Vitess
video_id (PK, random 11-char id)channel_idtitledescriptiondurationstatus (uploading/processing/ready/blocked)visibilityrenditions (list)thumbnail keyscreated_at

Sharded by video_id; a secondary lookup table (channel_id → video_ids) serves channel pages. Hot rows cached in Memcached/Redis.

channelsMySQL (Vitess)
channel_id (PK)owner_user_idnamesubscriber_count (approximate)settings

Small and relational.

raw uploadsObject storage (GCS/S3)
key = upload_idoriginal filechecksum

Kept for re-encoding with new codecs later; moved to colder storage classes over time.

segmentsObject storage + CDN
key = video_id/codec_resolution/seg_n.m4splus manifest.mpd / master.m3u8

Immutable files, so they cache perfectly. Popular videos live in edge caches; the long tail is fetched from origin on demand.

view_countsBigtable/Cassandra counters + Redis
video_idtotal_viewslikes; per-hour buckets for analytics

Updated by stream aggregation in batches, not per view.

watch_eventsKafka → data warehouse (BigQuery/ClickHouse)
user_idvideo_idsession_idpositionevent_typebitratets

Feeds view counting, creator analytics, recommendations and QoE dashboards.

commentsBigtable / Cassandra
video_id (partition)comment_id (time-ordered)user_idtextparent_idlike_count

Partitioned by video; very popular videos need paging and ranking (top comments) precomputed.

5 Architecture

CLIENTSEDGESERVICESASYNCDATAAPI callssegments (ABR)resumable chunksstore originalUploadCompletedread chunkswrite renditionsmark readyvideo pageget manifestrenditionscache misswatch eventsbatched countsViewer / creator appsCDN + ISP edge cachesAPI gatewayUpload serviceWatch eventscollectorVideo metadataservicePlayback serviceKafkaTranscode DAG workersModeration + ContentIDView aggregation(Flink)Raw upload storageSegment storage(origin)Vitess MySQL + cacheCounters (Bigtable)
ClientEdge / gatewayService / workerQueue / streamCacheDatabase / storageAI / modelThird partyrequestasync (event / queue)

Hover a box to highlight its connections.

6 Request flows

Upload and process a video

  1. 1The creator app calls POST /uploads and gets an upload session; it uploads in 8-16 MB chunks with Content-Range so a dropped mobile connection resumes instead of restarting.
  2. 2The upload service writes chunks to object storage, verifies the final checksum, creates the video row with status=processing and publishes UploadCompleted to Kafka.
  3. 3The transcode orchestrator builds a DAG: probe the file, split it into ~10-second chunks at keyframe (GOP) boundaries, encode each chunk for each rendition in parallel, then merge and package.
  4. 4Low resolutions (144p-480p H.264) get the highest priority so the video can go live within minutes; 1080p/4K and VP9 follow; AV1 is produced later only if the video becomes popular.
  5. 5In parallel, thumbnails are extracted, audio is normalised, captions are auto-generated, and moderation and copyright matching run.
  6. 6The packager writes CMAF segments plus DASH and HLS manifests to segment storage.
  7. 7When the minimum ladder and moderation pass, the metadata service flips status to ready (or blocked) and notifies the creator and subscribers.

Watch a video

  1. 1The app fetches /videos/{id} (metadata from cache) and /videos/{id}/playback, which returns a signed manifest URL on a CDN hostname chosen for the user's ISP and location.
  2. 2The player downloads the manifest listing renditions (e.g. 144p at 100 kbps up to 1080p at 5 Mbps).
  3. 3It starts with a low-to-medium bitrate to start fast, fetching ~2-4 s segments from the nearest edge (often a cache inside the user's ISP).
  4. 4The ABR algorithm watches throughput and buffer level, switching up when the buffer is healthy and down before it empties.
  5. 5On a cache miss, the edge fetches from a regional mid-tier cache (origin shield), and only then from origin storage.
  6. 6The player batches watch events (started, progress every 30 s, rebuffer) and sends them to the events collector.

Count a view

  1. 1Watch events land in Kafka partitioned by video_id.
  2. 2A Flink job filters invalid views (bots, repeated reloads, too-short watches) using per-user/per-IP state.
  3. 3It aggregates valid views per video in 10-30 s windows and writes increments to the counters store.
  4. 4The video page reads the total from a cache; counts may lag a few seconds to minutes, which is acceptable.

7 Deep dives

The transcoding pipeline as a parallel DAG

Encoding a 2-hour 4K video serially into ten renditions would take many hours. Instead, the orchestrator splits the source into independent chunks at keyframe (GOP) boundaries, typically a few seconds to tens of seconds each, and encodes every (chunk, rendition) pair as a separate task across thousands of workers. A merge step concatenates the encoded chunks and a packager produces CMAF segments with DASH and HLS manifests. Model it as a DAG in a workflow engine (Temporal or an internal scheduler) so each task is retried independently, progress is checkpointed, and a worker crash costs one chunk, not the whole video. Prioritise: produce 360p first so the video is watchable within minutes, then higher resolutions. Spend compute where it pays off: every upload gets H.264 for compatibility and VP9 for mid-popularity, but AV1 encoding is expensive and is done only after a video crosses a view threshold, because the bandwidth saving (~30% vs VP9) only matters when many people watch. Workers should be spot/preemptible instances, since tasks are idempotent and short. Keep the original upload so you can re-encode the catalogue when a better codec arrives.

Adaptive bitrate streaming and CDN tiering

Video is cut into short segments (2-6 s) available at several bitrates. The player picks the next segment's bitrate from measured throughput and buffer health (buffer-based algorithms like BOLA work well on noisy mobile networks). Short segments react faster but add request overhead; 2-4 s is a common balance. Because segments are immutable files with stable URLs, they cache perfectly. Delivery is tiered: edge caches inside ISPs (Google Global Cache, Netflix Open Connect style), regional PoPs, a mid-tier origin shield, and finally origin storage. Head content (the top few percent of videos, which draw most views) is almost always served from the edge; the long tail is fetched on demand and may come from a regional tier with slightly higher start time. The playback service steers each client to a good CDN node by IP, ISP and node load, and signs URLs with a short expiry so links cannot be hot-linked forever. For India, publishing low rungs (144p at ~80-100 kbps, 240p) and starting at a conservative bitrate cuts startup failures on congested networks.

Metadata at scale: sharded MySQL and caching

Video metadata is small (a few KB per video) but read very often. YouTube scaled MySQL by building Vitess, which shards tables transparently, routes queries by a keyspace id, and handles resharding and connection pooling. Shard videos by video_id so reads are spread evenly; channel pages use a secondary table keyed by channel_id. Put a cache (Memcached/Redis) in front: the read/write ratio is extreme (a video is written a few times and read millions of times), so a 95%+ hit rate is normal. Do not store fast-changing counters (views, likes) in the same row: they would cause write hot spots and cache invalidation storms. Keep them in a separate counters store and merge them in the API layer. Video ids are random (not sequential) so new uploads do not all land on one shard and ids cannot be enumerated.

View counting without a write per view

Incrementing a database counter on each view is ~60k writes/s on average with extreme hot keys: a viral music video can get 50k views/s on one row. Instead, the player sends watch events to a collector, events go to Kafka partitioned by video_id, and a stream processor (Flink) validates and aggregates them. Validation matters because view counts drive money and ranking: a view counts only after a minimum watch time, repeated reloads by the same user or IP within a window are dropped, and known bot patterns are filtered. The aggregator flushes per-video sums every 10-30 seconds, turning millions of events into thousands of writes. For a super-hot video, pre-aggregate inside each partition and shard the counter (several sub-counters summed on read). The public count can be eventually consistent; YouTube itself has historically frozen or delayed counts while validating suspicious spikes. Exact numbers for creator payouts are computed later in batch from the warehouse.

8 Trade-offs

Encode everything up front vs on demand

Encoding every rendition and codec for every upload wastes compute: most videos get few views. Encode a baseline ladder for all and add expensive codecs (AV1, 4K HDR) only when popularity justifies it. The trade is slightly worse quality-per-bit for long-tail videos in exchange for large compute savings.

Segment length

2 s segments adapt quickly and start faster but mean more requests and worse compression (more keyframes). 6-10 s segments are efficient but adapt slowly on mobile. 2-4 s is a good default for VOD.

Own CDN vs commercial CDN

At ~100 Tbps, placing your own caches inside ISPs is far cheaper and faster than paying per GB, and ISPs welcome it because it cuts their transit. A smaller platform should start with commercial CDNs and multi-CDN steering.

Exact vs approximate public counts

Exact real-time counts need transactional increments on hot rows. Approximate, slightly delayed counts from stream aggregation scale easily and allow fraud filtering first. Creator payouts use exact batch numbers.

9 Bottlenecks

Viral video or premiere spike

A sudden spike causes many simultaneous edge misses for the same segment. Request coalescing at the edge and the origin shield (one upstream fetch, many waiters) plus pre-warming edges for scheduled premieres keep origin load flat.

Transcoding backlog

Upload peaks (evenings, festivals) can outgrow the encoding fleet. Autoscale on queue depth with spot instances, prioritise low renditions and partners, and let high renditions catch up later.

Storage growth

Petabytes per day accumulate forever. Move old originals and rarely watched renditions to colder storage classes, delete renditions that can be regenerated, and use erasure coding instead of 3x replication.

10 Failure handling

Transcode worker dies mid-task

The workflow engine notices the missed heartbeat and reschedules that chunk task on another worker. Outputs are written to deterministic keys, so a retried task simply overwrites; the video is delayed by seconds, not reprocessed.

CDN node or PoP fails

The playback service and DNS steer clients to the next-best node; players retry a failed segment against an alternate host listed in the manifest. Viewers may see one quality drop, not an error.

Metadata database shard down

Serve video pages from cache (slightly stale) while Vitess fails over to a replica. Playback of already-started videos is unaffected because segments come from the CDN.

Upload interrupted

Resumable uploads keep acknowledged byte ranges; the client queries the session and continues from the last offset. Incomplete sessions expire after a few days.

11 What impresses

  • Does the bandwidth estimate (~100 Tbps) and concludes the CDN is the system
  • Explains chunked parallel transcoding as a DAG with per-task retries
  • Encodes expensive codecs only for popular videos and explains why
  • Separates hot counters from video metadata and aggregates views in a stream
  • Mentions request coalescing and origin shield for viral spikes
  • Designs for low-bandwidth Indian networks with low ladder rungs and conservative start

12 Mistakes

  • Serving video bytes from application servers
  • Transcoding synchronously in the upload request
  • Single-file progressive download with no adaptive bitrate
  • Incrementing a database row for every view
  • Ignoring storage and compute cost of encoding every format for every upload
  • Forgetting resumable uploads for multi-GB files on mobile networks

13 Follow-ups

Q1How would you add live streaming to this design?
Q2How do you implement 'resume where you left off' across devices?
Q3How does the CDN decide what to evict, and how do you pre-warm for a premiere?
Q4How would you detect and prevent fake views?
Q5How do you add subtitles in 10 Indian languages?
Q6How would you design the search index for video titles and transcripts?
Q7How would you handle a takedown request so the video stops playing everywhere within minutes?

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free