Design prompt: image and video uploader
Put numbers on size, link, drops and deadline first; part size, start time, URL batches and what survives a reload follow from them.
Predict first
Before you read: predict
ExamHall's test-centre laptops upload each oral-exam recording, 2 GiB, straight to storage as a multipart upload with 4 parts on their way at once. The centre's Wi-Fi drops at random, on average once for every 400 MiB a laptop sends. Every part but the last must be at least 5 MiB.
Which part size sends the fewest part requests while, on average, a laptop sends at most 10% more than the recording?
The 30-second version
An uploader's design is its budgets: file size, the link a site shares, how often it drops, the deadline. Each drop throws away about half a part per part on its way; take the largest part that fits. Time is bytes over your share of the link: start earlier, not wider. A reload keeps disk, not memory.
Put numbers on size, link, drops and deadline first; part size, start time, URL batches and what survives a reload follow from them.
How it works
Step 1 of 11
In the kitchen
- the clerk first asks how long the dispatch is, how many correspondents share the wire tonight, how often storms break it, and the press deadline → numbers first (step 1)
Analogy: A remote telegraph office filing a correspondent's long dispatch
| At the office | In the design |
|---|---|
| the clerk first asks how long the dispatch is, how many correspondents share the wire tonight, how often storms break it, and the press deadline | numbers first (step 1) |
| a storm loses every telegram being keyed, each sent again whole; the clerk keeps telegrams short enough that a break costs little, long enough that headers don't eat the night | part size from the drop rate (steps 3–4) |
| a second operator on the same shared wire sends no more words; keying the first pages while the correspondent still writes does | start earlier, not wider (steps 5–7) |
| booking slips are good for an hour, so the clerk collects a few at a time | URL batches (step 8) |
| the ledger of sent telegrams stays in the office; the night clerk checks the next page's headline, page count and date against it | a reload keeps disk; check the picked file (steps 9–10) |
In real terms: an uploader spends bytes, requests and minutes from a shared link that drops.
Breaks down when: a clerk can always retype from the paper; a page can read the file again only if it kept it on disk or the user picks it again.
Contrasting case: a chat app's 3 MB photo: one PUT, one retry, no budgets.
Examples, run for real
4.1 ExamHall EXH-3460 → MR !3760: a small centre's recordings
A 20-candidate centre runs 30-minute sessions, and its Wi-Fi drops on average once per 150 MiB a laptop sends. The pilot uploaded each 1 GiB recording after the session in 128 MiB parts, 4 at a time, over a 50 Mbit/s uplink (EXH-3460). MR !3760 sends 8 MiB parts while the session records (steps 3–7).
4.1 model: 20 laptops · 1024 MiB recording · 30-minute session · drops at random, mean gap 150 MiB · 50 Mbit/s uplink · 4 parts on their way
4.1 EXH-3460 pilot: 128 MiB parts, after the session · at risk per drop 512 MiB · expected waste per drop 256 MiB (half of each part on its way) · sent 775.9% over the recording · part requests 245.4 · last recording stored 8 h 22 min after the session ends
4.1 MR !3760: 8 MiB parts, during the session · at risk per drop 32 MiB · expected waste per drop 16 MiB (half of each part on its way) · sent 9.8% over the recording · part requests 155.8 · last recording stored 34 min after the session ends
At 128 MiB a drop risks 512 MiB and wastes about 256, over the 150 MiB gap: each laptop sends almost nine times its recording. At 8 MiB a drop wastes about 16 MiB, about seven times: near 10% (steps 3–4). An early start fixes the deadline (steps 5–7).
4.2 Proof domain, payments: the round's API for a settlement export
A payments ledger's back office uploads a 1.2 GiB settlement export; the tab reloads once at about 70%. Every call is logged (step 2).
4.2 model: 1228.8 MiB export · 77 parts of 16 MiB · part URLs 16 at a time · tab reloads after part 53
4.2 PUT /exports/{file}/upload: 2 calls · 156 bytes of JSON
4.2 POST /uploads/U{n}/part-urls: 6 calls · 3,106 bytes of JSON
4.2 GET /uploads/U{n}/parts: 1 call · 161 bytes of JSON
4.2 POST /uploads/U{n}/complete: 1 call · 31 bytes of JSON
4.2 total: 10 API calls · 3,454 bytes of JSON · 1,288,490,189 export bytes, all to storage · after the reload 24 parts sent, none twice
The API sees ten small JSON calls and no export byte. After the reload the page lists stored parts and sends the rest (fsd-file-upload-media step 8).
4.3 The board for "Design uploads for 2 GB videos on flaky networks" (worked, not executed)
| Typical question | Steps that answer it | Mechanism owner |
|---|---|---|
| "What part size, and why?" | 1, 3, 4 | this lesson; the 5 MiB floor and whole resends: fsd-file-upload-media |
| "The whole centre finishes at noon. When is everything stored?" | 5–7 | this lesson; bits against bytes: sd-back-of-envelope |
| "The tab reloads at 70%. What happens?" | 9, 10 | this lesson; ListParts and resending: fsd-file-upload-media |
| "Why should the file not pass through your API servers?" | 2 | fsd-file-upload-media steps 1–2 |
Try it
Answer first, then check. Nothing is saved.
Question 1 of 7
ExamHall's design so far: each test-centre laptop uploads its candidate's oral-exam recording when the session ends, in 16 MiB parts, 4 on their way at once. The interviewer's next follow-up: "A centre runs 40 candidates in one 30-minute session ending at 12:00. Each recording is 1 GiB, recorded at a steady rate, and every one must be in storage by 12:45. The centre's uplink is 100 Mbit/s, and nothing else uses it during exams." A laptop can re-encode a recording to half its size in as long as the recording lasts.
Which change answers the follow-up?
Question 2 of 7
A concert hall's gate app uploads the night's 3 GiB gate-camera archive to storage in 16 MiB parts, 4 on their way at once. The API signs each part URL for 15 minutes from the moment it hands it out, and storage refuses a PUT that starts later. The hall office's line gives the upload a steady 20 Mbit/s, which falls to 10 Mbit/s when the box office is busy.
Which way of asking for part URLs never has a PUT refused, at either speed, with the fewest calls to the API?
Question 3 of 7
A payments ledger's back-office page uploads the day's settlement export, 1,434 MiB, in 16 MiB parts; the operator picks it with a file input, and the export is always named settlement-export.csv. The page keeps the upload id in IndexedDB. At 70% of the parts, the tab reloads; the page asks the operator to pick the file again, then resumes that upload or starts a new one. In the logs, operators re-picking after a reload chose the same export, yesterday's export (a different size), or today's export again after finance re-ran it to correct one amount in the middle of the file, at the same size.
Which check before resuming means no stored export is ever a mix of two files, while a re-pick of the same export resumes?
Question 4 of 7
ExamHall's test-centre app records each 30-minute oral exam with MediaRecorder, start(1000), a blob a second, about 1 GiB in all, and uploads the recording when the session ends, keeping the upload id and each part's ETag in IndexedDB. The laptop has 40 GB of free disk. At 70% of an upload, a browser update reloads the tab.
Where should the app keep the recording until it is stored, so that the upload finishes after the reload with the whole recording?
Question 5 of 7
The interviewer says: "Design the upload of ExamHall's oral-exam recordings, up to 2 GiB, from test centres with unreliable Wi-Fi." The numbers you get when you ask: 30 candidates per session, 45-minute sessions ending together, 2 GiB per recording, a 200 Mbit/s centre uplink that nothing else uses during exams, Wi-Fi dropping on average once per 300 MiB a laptop sends, at most 10% sent over the recording, every recording stored within an hour of the session's end, part URLs signed for 15 minutes, and a share that can halve. In 20 minutes, write your board: the numbers, the API, the part size and parts on their way, when uploading starts, how part URLs are fetched, where the recording waits, and what a reload does.
Then write your choices in the shape of design.template.mjs as my-design.mjs, and run the check.
Question 6 of 7
A chat company's support office records its 30 agents' screen sessions for quality review. At 17:00 every agent's laptop starts uploading its day's 1 GiB recording, 4 parts on their way at once, over the office line, sold as 500 Mbit/s down and 100 Mbit/s up; nothing else uses the line after 17:00.
When is the last recording in storage, rounded up to the next minute?
Question 7 of 7
A streaming studio uploads each 4 GiB episode master straight to storage as a multipart upload with 3 parts on their way at once. Its line drops at random, on average once for every 500 MiB it sends. Every part but the last must be at least 5 MiB.
Which part size sends the fewest part requests while, on average, the studio sends at most 5% more than the master?
Go deeper
Pro tip
- Say the drop rate out loud, then multiply: parts on their way × half a part is what one drop costs; times the expected drops is the waste. When: the interviewer asks for a part size on a flaky network. Status: RAN on the seeded drop model (a model of Wi-Fi, not logs).
Source
No item is keyed on a source; every key is executed. A guide's interview advice is valid as of 2026-10-10.
- AWS, Uploading and copying objects using multipart upload (the curriculum row's URL): https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html (
aws-mpu-overview.txt). "Smaller part size minimizes the impact of restarting a failed upload due to a network error." (steps 3–4); "use multipart upload to maximize the use of your available bandwidth by uploading object parts in parallel" (step 6); "You can upload an object as you create it." (step 7). - AWS, Amazon S3 multipart upload limits: https://docs.aws.amazon.com/AmazonS3/latest/userguide/qfacts.html (
aws-mpu-limits.txt). "5 MiB to 5 GiB. There is no minimum size limit on the last part of your multipart" (step 4's floor). - AWS API Reference, ListParts: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html (
aws-api-listparts.txt). "Lists the parts that have been uploaded for a specific multipart upload." (step 2's list of stored parts; how a resume uses it isfsd-file-upload-mediastep 8). - tus, Resumable upload protocol 1.0.x (the curriculum row's URL): https://tus.io/protocols/resumable-upload (
tus-protocol.txt). "The core protocol describes how to resume an interrupted upload." A tus server keeps the bytes it received and the client resumes from itsUpload-Offset; S3 parts are all or nothing, which is why steps 3–4 exist. - Front End Interview Handbook, Front End System Design (the curriculum row's URL): https://www.frontendinterviewhandbook.com/front-end-system-design (
fih-overview.txt). "Requirements exploration: Understand the problem thoroughly and determine the scope by asking a number of clarifying questions" (step 1). - MDN, Origin private file system: https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system (
mdn-opfs.txt). "Browsers persist the contents of the OPFS to disk somewhere, but you cannot expect to find the created files matched one-to-one." (step 9). - MDN, Storage quotas and eviction criteria: https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria (
mdn-storage-quotas.txt). "Browsers can store up to 5 MiB of local storage, and 5 MiB of session storage per origin.". - MDN, File: lastModified property: https://developer.mozilla.org/en-US/docs/Web/API/File/lastModified (
mdn-file-lastmodified.txt). "last modified date of the file as the number of milliseconds since the Unix epoch" (step 10).
Related lessons
Checked against the tools and docs as of 2026-10-10.