Google Drive feels like a folder that magically shows up on every device you own. The magic is file sync: you upload a file once, and the same file appears everywhere — fast, safe, and without re-sending bytes you already have. Almost all of the hard engineering is in how files are split up, stored, and synced — not in handling a huge number of requests.
The animation on the right walks the whole sync trip from start to finish: Client 1 uploads a file → the block servers cut it into small pieces (chunks) → the chunks go to cloud storage (S3) while a map of which chunks make up this file is saved in the metadata DB → the notification service pokes Client 1's other device, which then pulls only the chunks that changed (and skips one it already has, thanks to block-level de-duplication).
Step 1: Pin down the requirements and the scale
Google Drive is huge, so we shrink the problem to a few core features:
- Add files (drag and drop), any file type, up to 10 GB each
- Download files
- Sync across devices — change a file on one device, and it shows up on the others
- File revisions (keep a history of old versions)
- Sharing and notifications when a file is edited, deleted, or shared
- Files must be encrypted while stored (scrambled so a thief can't read them)
Out of scope: two people editing the same file live at the same time (that's the Google Docs problem). Some non-functional goals worth saying out loud: reliability (we must never lose data), fast sync, low bandwidth use (people are often on mobile data), scalability, and high availability (it should almost never be down).
Back-of-the-envelope estimate
Users: 50M signed up, 10M active per day (DAU)
Free space/user: 10 GB
Uploads/user/day: 2 files, avg file size 500 KB
Read:write ratio: 1:1
Total storage = 50M users × 10 GB = 500 PB
Upload QPS = 10M × 2 / 24 / 3600 ≈ 240 uploads/sec
Peak QPS = 240 × 2 ≈ 480 uploads/sec
The numbers change how you think about the problem. 480 uploads per second is tiny — a single main database could easily handle those writes. The real pressure is 500 PB of storage that must never be lost, bandwidth (don't re-send unchanged data), and how quickly files sync. Saying this out loud — "the hard part isn't write volume, it's storage cost and bandwidth" — is the senior move. It pushes the whole interview toward chunking and delta sync.
Step 2: The three core APIs
All APIs need a logged-in user and run over HTTPS (SSL keeps the data safe while it travels).
- Upload — works in two modes:
- Simple upload for small files.
- Resumable upload for big files on shaky networks: you get a special upload URL, send the file while watching the progress, and if the connection drops you pick up from the last good spot instead of starting over.
POST https://api.example.com/files/upload?uploadType=resumable params: uploadType=resumable, data=<local file> - Download
GET https://api.example.com/files/download { "path": "/recipes/soup/best_soup.txt" } - Get file revisions (the version history)
GET https://api.example.com/files/list_revisions { "path": "/recipes/soup/best_soup.txt", "limit": 20 }
Step 3: High-level design
Start simple, with one machine (a web server + MySQL + a drive/ folder that holds each user's files), then split it apart the moment it starts to strain:
| Problem | Fix |
|---|---|
| Disk fills up | Shard (spread) file storage; move files to Amazon S3 (copied across regions so they're safe) |
| One machine = one point of failure | Put a load balancer in front of stateless API servers |
| Database becomes the bottleneck | Move the metadata DB onto its own machines; add copies + sharding |
After splitting it up, the system has these parts:
- API servers — stateless (they keep no per-user memory); handle login, profiles, and metadata. They do everything except the heavy file-byte uploads.
- Block servers — cut files into pieces, compress them, encrypt them, and push them to cloud storage.
- Cloud storage (S3) — stores each piece as its own object; cold storage (like S3 Glacier) holds rarely-used data cheaply.
- Metadata DB — users, files, blocks, versions. The actual files live in S3; this DB holds only the metadata (the info about the files).
- Metadata cache — keeps frequently-read metadata handy for fast reads.
- Notification service — a publish/subscribe layer that tells your other devices when a file changed.
- Offline backup queue — holds changes for devices that are currently offline, ready to deliver when they come back.
Block (chunk)
A file is cut into pieces called blocks, each with a maximum size — Dropbox caps a block at 4 MB. Each block gets a content hash (a short fingerprint of its exact bytes), is stored as its own object in S3, and is pointed to from the metadata DB. To rebuild a file, you join its blocks back together in order. That fingerprint hash is the key trick that makes both delta sync and de-duplication work.
Metadata schema (simplified)
User – username, email, profile photo
Device – push_id for mobile notifications (one user can have many devices)
Namespace – the user's root folder
File – everything about the latest version of a file
File_version – version history; these rows are read-only (so history can't be changed)
Block – one row per block; join them in order to rebuild any version
Two things to say out loud here. First, "files in S3, metadata in the DB" — mixing these up is a
classic mistake. Second, File_version rows never change: you don't overwrite history, you just add
a new version on top. That append-only rule is what makes "show me old file versions" easy and safe.
Step 4: Deep dive
Block servers and delta sync
Re-sending a whole file every time you edit it wastes bandwidth. Two tricks fix that:
- Delta sync — when a file changes, only the pieces that changed are synced (found by comparing block hashes), not the whole file.
- Compression — each block is squeezed smaller (gzip/bzip2 for text; other methods for images and video) before it goes to S3.
So the block-server upload path is: split → compress → encrypt → upload only the changed blocks. If a 10-block file changes blocks 2 and 5, only those two blocks move.
Why send the bytes through the block servers at all, instead of going client → S3 directly? Going direct is one hop faster, but then the chunking, compression, and encryption code has to be rewritten on every platform (iOS, Android, Web) — which is easy to get wrong — and putting encryption on a device that can be hacked is unsafe. Keeping that logic in the block servers is the safer default.
Saving storage space
Saving every version across several data centers gets expensive fast. Three ways to cut cost:
| Technique | What it does |
|---|---|
| De-duplicate blocks | Two blocks with the same hash are identical — so store just one copy for the account |
| Limit versions | Cap how many old versions you keep; lean toward keeping the recent ones |
| Cold storage | Move data nobody has touched in months/years to S3 Glacier (much cheaper than normal S3) |
Strong consistency
It would be bad for two devices to see different versions of the same file at the same moment, so the system aims for strong consistency (everyone always sees the same latest version) on the metadata:
- Keep the cache copies and the main database in agreement.
- Clear the cache on every database write so the cache and the database never drift apart.
- Use a relational database — its built-in ACID rules make consistency easier than forcing it onto NoSQL.
Upload flow (two paths at once)
When Client 1 uploads, two requests go out at the same time:
- Add metadata → the DB saves the new file as
pending→ the notification service tells other devices an upload is in progress. - Upload bytes → block servers chunk/compress/encrypt → push to S3 → S3 sends back a "done" callback → the status flips to
uploaded→ the notification service announces the file is fully uploaded.
Download flow and the notification service
A device finds out a file changed in one of two ways: if it's online, the notification service tells it to pull the update; if it's offline, the event waits in a queue and replays once it reconnects. Then the device gets the metadata first (the new list of blocks), downloads only the blocks it's missing, and rebuilds the file.
For sending those notifications, the choice is long polling vs. WebSocket:
| Long polling (chosen) | WebSocket | |
|---|---|---|
| Direction | One-way (server → client) ✓ matches our need | Two-way |
| Best for | Rare, occasional notifications ✓ | Constant chat-style traffic |
| Connection | Client holds the line open until a change, then reconnects | Always-open, two-way |
Google Drive notifications are rare and one-direction, so long polling (the same choice Dropbox made) fits better.
Failure handling
| Part that fails | How it recovers |
|---|---|
| Load balancer | A backup takes over (a heartbeat signal notices the death) |
| Block server | Other block servers pick up the unfinished jobs |
| Cloud storage | Read the data from another region (S3 keeps cross-region copies) |
| API server | Stateless — the load balancer just sends traffic to a healthy one |
| Metadata cache | Copied across nodes; read from a surviving one, then start a replacement |
| Metadata DB master | Promote a backup (slave) to be the new master, then add a new backup |
| Notification server | Long-poll connections drop; clients reconnect (slow — Dropbox reported >1M connections per machine) |
Sync conflicts deserve a sentence even if no one asks: "first write wins; the later write becomes a conflict." The device that lost is shown both copies — its own version and the server's latest — and picks whether to merge them or overwrite. Naming a real conflict rule, instead of hand-waving "we'll handle conflicts," is what makes an answer sound senior.
Wrap-up
Google Drive is interesting because it trades raw request volume for saving bandwidth, never losing data, and keeping versions consistent. The design has two flows — manage metadata and sync files — tied together by a notification service. The ideas that carry the answer:
- Cut files into hashed blocks → this enables delta sync and de-duplication.
- Files in S3, metadata in a relational DB → durable storage, ACID consistency, clear the cache on every write.
- Long polling for rare, one-direction change notifications.
- Delta sync + compression + dedupe + cold storage to keep 500 PB affordable.
A 45-minute pacing plan: 5 min requirements + estimate → 5 min APIs → 10 min high-level design → 20 min deep dive (block servers, delta sync, consistency, notifications) → 5 min failure cases and conflicts. If time is left, raise the client-direct-to-S3 trade-off and the idea of moving online/offline status into a separate presence service — both show you're thinking past the happy path.
Practice
Check your understanding of how Google Drive splits, stores, and syncs files.
1. Why is a file cut into small blocks, each with a content hash?
2. Where do the actual file bytes live, and what does the metadata DB hold?
3. The estimate says about 480 uploads/sec at peak but 500 PB of storage. What is the real challenge?
4. Why does Google Drive use long polling instead of WebSocket for sync notifications?
5. Why route upload bytes through the block servers instead of going client → S3 directly?