# Design Video Streaming

Course: [High-Level Design](https://www.devtutorials.ai/learn/system-design/hld) · Section: HLD Case Studies
Source: https://www.devtutorials.ai/learn/system-design/hld/case-studies/video-streaming

> Serve recipe videos: transcoding into qualities and segments, adaptive bitrate, chunked parallel transcoding and CDN delivery.

QuickBite is launching recipe videos. Restaurants can upload short cooking videos, and customers can watch them while deciding what to order. Some videos become extremely popular, especially during dinner hours when thousands of customers are browsing food options at the same time.

Video streaming is file storage taken to the extreme. A single video can be hundreds of megabytes in size, it must be processed before playback and it may be watched by tens of thousands of users at the same time. The biggest challenge is not storing the data. The biggest challenge is delivering enormous amounts of data efficiently.

**The main idea:** convert every uploaded video into multiple quality levels, split those videos into small segments, process them in parallel and serve the content through a CDN.

## What You Will Learn

In this case study, you will:

1. Write the requirements for video upload and playback.
2. Estimate storage requirements and bandwidth usage.
3. Understand transcoding, segmentation and adaptive bitrate streaming.
4. Improve transcoding speed through parallel processing.
5. Deliver video content efficiently through a CDN.
6. Build the architecture and test it under peak traffic conditions.

This lesson builds on File Storage, Estimation and Queues & Background Workers.

## Step 1: Requirements

Before designing the system, start by defining what it must do and how well it must do it.

### What It Must Do (Functional)

- Allow restaurants to upload recipe videos up to 20 minutes long.
- Allow customers to watch videos on any device.
- Support browsing and searching videos by restaurant and dish.
- Stream video smoothly during playback.
- Store video metadata and playback information.

### How Well It Must Do It (Non-Functional)

- Playback should start within about one second.
- Videos should continue playing even when network conditions change.
- Uploaded videos should become available within two minutes.
- The service should remain affordable despite heavy bandwidth usage.
- The platform should scale to support viral videos and traffic spikes.

These requirements immediately suggest that playback performance and bandwidth management are more important than database scalability.

## Step 2: Estimate

Good estimates reveal the real challenge before the architecture is designed.

Suppose QuickBite has approximately 40,000 viewers watching videos during peak dinner hours.

With an average of 2.5 Mbit/s each (a mix of 480p and 720p):

| Measure | At peak |
|---|---|
| Outgoing bandwidth | 40,000 × 2.5 Mbit/s = **100 Gbit/s** |
| Data sent each hour | **45 TB** |

What to notice:

- The platform must deliver about 100 Gbit/s of traffic.
- App servers should not be responsible for delivering that much video traffic.
- This is why video delivery should use a CDN.

Now consider storage.

QuickBite gets about 4,000 uploads a day. Each keeps the 600 MB original (a 10-minute phone video) plus about 450 MB for all the transcoded qualities. That is 1,050 MB per upload, or **4.2 TB of new storage a day**.

What to notice:

- Storage grows steadily over time.
- Object storage can handle this growth.
- Bandwidth is a much larger challenge than storage.
- Most design decisions exist to reduce bandwidth costs while keeping playback smooth.

## Step 3: Transcoding, Segments and Adaptive Bitrate Streaming

A phone usually records one large video file in a single quality.

That format is not ideal for a production video platform because users have different devices, network speeds and screen sizes.

To solve this, every uploaded video is transcoded into multiple versions such as:

- 240p
- 480p
- 720p
- 1080p

Each quality level uses a different bitrate and file size.

Lower qualities need less bandwidth and work on weaker connections. Higher qualities provide better visual quality for viewers with faster internet connections.

Each quality is then divided into small segments, usually around four seconds long.

A playlist file keeps track of every available quality and segment.

The player downloads the playlist first and then downloads segments one by one.

Adaptive bitrate streaming allows the player to adjust quality automatically.

Before downloading the next segment, the player measures network speed and chooses an appropriate quality.

For example:

- Fast connection → 1080p or 720p
- Medium connection → 480p
- Slow connection → 240p

The goal is simple: keep playback smooth.

A temporary drop in quality is much better than freezing the video. Step through a player whose network gets slower:

Here is the same idea in code:

```js runnable title="The player picks the best quality that arrives in time"
const ladder = [ // Mbit/s needed for each quality
  { name: "1080p", mbit: 5 },
  { name: "720p", mbit: 2.5 },
  { name: "480p", mbit: 1 },
  { name: "240p", mbit: 0.4 },
];

function pick(measuredMbit) {
  const safe = measuredMbit * 0.8; // keep 20% spare so playback does not stall
  return (ladder.find((q) => q.mbit <= safe) ?? ladder[ladder.length - 1]).name;
}

for (const speed of [12, 4, 1.5, 0.3]) console.log(`${String(speed).padStart(4)} Mbit/s -> ${pick(speed)}`);
```

Expected output:

```text
  12 Mbit/s -> 1080p
   4 Mbit/s -> 720p
 1.5 Mbit/s -> 480p
 0.3 Mbit/s -> 240p
```

## Step 4: Make Transcoding Fast

Transcoding is one of the most expensive tasks in the system.

Suppose one transcoder needs five minutes to process a ten-minute video into all required qualities.

QuickBite requires videos to become available within two minutes.

The solution is to split the video into smaller chunks.

For example:

- A 10-minute video contains 600 seconds.
- Split it into 10-second chunks.
- Create 60 independent transcoding jobs.

Multiple workers can process those chunks at the same time.

With 32 transcoder jobs running at once, the 60 chunks finish in 2 rounds of 5 seconds each. The chart compares that with one transcoder.

The total amount of work stays the same, but it finishes much faster because many workers share the workload.

This follows the same queue-and-worker pattern used in earlier lessons:

1. A restaurant uploads a video.
2. A transcoding job is created.
3. The job goes into a queue.
4. The video is split into chunks.
5. Workers process chunks in parallel.
6. Processed segments are saved for playback.

Large video files should be uploaded directly to object storage using a presigned URL. The API only stores metadata and creates transcoding jobs. A 600 MB upload should never pass through an application server.

## Step 5: Deliver Videos Through a CDN

Video segments rarely change after they are created.

Popular videos are watched repeatedly, making them ideal for caching.

A CDN stores copies of video segments close to viewers.

Instead of every request reaching object storage, most requests are served directly by edge servers. Step through what happens at the dinner peak:

What to notice:

- Most requests are served by the CDN.
- Object storage receives only a small fraction of requests.
- Latency decreases because content is closer to viewers.
- Costs stay lower because backend systems handle less traffic.

Without a CDN, bandwidth costs and backend traffic grow with every viewer. A CDN is a requirement, not an optional optimization.

## Step 6: Build It on the Canvas and Test It

Open the **design sandbox**.

The canvas starts with:

- 2 load balancers
- 6 video API servers
- Object storage
- A database
- No CDN
- No transcoders

The simulator sends:

- 40,000 segment downloads per second
- 2,000 API requests per second
- 3 new 10-minute uploads every minute

| Check | Passes when |
|---|---|
| Peak load | p99 at most 100 ms, under 0.1% errors, enough transcoders, and new videos ready within 2 minutes |
| Lose any one machine | Any one load balancer, API server, database copy or transcoder dies. Errors under 1%, p99 under 250 ms, and transcoding keeps up |
| Cost | At most $1,500 a month |
| Requirements | Uploads go through a queue to transcoders, which write to object storage |

Run the starting design first.

Then add:

- A CDN between phones and object storage.
- A queue for transcoding jobs.
- Transcoding workers.

Try both transcoding modes and compare the results.

What you will probably find:

- Without a CDN, application servers become overloaded very quickly.
- Whole-video transcoding is too slow to meet the two-minute target.
- Too few transcoders create a processing backlog.
- Additional transcoders improve reliability.

A design that passes:

- 2 load balancers
- 2 video API servers
- Object storage
- CDN
- 2 database copies
- Queue
- 4 transcoding workers

This design costs about **$1,460 per month** and keeps p99 latency around **32 ms**.

## Common Mistakes

| Mistake | Wrong | Correct | Why It Happens |
|---|---|---|---|
| Serving original uploads | Users download raw recordings directly | Transcode into multiple qualities and segments | Original files work during small-scale testing |
| Fixed video quality | One quality is selected for the entire session | Adaptive bitrate streaming | Network changes are often ignored during design |
| Whole-video transcoding | One worker processes an entire video | Split into chunks and process in parallel | Simpler implementation |
| No CDN | Backend serves every segment | Serve segments through a CDN | Bandwidth costs are underestimated |
| Uploading through servers | Large files pass through API servers | Upload directly to object storage | Existing request paths seem easier |

## Practice

## What to Remember

- Video platforms are primarily bandwidth problems.
- Every upload should be transcoded into multiple quality levels.
- Videos should be split into small segments.
- Adaptive bitrate streaming allows quality to change during playback.
- Chunk-based transcoding greatly reduces processing time.
- Upload large files directly to object storage.
- Use queues and workers for video processing.
- Serve video segments through a CDN.
- Most scaling decisions are driven by bandwidth rather than storage.

## Further Reading

These are the sources this lesson was checked against:

- [Apple: HTTP Live Streaming (HLS)](https://developer.apple.com/streaming/): playlists, segments and quality ladders.
- [Netflix Tech Blog: Per-title encode optimization](https://netflixtechblog.com/per-title-encode-optimization-7e99442b62a2): choosing the quality ladder for each video.
- [MDN: Media Source Extensions](https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API): how web players feed segments to the video element.

Next: **LLM Inference Serving**, where QuickBite runs an AI support assistant using GPUs.
