Articles
Cloud File Storage System Design Interview: Chunked Uploads, Sync, Sharing, and Conflict Resolution
Learn cloud file storage system design: chunked uploads, metadata, sync, sharing permissions, version history, conflicts, and regional recovery.
A strong cloud file storage system design interview answer separates immutable file bytes from strongly consistent metadata. Upload chunks directly to blob storage, commit a file version only after validating its manifest, synchronize devices through an ordered change journal, and preserve ambiguous concurrent edits as separate versions instead of silently overwriting data.
Cloud file storage system: a Dropbox- or Google Drive-style product that stores large files, resumes interrupted transfers, synchronizes folders across devices, shares content safely, keeps version history, and recovers from client, service, or regional failure.
This guide is for engineers preparing for backend, storage, or distributed-systems rounds.
The scope is whole-file storage and synchronization. Real-time collaborative editing, full-text search, and detailed CDN design are separate problems.
Architecture focus: transactional metadata commits refer to durable immutable chunks, while an ordered change journal keeps devices synchronized.
Cloud file storage system design interview: the quick answer
Use an API gateway for metadata and upload sessions, then send chunks directly to object storage through signed URLs. A transactional metadata database stores stable node IDs, versions, manifests, permissions, and tombstones; the blob store holds immutable chunk bytes.
On upload completion, validate every required chunk, atomically create a new file version, update the current-version pointer, and append a change event through the same transaction or an outbox. Devices pull changes using a monotonic namespace cursor. Push notifications only wake clients. Concurrent writes compare a supplied base_version_id; when the base is stale, preserve both versions.
Use the BMSR interview frame: Bytes covers chunks and manifests; Metadata covers IDs, versions, and ACLs; Sync covers cursors and retries; Recovery covers conflicts, history, and replication.
Clarify requirements, scale, and invariants first
Ask about folders, offline edits, share links, inherited permissions, version retention, cross-region recovery, maximum file size, and deduplication. A consumer sync product usually offers versioned object semantics, not arbitrary byte-range writes to an open file.
One interview model could have 20 million daily active users, two uploads per user per day, and an 8 MB mean file: 40 million uploads and roughly 320 TB of logical ingest per day. These are assumptions, not production facts; design for peak bandwidth and large-file concurrency.
State the invariants before drawing services:
- A committed file version never points to a missing or unverified chunk.
- A file keeps the same stable ID across rename and move operations.
- Every namespace mutation receives an ordered sequence number.
- Retrying an upload part or commit cannot create duplicate versions.
- Permission revocation prevents new authorization, even if caches are stale.
- Deletes remain recoverable during the configured retention window.
Separate the metadata control plane from the blob data plane
The control plane handles small, consistency-sensitive namespace, permission, upload-session, journal, and version records. The data plane moves chunks directly between clients and object storage, avoiding an application-server bandwidth bottleneck.
A useful model includes:
Node(node_id, namespace_id, parent_id, name, type, current_version_id)FileVersion(version_id, node_id, base_version_id, manifest_id, device_id, created_at)Manifest(manifest_id, ordered_chunk_hashes, total_size, checksum)Chunk(chunk_hash, size, object_key, ownership_scope, ref_count)UploadSession(session_id, node_id, expires_at, state)Permission(resource_id, principal_id, role, inherited_from)ChangeEvent(namespace_id, sequence, operation, node_id, version_id)Tombstone(node_id, deleted_at, prior_version_id)
Shard metadata primarily by namespace_id, such as a user's drive or a shared team space. That keeps most folder operations, permissions, and the change stream within one consistency domain. Store blobs by hash prefix or storage placement policy rather than by namespace.
Make chunked uploads resumable and commit them atomically
An upload should be a state machine, not one long request:
StartUploadauthenticates the user and returns an upload-session ID, chunk policy, expiry, and signed part URLs.- The client splits the file, computes checksums, and submits a manifest proposal.
- The service identifies chunks already present within the allowed deduplication scope.
- The client uploads missing chunks in parallel with idempotent part IDs.
CompleteUploadvalidates chunk presence, sizes, checksums, quota, and the expected base version.- A transaction creates the manifest and file version, advances the node pointer, and records an outbox or change-journal entry.
- Asynchronous workers scan content, create previews, replicate blobs, and notify clients.
Amazon S3 multipart uploads illustrate the core benefit: parts can upload independently and failed parts can be retried without restarting the object. The tus resumable upload protocol similarly lets a client query the current offset and resume. In your design, expire abandoned sessions and garbage-collect unreferenced chunks after a safety window.
Never expose a version before all chunks are durable. Key CompleteUpload by session and operation ID so retries return the existing version.
Choose chunking and deduplication boundaries deliberately
Fixed-size chunks are simple, easy to address, and support parallel transfers, but inserting bytes near the beginning shifts all later chunk boundaries. Content-defined chunking chooses boundaries from the byte stream, so local edits can reuse more old chunks, at the cost of CPU, complexity, and less predictable part sizes.
Dropbox has described files as ordered lists of hashed blocks in its streaming synchronization architecture. Its Broccoli metadata system determines needed blocks before transfer. These sources support the manifest pattern without prescribing an exact implementation.
Default to user- or tenant-scoped deduplication. Global cross-user deduplication saves more storage but can leak file existence through timing or missing-chunk responses, complicate deletion and billing, and cross permission boundaries. Encrypt chunks with scope-aware keys and require authorization before revealing whether a hash exists.
Synchronize devices with a cursor-based change journal
A desktop client maintains a local database, filesystem watcher, pending-operation journal, and last server cursor. Each sync cycle:
- Records local changes durably before attempting network calls.
- Pulls
GET /changes?cursor=...from the authoritative namespace journal. - Applies remote operations idempotently in sequence order.
- Pushes local operations with stable client operation IDs and base versions.
- Advances the local cursor only after durable application.
Google Drive's change-retrieval API uses page tokens so clients can retrieve changes without rescanning everything. Push should therefore be a hint to pull, not the source of truth. If a cursor is too old or invalid, return a resnapshot instruction and a new baseline cursor.
Keep file identity independent of path. Dropbox's discussion of rewriting its sync engine highlights how offline work, concurrent moves, and changing paths expand the state space. A stable node_id lets the server distinguish rename, move, delete, and recreate operations.
Resolve conflicts without losing user data
Each write supplies base_version_id. If it matches the current version, commit normally. If not, the client edited an older base. Text formats may use a type-specific merger, but a generic storage system should not guess how to merge arbitrary documents, archives, images, or binaries. Preserve both versions, mark the new branch as conflicted, and let the client surface a clearly named copy.
Workflow focus: every stage is retry-safe, and ambiguous concurrent edits become recoverable versions rather than silent data loss.
| Conflict | Safe default | Reason |
|---|---|---|
| Content edit vs. content edit | Keep both versions and create a conflicted copy | Opaque bytes cannot be merged safely. |
| Rename vs. rename | Choose a deterministic winner and retain the alternate name in history | Both operations target one stable node. |
| Move vs. move | Serialize by namespace sequence and expose the losing move as a conflict | Prevents divergent folder trees. |
| Delete vs. edit | Restore the edited version or place it in a recovery area | An offline edit should not disappear. |
| Permission revoke vs. edit | Reject unauthorized commit; retain the local draft only on the client | Access control outranks sync convenience. |
Validate folder moves against the directory graph so a node cannot become its own ancestor. Use server order and expected versions, not device timestamps, because clocks and networks disagree.
Model sharing, permissions, and revocation explicitly
Represent user and group permissions as ACL entries with roles such as owner, editor, and viewer. Calculate effective capability server-side for every metadata operation and download authorization. Google Drive's sharing model illustrates permission resources, roles, and inherited access.
Share links need high-entropy random tokens, a hashed representation at rest, a resource scope, optional password, expiry, and revocation. Issue short-lived signed download URLs only after authorization. Permission caches should use short TTLs plus version checks or invalidation events; a revoked principal must not receive a fresh blob URL merely because an edge cache is stale.
Log share creation, permission changes, sensitive downloads, and administrative restores in an append-only audit trail.
Define consistency, scaling, and hot-spot trade-offs
Use strong consistency for current metadata, expected-version checks, permission mutations, and the change sequence. Search, thumbnails, notifications, scans, analytics, and cross-region replicas can be eventual if the UI exposes processing state.
A hash-prefixed blob key spreads ordinary chunks, but large shared folders can hot-spot metadata and change consumers. Split namespaces by subtree only when that cost is justified; paginate change feeds and apply backpressure to slow devices.
Track logical quota separately from physical bytes. Keep reference counts outside the commit so a counter error cannot delete live chunks.
Monitor upload success, resume rate, checksum failures, commit latency, orphan bytes, sync lag, cursor resets, conflict rate, permission-denied anomalies, restore success, and replication delay.
Recover from failures and regional outages
At-least-once execution is expected. Idempotent part writes, operation IDs, conditional version commits, and ordered change sequences make duplicates harmless. A transactional outbox prevents a committed version from missing its change event. Reconciliation scans for committed manifests with absent journal entries, missing chunks, negative references, and stuck upload sessions.
Keep version history and delete markers for a retention window. Amazon S3 Versioning shows how retaining versions can recover overwritten or deleted objects. Delay physical deletion until no live manifest, retained version, legal hold, or in-progress restore references the chunk.
For regional resilience, assign each namespace a home write region. Replicate immutable blobs asynchronously, copy metadata through a durable log, and fence the old writer before failover. AWS documents S3 replication as asynchronous, so state an explicit recovery-point objective rather than promising zero data loss. Test restore procedures, replay journals, and verify invariants after failover.
A 45-minute interview walkthrough
Spend 5 minutes on scope and invariants, 7 on APIs and data, 8 on architecture, and 10 on upload and atomic commit. Use 8 minutes for sync and one conflict example, then close with sharing, failure recovery, metrics, and trade-offs. Follow the interviewer's priority: storage cost suggests chunking depth; collaboration suggests namespace ordering and conflict policy.
Frequently asked questions
What is the hardest part of cloud file storage system design?
The hardest part is maintaining one correct namespace while file bytes move independently. Commit only complete versions, preserve offline edits, enforce revocation, and recover from duplicated work without losing data.
Should file uploads pass through application servers?
Usually not for the byte path. Let application servers authenticate the request, create the upload session, enforce quota, and issue narrowly scoped signed URLs. Clients then upload chunks directly to object storage. The service still validates the manifest and atomically commits metadata before exposing the version.
How do Dropbox-style clients detect changes?
Use a local filesystem journal plus an authoritative server change feed. The client pulls ordered changes after its last cursor, applies them idempotently, pushes local operations with stable IDs and base versions, and advances the cursor only after durable application. Push notifications should only trigger a pull.
How should the system handle simultaneous edits from two devices?
Compare each commit's base_version_id with the server's current version. If one device is stale and the file type has no safe merger, keep both versions and create a visible conflicted copy. Never select a winner using device timestamps alone or silently discard one user's bytes.
Is global file deduplication worth it?
It can reduce physical storage, but cross-user deduplication introduces privacy side channels, authorization questions, deletion complexity, and confusing quota accounting. Tenant-scoped deduplication is a safer default. Discuss global deduplication only with deliberate hash-disclosure controls, encryption boundaries, and business justification.
Final takeaway
The best cloud file storage system design interview answer connects four decisions: immutable chunk storage, transactional version metadata, cursor-based synchronization, and lossless conflict handling. Start with a retry-safe upload commit, stable file IDs, and a single ordered namespace.
Then add sharing, scoped deduplication, version retention, asynchronous replication, reconciliation, and explicit failure objectives.
Sources and Further Reading
- Amazon S3 multipart upload overview
- tus resumable upload protocol
- Dropbox Engineering: Streaming File Synchronization
- Dropbox Engineering: Broccoli, Syncing Faster by Syncing Less
- Dropbox Engineering: Rewriting the Heart of Our Sync Engine
- Google Drive API: Retrieve Changes
- Google Drive API: Share Files, Folders, and Drives
- Amazon S3 Versioning
- Amazon S3 data consistency model
- Amazon S3 replication
Research note: This guide was checked on September 1, 2026. Numeric scale values are interview assumptions; production requirements vary by product, workload, and durability target.