Design Dropbox / File Sync
Files change on several devices at once, uploads drop halfway, and the same bytes get uploaded again and again. The design splits files into content-addressed blocks and keeps a change log every device can replay.
1 · Requirements
The Prompt
Multi-device file sync with conflict resolution, deduplication, and resumable uploads.
Functional
- Upload and download files of any size, resuming after a dropped connection
- Sync changes to every device signed in to the account
- Keep file revisions and resolve conflicting edits
- Share files and folders
Non-Functional
- A change shows up on other online devices within seconds
- No edit is silently lost when two devices conflict
- Identical blocks are stored once
2 · Estimates
Drill This Phase First
Show the Answer and Estimates
Answer
About 12,000 a second
100M times 10 is 1B changes a day. 1B divided by 86,400 seconds is about 11,600, so call it 12,000 writes a second.
- Changes
- 100M daily users making 10 file changes a day: 1B changes, about 12,000 writes a second
- Blocks
- 4 MB blocks and about 30% dedup: about 5B blocks a day, 3.5B of them unique
- Storage
- 3.5B unique blocks at up to 4 MB: about 14 PB a day raw, and about 25 PB with erasure coding and a cross-region copy
- Metadata
- About 100B files at 500 bytes each: roughly 50 TB in SQL, sharded by user_id
- Sockets
- About 20% of daily users online: 20M WebSocket connections across about 10,000 gateway nodes
- CDN
- The CDN download path saves about 60% of egress for shared and popular files
3 · API
POST /blocks { sha256, size } → { upload_url } | { already_exists: true }
PUT /blocks/:sha256 (binary) → 200
POST /files/commit { path, version, block_list[sha256...] } → { file_id, rev }
GET /files/:id?rev=… → { manifest, block_urls[] }
GET /changes?cursor=… → { events[], next_cursor }
WS /notify: pushes { file_id, rev, actor } on changeData Model
files (SQL, sharded by user_id):
file_id (PK) : uuid
user_id : uuid
path : string
current_rev : int
size : bigint
modified_at : timestamp
deleted : bool
file_revisions (SQL):
file_id (FK) : uuid
rev : int
block_list : json array of sha256
author_device : uuid
ts : timestamp
blocks (KV / object store):
sha256 (PK) : string
size : int
refcount : int (for GC)
s3_key : string4 · High-Level Design
5 · Deep Dives
Blocks and Dedup
Hash each 4 MB block with SHA-256 and ask the block service which hashes already exist. Only new blocks get uploaded, so a copied file costs one metadata write. Resuming an upload is the same check: send the blocks the server still lacks.
Conflicts
Every commit names the revision it was based on. If the current revision has moved on, the commit is a conflict: keep the server version and save the incoming one as a conflicted copy beside it, so no edit disappears. Vector clocks can detect concurrent edits, and the conflicted copy is what users understand.
The Change Log
Each user's changes form an ordered log with a cursor. A device that was offline for a week replays from its last cursor, and an online device gets a WebSocket nudge to pull. Change data capture from the metadata database keeps the log in step with committed revisions.
6 · Wrap Up
The Short Version
Chunk files into ~4MB blocks; SHA-256 dedup. Metadata in SQL. Notify clients via WebSocket or long-poll. Resumable via chunk-level acks.