Fun with Learning Technology
LearnCoursesQuestionsTracksToolsNewsExplorePractice
Fun with Learning Technology

A new problem, explained clearly, every day.

Subscribe
Learn
  • Lessons
  • Topics
  • News
  • Tools
  • Courses
  • Career tracks
  • Everything
Site
  • About
  • Contact
  • Support
  • Privacy
  • Terms
Get the daily one

One email per new problem. No spam.

Request a tutorial

Requests shape what gets made next.

© 2026 Fun with Learning TechnologyRSS
Home›Courses›System Design›Design Video Streaming (YouTube)

Classic Design Problems

Design Video Streaming (YouTube)

Video streaming architecture is a high-bandwidth, latency-sensitive system designed to deliver massive media files to geographically distributed clients. It matters because it balances the storage of petabytes of data with the need for smooth playback under variable network conditions. You reach for this design when building content delivery platforms, video conferencing tools, or any application requiring adaptive bitrate streaming at scale.

Ingestion and Transcoding Pipeline

The ingestion process begins by receiving raw video files from users, which are immediately stored in an object store to ensure durability. Because users upload files in various formats and resolutions, we must employ a transcoding pipeline to convert these raw files into multiple output formats like MP4 or DASH, each tailored for different network speeds and device capabilities. The core reasoning behind this is the 'Adaptive Bitrate' requirement: the client needs to seamlessly switch between low-resolution and high-resolution streams based on their current network congestion without stalling. By creating multiple representations of the same video upfront, we offload the processing burden from the request path. We use a task queue to decouple the upload from the transcoding service, ensuring that the system can handle bursts of traffic without failing. This approach ensures that the primary storage is decoupled from the compute-intensive transcoding tasks, leading to better scalability and fault tolerance throughout the ingestion pipeline.

def transcode_video(raw_file_id, resolutions=['360p', '1080p']): 
    # This function mocks a transcoding job submission to a worker pool
    # In a real system, this adds a message to a distributed queue like RabbitMQ
    for resolution in resolutions:
        job = {'id': raw_file_id, 'target': resolution}
        print(f'Submitting {raw_file_id} for transcoding to {resolution}')
    return 'Job Queued'

Efficient Media Storage Strategy

Storing raw video files is cost-prohibitive and inefficient for retrieval, so we must utilize a hierarchical storage strategy. Original source files should be moved to cold storage after transcoding to reduce costs, while the processed segments are stored in high-performance block storage or highly available object stores. We organize these segments into chunks, typically between 2 to 10 seconds in duration. This chunking strategy is vital because it allows the client to fetch small, manageable pieces of the video rather than the whole file at once. By requesting only the next few segments, the client maintains a small buffer, which is critical for quick start times and minimal wasted bandwidth if the user stops watching. We use a metadata database to track the locations of these chunks, effectively mapping a video ID to a set of URI endpoints. This separation between the metadata layer and the raw media blob storage allows us to scale read operations horizontally across multiple storage clusters.

class StorageMapper:
    def __init__(self):
        self.manifests = {} # Maps video_id to chunk locations

    def add_segment(self, video_id, chunk_id, url):
        # Stores the location of specific segments for retrieval
        if video_id not in self.manifests:
            self.manifests[video_id] = {}
        self.manifests[video_id][chunk_id] = url
        print(f'Added segment {chunk_id} for {video_id}')

Content Delivery Network (CDN) Integration

To deliver video content to a global audience, the latency between the user and the storage server must be minimized. We accomplish this by deploying a Content Delivery Network (CDN) that acts as an edge caching layer. When a user requests a video segment, the system directs them to the nearest CDN edge node instead of the origin server. If the edge node already contains the requested chunk, it serves the data directly, significantly reducing round-trip time. If the data is missing (a cache miss), the edge node fetches it from the origin, caches it for future requests, and delivers it to the user. This strategy works because video segments are immutable, meaning they never change once created, making them perfect candidates for long-term caching. By delegating the delivery to geographic edge nodes, we offload the bulk of the traffic from the core infrastructure and ensure the user experiences smooth playback regardless of their physical location relative to the data center.

