system-design · intermediate
Design Dropbox — File Sync and Storage
Start here
Design Dropbox (simplified) means users can:
- Upload files from desktop/mobile
- Download/sync across devices
- Share links (optional MVP+)
- Keep metadata (names, folders, versions) consistent
What you will learn
- Clarify sync vs simple cloud drive MVP.
- Chunk large files and dedupe.
- Design metadata DB vs object storage.
- Sync protocol with local change detection.
- Handle conflicts when two devices edit offline.
- Discuss security (encryption at rest, link sharing).
Words you need before we begin
| Term | Plain English |
|---|---|
| Chunking | Split file into blocks for upload/resume/dedupe. |
| Content hash | Fingerprint of bytes (e.g. SHA-256). |
| Metadata | Name, path, owner, version—not the bytes. |
| Object storage | Durable blob store for chunks/files. |
| Sync cursor | Token meaning “changes since X.” |
| Conflict | Concurrent edits producing divergent versions. |
| Deduplication | Store identical chunks once. |
Requirements
MVP
- Upload/download file
- Folder tree per user
- Multi-device list/sync recent changes
- Resume interrupted uploads
Non-functional
- Integrity of bytes
- Efficient sync (do not re-upload whole file for small edits when possible)
- High durability
Scale example
- 500M users, average 10 GB stored (illustrative) → multi-EB planning story
- Uploads spiky after work hours
High-level design
flowchart LR
Client --> API[Control plane API]
Client --> Upload[Chunk upload via presigned URLs]
API --> Meta[(Metadata DB)]
Upload --> Obj[(Object storage chunks)]
API --> Notify[Change notifications]
Notify --> Client
Step-by-step design
Step 1 — Metadata model
namespace, inode/file_id, parent, name, version, size, content_hash, updated_at. Folder entries vs file entries.
Step 2 — Chunk and upload
Client splits file into ~4MB chunks, hashes each, asks server which chunks are missing (dedupe), uploads missing chunks to object storage via presigned URLs, then commits metadata transaction referencing chunk list.
Step 3 — Download / sync
Client sends cursor; server returns changed metadata; client fetches missing chunks by hash.
Step 4 — Notifications
Websocket/long poll/push: “namespace changed” so clients pull deltas.
Step 5 — Conflicts
If two devices commit different content for same path version, create conflict copy (file (conflicted).docx) or CRDT for special file types—state the simple approach in interviews.
Step 6 — Sharing (extension)
Share records with ACLs; link tokens; audit access.
Failure modes
| Mode | Impact | Mitigation |
|---|---|---|
| Partial chunk upload | Incomplete file | Commit only when all chunks present |
| Metadata commit fail after bytes | Orphan chunks | GC job for unreferenced chunks |
| Dual writers | Conflicts | Version checks |
| Hot shared folder | Metadata hotspots | Cache; partition carefully |
| Hash collision fears | Integrity debate | Use strong hashes |
Trade-offs
| Choice | Benefit | Cost |
|---|---|---|
| Small chunks | Resume + dedupe | More metadata |
| Whole-file only | Simple | Bad for large files |
| Server-side encryption keys | Simpler clients | Provider trust |
| Client-side E2E encryption | Privacy | Feature limits |
Common mistakes
- Streaming all bytes through app servers permanently.
- No resume for multi-GB uploads.
- Treating S3 as the only database for listing folders.
- Ignoring conflict cases.
- Perfect global filesystem semantics in 45 minutes.
Check your understanding
- Why separate metadata and bytes?
- How does chunk dedupe work?
- What is a sync cursor for?
- Name a simple conflict policy.
- Why presigned uploads?
Practice
- Sequence for uploading a 2 GB video with one failed chunk.
- Estimate chunk metadata count for 1 TB unique data.
- Design API for list folder and get changes since cursor.
- Discuss ransomware versioning/history.
- Timed mock interview.
Deeper production notes
Garbage collection
Unreferenced chunks after failed commits need lifecycle policies.
Consistency
Metadata needs strong transactional semantics for renames/moves; object store is eventually consistent in some ops—design commit carefully.
Additional teaching scenarios
Scenario A — 10× peak
Which component saturates first? First mitigation?Scenario B — dependency down 30 minutes
What still works? What degrades?Scenario C — interview wrap (5 sentences)
Requirements, MVP, main scale lever, key failure, top trade-off.Revision summary
- Bytes ≠ metadata.
- Chunk, hash, dedupe, commit.
- Sync via cursors + notifications.
- Plan conflicts and orphan GC.
Glossary
| Term | Definition |
|---|---|
| Chunk | Fixed-size block of file content. |
| Namespace | User or shared space of paths. |
| Commit | Metadata transaction publishing a new file version. |
Abbreviations and terminology
- SHA — Secure Hash Algorithm family
- ACL — Access control list
- E2E — End-to-end
What to learn next
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Extra teaching notes
When you apply this lesson, write the user-visible success metric first, then the failure mode you fear most. Design the smallest mechanism that protects that metric under partial failure. Prefer explicit timeouts, idempotency, and ownership over adding more infrastructure boxes.
In interviews or design reviews, narrate assumptions, request paths, and trade-offs out loud. A correct-enough design with clear failure handling beats a buzzword diagram without numbers. Revisit the worked example and restate it for a different domain to prove you own the ideas, not the template wording.
Interview and production field guide for this topic
Use this section as deliberate practice, not filler. Rewrite the worked example for a second domain you know well—fintech, education, logistics, or media. Keep the same skeleton: requirements, estimates, high-level diagram, request path, data model, scale lever, failure modes, and trade-offs. If you cannot fill every section without copying buzzwords, you do not yet own the design.
Numbers to force yourself to state
Always speak order-of-magnitude figures: peak QPS, storage growth per day, fan-out factor, connection counts, or queue depth. Wrong numbers that are explicit beat silent hand-waving. Correct the numbers when the interviewer or teammate challenges them; that is collaboration, not failure.
Failure minute
Set a timer for sixty seconds and list only failures: timeouts, duplicates, hot keys, dependency outages, bad deploys, and data corruption paths. For each, name detection and first mitigation. Designs that only describe the happy path are incomplete for production and weak in interviews.
Ownership and operability
Name the dashboard, the alert, the runbook section, and the team that pages. If any are blank, the system will train you during an incident. Prefer progressive delivery: canaries, flags, and rollback notes written before the change lands.
Consistency and retries
State whether the design assumes at-least-once delivery, whether handlers are idempotent, and where unique constraints live. Retries without idempotency are how double charges, double messages, and duplicate fan-out jobs appear. Timeouts without bounds are how thread pools die.
What good looks like in a review
A strong design review or interview answer clarifies scope, makes assumptions audible, draws a minimal path, deepens one or two bottlenecks, and closes with trade-offs and evolution. Use that bar on design-dropbox round 0 every time you revisit it.
Interview and production field guide for this topic
Use this section as deliberate practice, not filler. Rewrite the worked example for a second domain you know well—fintech, education, logistics, or media. Keep the same skeleton: requirements, estimates, high-level diagram, request path, data model, scale lever, failure modes, and trade-offs. If you cannot fill every section without copying buzzwords, you do not yet own the design.
Numbers to force yourself to state
Always speak order-of-magnitude figures: peak QPS, storage growth per day, fan-out factor, connection counts, or queue depth. Wrong numbers that are explicit beat silent hand-waving. Correct the numbers when the interviewer or teammate challenges them; that is collaboration, not failure.
Failure minute
Set a timer for sixty seconds and list only failures: timeouts, duplicates, hot keys, dependency outages, bad deploys, and data corruption paths. For each, name detection and first mitigation. Designs that only describe the happy path are incomplete for production and weak in interviews.
Ownership and operability
Name the dashboard, the alert, the runbook section, and the team that pages. If any are blank, the system will train you during an incident. Prefer progressive delivery: canaries, flags, and rollback notes written before the change lands.
Consistency and retries
State whether the design assumes at-least-once delivery, whether handlers are idempotent, and where unique constraints live. Retries without idempotency are how double charges, double messages, and duplicate fan-out jobs appear. Timeouts without bounds are how thread pools die.
What good looks like in a review
A strong design review or interview answer clarifies scope, makes assumptions audible, draws a minimal path, deepens one or two bottlenecks, and closes with trade-offs and evolution. Use that bar on design-dropbox round 1 every time you revisit it.
FAQ from first-time learners
Q: Block-level sync like rsync?
A: Advanced; chunking is the interview-friendly version.
Q: Database for chunks?
A: Prefer object storage; DB for metadata.
Track: Distributed Systems
Previous: Design a Notification Service — Push, Email, SMS
Next: Design Instagram — Photos, Feed, and Fan-Out
By Shubham Jain