Course Content
Mobile System Design Interview
11 sections · 23 lessons
YouTube: requirements, adaptive bitrate and fast start
Prompt: "Design a video streaming app — a YouTube or Netflix client."
The capstone. It touches nearly every building block from Section 3: transports, caching, prefetch, background limits, storage budgets, resumable transfer, and observability. It also introduces the one thing no other case study has — a hard real-time deadline. A feed that renders 200 ms late is fine. A video decoder that misses its deadline stutters, and the user sees it.
This lesson scopes the problem and designs the two mechanisms that keep a picture on screen over a mobile network: adaptive bitrate and the buffer. The next covers the playback session, offline downloads and the follow-ups.
The questions worth asking
"Playback only, or upload too?" Take playback. Upload is the resumable-transfer problem from the Google Drive app with a transcoding wait bolted on, and it will crowd out the interesting material. Say that reasoning out loud rather than avoiding it.
"Offline downloads?" Yes, and ask whether downloads are licensed content with expiry or plain files. Licensed content brings digital rights management, encrypted storage, and licence renewal, which is a substantial part of a real design.
"Live streams?" Ask specifically. Live is a genuinely different buffer problem — a small buffer to keep latency low, against a large one to survive network variation — and it is worth covering as a follow-up rather than as the main case.
"Background audio and picture-in-picture?" Both, ask. They drive the session model in Client architecture and they are where platform knowledge shows.
"Which quality levels, and what is the default on cellular?" This is the question with the biggest user-visible consequence, because it is the user's money.
The scope to state back
In scope: adaptive-bitrate playback with fast start, a browse surface with prefetch, offline downloads with storage management, background audio, and picture-in-picture.
Out of scope: upload and transcoding, the recommendation system, the content delivery network's design, and comments. Design YouTube in System Design Interview covers the server and delivery side.
Requirements and constraints
Functional requirements
- Play a video with a fast start and no rebuffering.
- Adapt quality automatically to available bandwidth, with a manual override.
- Download videos for offline playback, with a chosen quality.
- Continue audio when the app is backgrounded, and support picture-in-picture.
- Resume a partially watched video at the right position, across devices.
- Manage downloaded content and see what it is using.
The non-functional targets
| Target | Value | Why |
|---|---|---|
| Time to first frame | Under ~1 s from tap | The strongest predictor of whether a user stays |
| Rebuffer ratio | Under ~1% of watch time | Rebuffering is the most disliked defect in streaming |
| Quality switches | Infrequent and unobtrusive | Visible oscillation is worse than a steady lower quality |
| Seek response | Under ~500 ms to first frame at the new position | Requires segment-aligned seeking |
| Background audio | Continues indefinitely while playing | The platform permits this for active playback |
The four constraints
Bandwidth, and its variability. Not just how much, but how unstable. A train journey moves between 15 Mbps and 0.2 Mbps within a minute. The design must ride that rather than assume an average.
Cellular data as a cost to the user. The data-cost table above makes this real. This is one of very few constraints in the course that is about the user's money rather than their device, and treating it as a first-class requirement — a data-saver mode, a cellular quality cap, a warning before a large download — is a mark of someone who has shipped a video app.
Battery. Video playback is genuinely expensive: the screen is on at full brightness, the radio streams continuously, and the decoder runs constantly. Hardware decoding is dramatically cheaper than software decoding, which is the practical argument for using the platform's player rather than bundling your own. Audio-only playback with the screen off is roughly an order of magnitude cheaper than video, which is why background audio is worth designing properly.
Storage. Downloads compete with photos and everything else. An hour of 720p is about 1.1 GB, so a handful of downloaded films fills a device.
The constraint that shapes the design
Bandwidth varies faster than a user's patience. The rest of this lesson — adaptive bitrate and the buffer — is a response to that sentence: measure continuously, keep a buffer as a shock absorber, start low to start fast, and change quality in a way the viewer does not notice.
Offline, explicitly: downloaded videos play fully, including seeking, with no network. Undownloaded videos show a "not available offline" state with a download action queued for reconnect. The browse surface renders cached metadata and thumbnails. Watch position is recorded locally and synced later — a user who watches a downloaded film on a plane should not lose their position.
Adaptive bitrate playback on the client
Adaptive bitrate is the technique that makes streaming work on a mobile network. It is also a client-side algorithm — the server offers options, and the client decides, which is why it belongs in this course and not in System Design Interview.
Manifests and segments
The video is encoded several times at different qualities, and each encoding is cut into short segments — typically 2 to 6 seconds each. A manifest is a small text file listing the available qualities and how to find each segment.
manifest├── 144p ~0.1 Mbps seg_0001.m4s seg_0002.m4s …├── 360p ~0.7 Mbps seg_0001.m4s seg_0002.m4s …├── 720p ~2.5 Mbps seg_0001.m4s seg_0002.m4s …└── 1080p ~4.5 Mbps seg_0001.m4s seg_0002.m4s …Because segments are aligned across qualities, the player can fetch segment 12 at 720p and segment 13 at 360p and play them back to back. That alignment is the entire mechanism.
The decision, made once per segment
Before each fetch, the player chooses a quality from two inputs.
Measured throughput. How fast recent segments actually downloaded. Use a harmonic mean over the last several segments rather than an arithmetic one — the harmonic mean is dominated by the slow samples, which is the conservative behaviour you want.
Buffer level. How many seconds of video are already downloaded and waiting. This is the better signal, because it directly measures how close you are to the failure you are trying to avoid.
chooseQuality(throughput, bufferSeconds): safe = throughput * 0.8 // headroom for variance if bufferSeconds < 5: // danger: emergency return lowestQuality if bufferSeconds < 15: // cautious: do not step up return highestQualityUnder(safe, noHigherThan = current) if bufferSeconds > 25 and sustainedFor(10s, safe > next.bitrate * 1.5): return next quality up // step up slowly, one level return highestQualityUnder(safe)The asymmetry that makes it feel good
Step down fast, step up slowly. Dropping quality prevents a rebuffer, which is the worst outcome, so do it immediately on any sign of trouble. Raising quality risks causing the rebuffer you avoided, so require sustained headroom — a bitrate comfortably below measured throughput, held for several seconds — and move one level at a time.
The failure this prevents is oscillation: a player that switches every few seconds between 480p and 720p looks visibly worse than one that sits at 480p, even though its average bitrate is higher. Steadiness beats peak quality.
Constraints the algorithm must also respect
Bandwidth is not the only input. Cap quality on metered connections, cap it in low-power mode, cap it to the display resolution — decoding 4K for a 1080p screen wastes battery for nothing — and honour the user's manual override until they leave the video.
Offline: no adaptation. A downloaded video plays at the quality it was downloaded at, which is why that choice is made at download time in Offline downloads.
The buffer, and why start-up time is a design problem
The algorithm leans on buffer level, so the buffer needs a design of its own. It is a shock absorber: seconds of video already downloaded, so a network hiccup becomes invisible. Sizing it is a direct trade between resilience and how fast playback begins.
The trade
A large buffer survives long interruptions. A 30-second buffer rides out an entire tunnel. It costs data the user may never watch — abandoning after ten seconds with 30 seconds buffered wastes two thirds of what was downloaded — and it delays start, because you cannot begin until you have something.
A small buffer starts fast and wastes less, and rebuffers on the first dropout.
Typical shape for on-demand video: begin playback after 1–2 segments (a few seconds), then build toward a 20–40 second forward buffer, filling opportunistically while playing.
Why start-up is worth optimising hard
Time to first frame is the strongest predictor of whether a viewer stays. The exact relationship varies by product and is worth measuring rather than assuming — but the direction is consistent across every published study of streaming engagement: slower starts lose viewers, and the loss is steep in the first couple of seconds.
Four techniques, in order of impact:
1. Start at a low quality and step up. The first segment at 360p is roughly a fifth the bytes of 1080p, so it arrives roughly five times sooner. Play it, then step up once the buffer is healthy. The viewer sees a slightly soft first few seconds instead of a spinner, and almost nobody notices the former.
2. Fetch the manifest early. The manifest is small and needed before anything else. Fetch it when the user opens the video's page — before they press play — and the first segment request goes out the instant they tap.
3. Reuse the connection. A cold connection costs about three round trips (The network layer), which on a 150 ms link is ~450 ms of the 1-second budget. Keep the connection to the delivery network warm.
4. Prefetch the first segments of likely-next videos. While the user browses, fetch the manifest and first segment or two of the top items. When they tap, playback starts from local data — under 200 ms rather than 800.
Prefetching honestly
Prefetch is speculative and it spends the user's data on guesses. The discipline:
- Only on unmetered connections by default.
- Only the first one or two segments, at a modest quality — a few hundred kilobytes each, not megabytes.
- Only the top two or three candidates, and cancel immediately when the user scrolls past them.
- Bounded by a cache ceiling and evicted least-recently-used, like any other cache.
Say the numbers when you propose it: "two segments at 360p is roughly 700 KB per candidate; at three candidates that is about 2 MB to make three possible taps instant, and only on Wi-Fi." That is a defensible trade. "We prefetch the next videos" without those bounds is not.
Seeking
A seek jumps to a position with an empty buffer, so the same start-up problem applies. Two techniques: seek to the nearest segment boundary that begins with an independently decodable frame, and fetch that segment at a lower quality to get a picture up fast, stepping up once playback is stable.
Offline: a downloaded video has its whole buffer on disk, so start-up is a file read and seeking is instant. Worth stating, because it is the one place offline is better than online.