def get_content(user_location, chunk_id):
    # Simulate routing to the nearest edge node based on IP/Location
    edge_node = find_nearest_node(user_location)
    if edge_node.has_cached(chunk_id):
        return edge_node.serve(chunk_id)
    else:
        data = fetch_from_origin(chunk_id)
        edge_node.cache(chunk_id, data)
        return data

Adaptive Bitrate Streaming Logic

Adaptive Bitrate (ABR) streaming is the mechanism that dynamically adjusts the video quality based on the user's available bandwidth. The client device constantly monitors the download speed and the state of its playback buffer. If the network becomes congested, the client will intelligently request the next video segments from a lower resolution manifest. Conversely, when the network throughput increases, it will switch to a higher quality stream to provide a better viewing experience. This logic is implemented on the client-side, but it requires the server to provide a manifest file that lists all available qualities for each segment. The reasoning here is that by empowering the client to make these decisions, the server remains stateless and can handle a significantly higher number of concurrent connections. This decentralization of the decision-making process is the primary reason high-scale video platforms can remain stable during fluctuating network conditions, effectively mitigating the 'buffering' issue users hate.

def select_bitrate(buffer_health, network_speed):
    # A client-side logic heuristic to choose the next quality level
    if buffer_health < 5 and network_speed < 2.0:
        return '480p' # Switch to low quality to save buffer
    elif network_speed > 10.0:
        return '1080p' # Upscale if bandwidth is healthy
    return '720p'

System Monitoring and Analytics

For a system of this magnitude, monitoring isn't just about server uptime; it is about tracking the Quality of Experience (QoE). We must capture metrics such as re-buffering ratio, start-up delay, and average bitrate to identify performance bottlenecks. These metrics are sent as periodic heartbeats from the client to an analytics aggregator. The data is processed in real-time to alert engineers if a specific geographic region or CDN node starts reporting high failure rates. By analyzing these logs, we can identify patterns like peak usage hours or common device issues, allowing us to proactively adjust our CDN caching policies or upgrade infrastructure in underperforming areas. The key to this feedback loop is the use of distributed logging and time-series databases, which allow us to store high-cardinality data and run complex queries over millions of playback sessions to ensure that the streaming experience remains consistent across the entire user base.

import time

def report_qoe_metric(video_id, event_type, duration_ms):
    # Logs playback metrics to a collector for real-time analysis
    timestamp = time.time()
    metric = {'id': video_id, 'event': event_type, 'latency': duration_ms, 'ts': timestamp}
    # Send to an ingestion service like Kafka for real-time processing
    print(f'Sending QoE data: {metric}')

Key points

  • Transcoding raw uploads into multiple bitrates enables the client to adapt to fluctuating network speeds.
  • Chunking video files into short segments allows for efficient caching and lower initial latency during playback.
  • Using a CDN edge network is essential to minimize the physical distance data must travel to reach the user.
  • The client-side handles bitrate selection, which keeps the server-side architecture stateless and highly scalable.
  • Separating video metadata from the raw media storage allows for independent scaling of query and delivery services.
  • Immutability of video chunks simplifies the caching strategy, as segments never need to be invalidated.
  • Monitoring Quality of Experience metrics is vital for detecting and resolving regional playback issues in real time.
  • Decoupling the ingestion pipeline via asynchronous task queues ensures system stability during high-traffic upload bursts.

