Design Cloud File Storage (Google Drive / Dropbox)
Upload, sync, share, and version files across devices with dedup and conflict resolution.
Overview
A file storage/sync service stores users' files durably and keeps them consistent across devices. The interesting engineering is chunking + deduplication, efficient sync (only send what changed), and resolving concurrent edits.
Requirements
Functional
- Upload/download files; keep them synced across a user's devices.
- Share files/folders with permissions.
- Version history and restore.
- Efficient sync — transfer only changed chunks.
Non-functional
- Strong durability (no data loss) and high availability.
- Bandwidth- and storage-efficient via dedup.
- Handle large files and offline edits with conflict resolution.
Back-of-the-envelope
The numbers that justify the architecture.
| Users | 500M | |
| Avg storage / user | ~10 GB | → exabytes total |
| Chunk size | ~4 MB | dedup + partial sync unit |
| Metadata ops | high | many small files + versions |
Reference architecture
A client splits files into content-hashed chunks, uploads only new chunks to blob storage, and syncs a compact metadata model that clients diff against.
Deep dives
Chunking and deduplication
Split each file into fixed or content-defined chunks (~4 MB) and identify each by a hash of its contents (content-addressed storage). Before uploading, the client asks 'do you already have chunk H?' — unchanged chunks and files shared across users are stored once. Editing a 1 GB file changes a few chunks, so sync transfers kilobytes, not gigabytes. This is the core efficiency win.
Metadata vs blocks (split the plane)
Separate the metadata plane (file tree, names, permissions, chunk lists, versions) from the data plane (the chunks themselves). Metadata is small, transactional, and queried constantly → a replicated relational/indexed store. Chunks are large and immutable → blob storage. A file version is just an ordered list of chunk hashes, which makes version history and restore cheap.
Sync and change notification
Clients keep a local view and reconcile against server metadata. On a change, the server pushes a notification (long poll / WebSocket) so other devices pull the metadata delta and fetch only new chunks. Offline devices catch up on reconnect using a per-user change journal / cursor.
Conflict resolution
Two devices editing the same file offline will conflict. Detect via version vectors; the pragmatic resolution most products ship is 'keep both' — create a conflicted copy (`file (conflicted copy from Device X)`) rather than silently losing an edit. For structured docs, operational transforms / CRDTs enable true merge, but for opaque files, conflicted copies are the honest answer.
Key trade-offs
For each decision: the two options, and when to pick which.
Bottlenecks & follow-ups
Where it breaks under load — and what an interviewer will probe.
- ▲Metadata hotspots on shared folders → shard by user/namespace, cache the tree.
- ▲Re-uploading unchanged data → content-addressed dedup.
- ▲Thundering sync after outage → change cursors + batched deltas.
What a strong answer sounds like
- ✓Separate metadata plane from data plane on the board — it structures the whole answer.
- ✓Lead with chunk-level dedup; it's the efficiency insight interviewers want.
- ✓Refuse to silently lose an edit — propose conflicted copies for offline conflicts.