Common mistakes

  • Mistake: Designing for a monolithic storage system. Why it's wrong: YouTube handles exabytes of data; a single database cannot scale. Fix: Use object storage like S3 for raw videos and distributed databases like Cassandra/Bigtable for metadata.
  • Mistake: Encoding videos on the fly while the user watches. Why it's wrong: Real-time encoding is too slow for 4K video, causing buffering. Fix: Use an asynchronous task queue to pre-encode videos into multiple bitrates/resolutions.
  • Mistake: Storing all video chunks on a single web server. Why it's wrong: This creates a single point of failure and extreme network congestion. Fix: Utilize a Content Delivery Network (CDN) to cache chunks geographically closer to users.
  • Mistake: Over-relying on a single database for all metrics. Why it's wrong: Analytics (views, likes, watch time) generate massive write traffic that locks traditional RDBMS. Fix: Use a distributed stream processing platform like Kafka to ingest logs and batch-write to analytical storage.
  • Mistake: Ignoring video chunking in the streaming protocol. Why it's wrong: Sending a large file as one stream prevents efficient seeking and adaptive bitrate switching. Fix: Split videos into smaller temporal segments (e.g., 5-10 seconds) for DASH/HLS streaming.

Interview questions

What are the core functional requirements for designing a platform like YouTube?

To design a video streaming platform, we must focus on three primary functional pillars. First, users need to upload videos, which involves storage and transcoding. Second, users need to view videos, requiring efficient streaming protocols. Third, we need support for user interactions, such as commenting, liking, and subscribing. These requirements drive our choice of architecture: we need a robust object storage service for raw files and a content delivery network to minimize latency for global viewers. We must also design for eventual consistency regarding view counts and comments to ensure the system remains performant under high read-heavy loads.

How would you handle the storage and transcoding of videos once they are uploaded?

When a user uploads a video, we first store the raw file in a highly durable object store like S3. However, raw files are unsuitable for streaming due to bitrate and codec variations. We trigger a transcoding job using a distributed task queue like RabbitMQ or Kafka. Transcoding workers convert the video into multiple resolutions (e.g., 480p, 1080p, 4K) and formats (e.g., HLS or DASH). We save these chunks in the object store. This is crucial because it allows the client to adaptively stream based on network conditions, switching resolutions dynamically to prevent buffering.

Compare the use of HLS (HTTP Live Streaming) versus DASH (Dynamic Adaptive Streaming over HTTP) for video delivery.

Both HLS and DASH are adaptive bitrate streaming protocols that operate over standard HTTP. HLS, developed by Apple, is widely supported by iOS devices and uses an .m3u8 playlist format to define segments. DASH is an open-standard, codec-agnostic protocol that uses .mpd files, offering more flexibility for different containers. We would choose HLS if our primary audience is mobile-heavy, whereas DASH is superior for cross-platform compatibility and proprietary codec support. In a system design context, both mitigate latency by allowing the client to request small sequential file segments rather than one massive stream, reducing server-side state complexity.

How would you optimize video delivery globally to minimize latency?

Global latency is addressed through the implementation of a Content Delivery Network (CDN). We cache processed video segments at edge locations geographically closer to the end-user. When a request hits, the DNS routes the user to the nearest edge server. If the segment isn't there, the edge server fetches it from the origin storage. By offloading static content delivery to a CDN, we protect our core infrastructure from massive traffic spikes. We can also implement intelligent caching policies, prioritizing popular videos for longer retention at the edge to ensure the fastest possible startup time for trending content.

How do you manage the database schema to handle massive scale for video metadata?

For video metadata, we require a database that handles heavy read operations while maintaining scalability. I would use a sharded relational database or a NoSQL database like Cassandra. We shard by 'user_id' or 'video_id'. A sample metadata schema would include: VideoTable {video_id: UUID, user_id: UUID, title: String, description: Text, created_at: Timestamp, file_path: URL}. Because we have millions of requests, we would use a read-replica architecture or a caching layer like Redis to serve frequently accessed metadata, such as view counts or titles, effectively reducing the pressure on our primary write-master node and ensuring low-latency retrieval for the user interface.

Design the system architecture for handling viral video spikes to prevent site crashes.

To prevent crashes during a viral event, we must decouple components. We use a load balancer to distribute traffic across a horizontal auto-scaling group of web servers. When a video goes viral, we rely heavily on the CDN to cache the video segments so they never touch our backend storage. For view counts, which update constantly, we use a message queue like Kafka; instead of writing every single view to the database instantly, we aggregate the views in memory and perform periodic bulk writes to the database. This approach follows the principle of asynchronous processing, which keeps the system responsive even when millions of users are interacting with the same video simultaneously.

All System Design interview questions →

Check yourself

1. When designing the video processing pipeline, what is the primary benefit of pre-encoding videos into multiple resolutions and bitrates?

  • A.To reduce the total storage space occupied by the raw video file
  • B.To enable Adaptive Bitrate Streaming, allowing the player to switch quality based on network conditions
  • C.To ensure the video can be encrypted before being moved to the CDN
  • D.To eliminate the need for a Content Delivery Network entirely
Show answer

B. To enable Adaptive Bitrate Streaming, allowing the player to switch quality based on network conditions
Adaptive Bitrate Streaming allows a seamless experience even if bandwidth fluctuates; the others are incorrect because pre-encoding increases total storage, doesn't handle encryption specifically, and makes CDNs more, not less, necessary.

2. Which of the following describes the most efficient way to handle high-frequency view count updates in a global system?

  • A.Increment the value directly in the primary relational database with each view event
  • B.Use a distributed cache to aggregate increments and periodically flush them to persistent storage
  • C.Send every view event through a synchronous REST API call to the metadata service
  • D.Store the view count only on the client side to minimize server-side state
Show answer

B. Use a distributed cache to aggregate increments and periodically flush them to persistent storage
Caching and batching updates prevents database write contention. The other methods fail due to high latency, database locks, or lack of data integrity.

3. Why is it necessary to split long videos into smaller chunks (e.g., 5-second segments) for streaming?

  • A.To ensure the browser can cache the entire video file locally before playing
  • B.To reduce the compression overhead of the video codec
  • C.To allow the client to request specific segments, enabling fast seeking and dynamic bitrate switching
  • D.To make it easier to upload the file to a relational database
Show answer

C. To allow the client to request specific segments, enabling fast seeking and dynamic bitrate switching
Chunking is essential for HTTP-based streaming protocols (DASH/HLS) to enable granular control. Caching the whole file is inefficient, codecs work on frames regardless of chunking, and databases are not for blob storage.

4. What is the primary role of a CDN in a video streaming architecture?

  • A.To perform heavy transcoding operations before the video is stored
  • B.To provide a backup of the user's authentication and account profile data
  • C.To cache video chunks at edge locations to minimize latency and offload traffic from the origin server
  • D.To handle user comments and real-time chat during live streaming
Show answer

C. To cache video chunks at edge locations to minimize latency and offload traffic from the origin server
CDNs are for caching content geographically near users. Transcoding, auth, and chat management are handled by dedicated backend microservices, not the CDN.

5. In a distributed storage system for raw video files, what is the advantage of using object storage over a traditional file system on an application server?

  • A.Object storage supports ACID transactions, which are required for video editing
  • B.Object storage provides better horizontal scalability and is designed to handle massive volumes of unstructured data
  • C.Object storage allows for real-time querying of video frames using complex SQL joins
  • D.Object storage automatically transcodes video files into different formats upon upload
Show answer

B. Object storage provides better horizontal scalability and is designed to handle massive volumes of unstructured data
Object storage is highly scalable and suited for static large blobs. The others are false because object storage lacks transactional locks, does not support SQL joins, and does not perform transcoding.

Take the full System Design quiz →

← PreviousDesign Ride-Sharing (Uber)Next →System Design Interview Tips

System Design

31 lessons, free to read.

All lessons →

Track your progress

Sign in to mark lessons done, score quizzes and keep notes.

Open in the app