SwadhyAI Notes

All System Design notes

System Design Case Study

Cloud File Storage

A 2 GB video drops into Google Drive or Dropbox on a laptop; a doc is edited offline on a phone; the same folder opens on a desktop, and every rename, share link, and conflict still has to make sense. To the user it is one folder. Under the hood it is a catalog plus a warehouse.

The hard part is not "put a blob in S3." It is keeping correct across devices while storing bytes efficiently with and .

What happens first?

1

Upload only new pieces to object storage.

2

One transactional write for name, ACL, chunk list.

3

Wake sync, search, and notifications.

4

Other devices catch up without full rescan.

Try it: upload, metadata, and download for file storage

Large uploads use multipart to object storage while a metadata DB owns permissions and tree listings.

  1. Client
  2. API
  3. Metadata DB
  4. Object store
  5. CDN
Highlighted hops show where the last action moved traffic. A stopped hop means backpressure, rejection, or a consistency guard blocked further progress on that path.
Parts done
0
Metadata writes
0
Mode
upload
Path hop
0

Consistency

metadata

Listing truth lives in the DB; objects alone are not enough for ACLs.

Capacity

multipart

0 transfer steps completed.

Security

signed URL

Tokens expire; revoke by rotating signing keys or object ACL.

Switch between upload and download, then advance the transfer path hop by hop.

What actually happens

The client splits the file with , hashes each piece, and asks whether that hash already exists. Known chunks skip the network; new ones upload via into object storage. Only when every required chunk is durable does the service commit : path, version, , and the ordered chunk list.

That commit also appends to a change log. Other devices later call sync with a and apply added, modified, and deleted entries. If two offline edits race, the product policy creates a conflict copy or last-writer-wins, never silently drops an edit the user thought was saved.

At HLD scale: roughly 1B users, 200M DAU, and petabytes of logical data: metadata stays strongly consistent while chunk storage can garbage-collect eventually. Sharing is just another metadata check before issuing download URLs.

How to choose the shape of the system

1. Is this a catalog fact or a byte? Names, folders, versions, and permissions belong in . Raw bytes belong in object storage keyed by hash. Mixing them makes sync and sharing brittle.

2. Can the upload resume? Large files fail mid-flight. Design and session state so retries are cheap and the final commit is atomic.

3. What if two devices diverge? Decide conflict policy early. A conflict copy is usually safer than last-writer-wins for user documents; either way, sync must converge without losing either edit.

Simple rule of thumb

Treat Drive as a strongly consistent tree pointing at . Commit metadata only after chunks are durable, fan out through a change log, and let devices catch up with a . Check before every download URL.

In simple terms: the folder view is the hard system; S3 is the warehouse. Design the catalog first.

Related building blocks

Object storage, queues, caching, and CDN for shared downloads.

High-level design diagram

Follow section 13 data flow: upload → chunk → metadata → Kafka → sync → share/download.

Cloud file storage HLD: clients through DNS CDN WAF API gateway auth, upload download metadata sync sharing trash, Cassandra metadata OpenSearch Kafka journal, S3 chunking dedup versioning, sync conflict resolver, permissions notifications preview virus scan
Sync request

API waits for metadata response

Async event

Kafka change log fan-out

Data flow

Chunks to object storage

Control flow

Sync, permissions, conflicts

Design highlights (from the diagram)

in a DB; in object storage by hash.
plus delta; WebSocket hints are optional nudges.
ACLs and expiring share links control who can view or edit.
Multipart resumable upload keeps large files reliable on flaky networks.
change log fans out sync, search, and notifications.
Version history is a graph of chunk lists; needs an explicit policy.

Architecture layer by layer

01
Clients, edge, and gateway

Web, desktop, mobile, and CLI hit a secure front door.

In plain terms: The reception desk before anyone touches the filing room.

Web and mobile clients interact with APIs, while desktop agents also watch local changes and maintain a sync database. DNS routes them to an available service region; a CDN serves static application assets and permitted downloads. The gateway authenticates users and devices, applies quotas and request limits, and routes metadata operations without proxying every large file through the application tier.

Account sign-in can use OAuth or OpenID Connect, with multi-factor authentication and device management where the product requires them. Those mechanisms establish identity; each file operation still needs a current permission decision. A device with an open sync connection must lose access when its session or membership is revoked, so long-lived connections cannot bypass policy changes.

02
File operations services

Upload, download, metadata, sync, sharing, trash.

In plain terms: Specialist clerks: intake, checkout, catalog, and lending desk.

An upload session records the intended file, base version, expected chunks, and expiry. The client uploads missing chunks with checksums and resumes only failed parts after interruption. Download authorization returns the exact committed version and supports ranged or parallel chunk reads. A completed transfer is distinct from publishing a new file version in the catalog.

Metadata operations create, move, rename, share, and delete stable file identifiers; paths are mutable views of those identifiers. Sync returns ordered changes since a device cursor, including deletion markers. Trash and restore preserve references according to a retention policy. These services must agree on version and permission checks so a stale rename or restore cannot overwrite a newer change.

03
Metadata, search, and change log

Strong consistency for names, permissions, and versions.

In plain terms: The card catalog and audit ledger, not the warehouse shelves.

The authoritative catalog stores stable file and folder identifiers, parent relationships, permissions, version pointers, and the chunk manifest for each retained version. Pick a database and transaction model that can enforce these invariants; naming a distributed key-value store does not automatically make a move, permission update, or version commit strongly consistent. Use conditional writes or appropriate transactions for the actual access pattern.

A committed metadata mutation also records a durable journal or outbox entry. A relay publishes that change to Kafka for sync notifications, search indexing, and audit processing, with replay-safe identifiers. Search can lag, but its results still need authorization before content is disclosed. The audit trail records who changed which version or permission, allowing failures and unexpected access changes to be reconstructed.

Separate . Permission checks run on every read/write path; invalidate caches when ACLs change.

04
Object storage and deduplication

Bytes live in S3/GCS; files are ordered lists of chunk hashes.

In plain terms: Warehouse bins labeled by fingerprint: many files can share one bin.

Store immutable chunks under a verified content hash and represent a file version as an ordered manifest of hashes. Fixed-size chunks are simple; content-defined chunking finds boundaries in the bytes so some small edits preserve more existing chunks. Savings depend on the workload, chunk sizes, and encryption design, so measure reuse rather than assuming a fixed percentage. Deduplication must stay within the intended tenant and authorization boundary.

Publish a manifest only after all referenced chunks are durably available and their references are protected from garbage collection. Retained versions, trash, and active uploads can all keep chunks live. A delayed reference-count event is insufficient proof that deletion is safe. Coordinate reference creation with a deleting state or pins, wait through the retention grace period, and recheck authoritative reachability before removing bytes.

changes chunk boundaries according to content; compare its reuse rate and CPU cost against fixed-size chunks using representative edits. Chunk deletion depends on the reachability of every retained file version, not merely a momentary zero counter. Upload pins and a metadata-coordinated deletion state prevent a collector from removing a chunk while a new version is acquiring a reference.

05
Sync and conflict resolution

Keep laptops, phones, and web in sync without losing edits.

In plain terms: Two people editing the same shared notebook: need rules when both change page 3 offline.

Each device keeps a local database, pending edits, and the last journal position it applied successfully. A sync response contains added, changed, and deleted entries after that cursor. Apply the delta and advance the local cursor together so a crash causes safe replay instead of skipping changes. WebSockets or SSE can announce that newer changes exist, but the client still fetches authoritative deltas.

An edit names the version on which it was based. If another device already committed a newer version, the server detects the conflict rather than silently replacing it. Preserve both versions, create a conflict copy, or apply a content-specific merge policy. If a cursor is older than journal retention, request a fresh snapshot and reconcile pending local edits instead of pretending the missing history was empty.

Clients poll or push using a . When versions diverge, apply policy, never silently drop both edits without a rule.

06
Permissions, links, and collaboration

Who can view or edit; public links with expiry.

In plain terms: Library lending cards and guest passes with expiration dates.

Permissions combine account or workspace roles with the product’s file and folder inheritance rules. Specify how inherited grants, explicit exceptions, and moves between folders interact; deny-overrides is one possible policy, not a universal filesystem rule. A share link delegates a bounded capability, such as viewing one file until expiry, and should not silently grant editing or access to sibling files.

Revocation must reach download authorization, existing sync subscriptions, and relevant caches. A previously issued signed download URL may remain usable until its own expiry unless the delivery system provides a stronger revocation mechanism, so choose the lifetime deliberately. Sharing and commenting publish asynchronous notification events, while real-time collaborative editing requires an additional merge protocol beyond ordinary file synchronization.

07
Platform, ops, and scale

Preview, virus scan, quota, observability, multi-region.

In plain terms: Building maintenance, security scans, and usage meters.

Upload completion can enqueue scanning, preview, and thumbnail jobs while metadata tracks whether the file is pending, ready, or rejected. Workers use a file-version identifier so an old preview cannot replace the output for a newer edit. Quota accounting must define logical bytes, retained versions, and physical deduplicated bytes separately; otherwise concurrent uploads can exceed a workspace limit or make the bill impossible to explain.

Measure upload completion, metadata latency, device catch-up age, failed transformations, and unreferenced-byte growth. Keep backups of the catalog and chunks with compatible recovery points, and test a restore that reconstructs an actual folder tree. Multiple regions need explicit metadata ownership, permission behavior, and recovery objectives; cache clusters, orchestration, and key management support those decisions rather than replace them.

Metadata vs chunk bytes

Keep the catalog strongly consistent; let the warehouse store hashed chunks.

Strong consistency for the catalog. This is what users mean when they say "my Drive folder."

The catalog binds a stable file identifier to its name, parent, permissions, and current version. A version holds an ordered chunk manifest, so a rename changes metadata without copying the file body. A conditional version update detects edits based on an old version instead of silently discarding concurrent work.

Upload bytes first, verify their durability, and then atomically publish the new manifest within the metadata store. This is not a distributed transaction that simultaneously writes every object. Uncommitted chunks remain protected by an upload session until they are referenced or become eligible for delayed cleanup.

Chunks

warehouse bytes. Many files can share one hashed object without copying the payload.

can preserve unchanged chunks across edits, while fixed-size chunking is cheaper to implement. The manifest supplies ordering; a hash supplies identity and an integrity check, not permission to read the bytes. Reuse must honor encryption and tenant boundaries.

Garbage collection starts from all retained version manifests, trash entries, and protected uploads. Before deletion, coordinate with concurrent reference creation and recheck the chunk’s live state. A grace period handles delayed cleanup, but it cannot replace that coordination: otherwise a newly committed file may point to bytes the collector just removed.

Core flows

Upload commits metadata only after chunks are durable.

Upload and commit

Upload chunks first and verify that every referenced chunk is durable before committing the new file version in the metadata transaction. Until that commit, the upload is incomplete and can be retried or abandoned without changing the visible file. Publish a metadata-change event with the committed version so other devices can sync. This ordering prevents a folder entry from pointing to bytes that were never successfully stored.

Diagram text: the exact Mermaid definition below preserves the nodes, labels, and connections. Enable JavaScript to view the rendered diagram.
Read the diagram definition
sequenceDiagram
    autonumber
    participant C as Client
    participant GW as API gateway
    participant UP as Upload service
    participant DD as Dedup index
    participant S3 as Object storage
    participant MD as Metadata service
    participant K as Kafka

    C->>GW: start upload session
    GW->>UP: allocate upload_id
    loop each chunk
        C->>UP: report chunk hash
        UP->>DD: lookup hash
        alt chunk exists
            DD-->>UP: ref exists (skip upload)
        else new chunk
            UP-->>C: presigned PUT URL
            C->>S3: PUT chunk bytes
            UP->>DD: register hash ref
        end
    end
    C->>GW: commit upload
    UP->>UP: verify all chunks durable
    MD->>MD: txn write file metadata + chunk list
    MD->>K: metadata-changed
    MD-->>C: file ready

Multi-device sync

Delta since cursor; optional push hint.

Diagram text: the exact Mermaid definition below preserves the nodes, labels, and connections. Enable JavaScript to view the rendered diagram.
Read the diagram definition
sequenceDiagram
    autonumber
    participant C as Client device
    participant GW as API gateway
    participant SY as Sync service
    participant MD as Metadata store
    participant K as Kafka
    participant N as Notifier

    C->>GW: POST /sync (since_cursor)
    GW->>SY: get delta
    SY->>MD: changes after cursor
    MD-->>SY: added / modified / deleted
    SY-->>C: delta + new_cursor
    Note over C: apply locally, upload local edits
    C->>GW: POST local change (version)
    GW->>SY: apply edit
    SY->>MD: compare server version
    alt version match
        MD->>MD: commit update
        MD->>K: metadata-changed (async)
        K->>N: consume event
        N-->>C: WebSocket hint (optional)
    else version mismatch
        SY->>MD: write conflict copy
        MD-->>C: conflict file + server version
    end

Download

Authenticate the requester and check current file or sharing-link permissions before issuing short-lived download access to the required chunks. A client that already has verified chunks can fetch only missing ones. Signed URLs are bearer capabilities until they expire, so revoking a share may require a short validity window or a download path that rechecks policy. Content hashes identify bytes; they must not bypass ownership checks.

Diagram text: the exact Mermaid definition below preserves the nodes, labels, and connections. Enable JavaScript to view the rendered diagram.
Read the diagram definition
sequenceDiagram
    autonumber
    participant C as Client
    participant GW as API gateway
    participant DL as Download service
    participant MD as Metadata
    participant S3 as Object storage

    C->>GW: GET download (file_id)
    GW->>DL: auth + ACL check
    DL->>MD: load chunk hash list
    DL-->>C: presigned URLs per chunk (or CDN)
    loop missing chunks
        C->>S3: GET chunk by hash
        S3-->>C: bytes
    end
    C->>C: assemble file locally

What users experience

1

Upload a large file

You: You drop a 2 GB video into your Drive folder.

System: Client chunks file, hashes each piece, uploads only new chunks to S3, then commits metadata in one transaction.

2

Edit on two laptops

You: You change a doc offline on your laptop; your desktop had an older copy.

System: Sync detects version conflict; creates conflict copy or applies last-writer-wins per product policy.

3

Share a folder link

You: You send a view-only link to a colleague.

System: Sharing service stores token + expiry; download checks ACL before presigned URLs.

Requirements

Upload / download

  • Resumable multipart
  • Range download
  • TB-scale files

Sync

  • Delta sync
  • Offline queue
  • Conflict handling

Sharing & versions

  • Link + user ACL
  • Version restore
  • Trash retention

Numbers that drive the design

2 EB
Logical storage

30% dedup saves ~600 PB physical

50 TB/d
Daily uploads

200M DAU × 5% uploaders

139K/s
Sync checks (avg)

3 devices × 20 checks/day

30%
Dedup savings

On 2 EB logical storage

Assume 200M DAU, 5% upload daily (10M uploaders), 50 TB/day at 4 MB chunks (12.5M chunks/day). Sync checks: 200M × 3 devices × 20/day = 139K QPS average. Logical storage is 2 EB; 30% dedup saves ~600 PB physical.

Case-study upgrade

File Storage and Sync Math

File sync stores bytes, metadata, permissions, versions, and sync cursors. Metadata correctness is usually harder than storing raw bytes.

Assumptions and formulas

  • Daily active users: 200M. Five percent upload daily. Chunk size: 4 MB. Logical storage: 2 EB.
  • Upload volume: 50 TB/day. Users may have multiple devices and offline edits.
  • Deduplication saves about 30% on 2 EB logical storage (~600 PB physical savings).

Concrete math

  • Uploaders: 200M x 5% = 10M uploaders/day.
  • Chunks: 50 TB/day / 4 MB = about 12.5M chunks/day = ~145 chunk commits/sec average; 10x ingest peak ≈ 1.45K dedup hash lookups/sec.
  • Chunk index: 12.5M chunks/day x 64 bytes = 800 MB/day raw; 5 years is about 1.46 TB before indexes and replication.
  • Metadata rows: 1B users x 2K files = 2T file metadata rows; at ~400 bytes/row = ~800 TB raw before indexes and replication.
  • Metadata QPS: chunk commits ~145/s avg + ACL checks and folder list ops during sync; sync-driven metadata reads share the 139K QPS sync budget.
  • Sync checks: 200M users x 3 devices x 20/day = 12B/day = 139K QPS average.
  • Sync notifications: push to 600M device endpoints (200M x 3 devices) can cut polling QPS by 80-90% versus pure pull sync.
  • Version retention: if average 5 versions per active file, physical storage multiplier is ~1.5-2x logical after 30% dedup savings.
  • Dedup savings: 30% savings on 2 EB logical storage saves about 600 PB physical storage.

Design decisions forced by numbers

  • Shard namespace metadata separately from blob storage.
  • Use upload sessions so object writes and metadata commits can be retried safely.
  • Permission changes must invalidate folder and file access caches quickly.

Scaling to millions

  • At 1M users: simple metadata store, object storage, and upload sessions are enough.
  • At 10M users: add namespace sharding, chunk index, and sync cursor service.
  • At 100M+ users: add regional metadata partitions, conflict resolution, dedup filters, and orphan cleanup.

Readable flow

Upload session
Chunk hash
Dedup check
Object write
Metadata commit
Sync cursor

Interview follow-ups to expect

  • How do rename and move work while another device edits offline?
  • How are permissions inherited and invalidated?
  • How do orphan chunks get garbage collected safely?

Operational readiness checklist

After the math, explain how this capacity plan is measured, protected, launched, and evolved.

Observability

  • Attach each capacity estimate to a dashboard metric: p99 latency, queue age, cache hit rate, shard skew, error rate, and freshness lag.
  • Alert on rate-of-change and saturation, not only hard failures; backlogs and hot keys usually warn before an outage.

Security and abuse

  • Budget for auth checks, rate limits, quota isolation, audit logging, privacy filters, and abuse-review side paths.
  • Separate trusted internal events from user-controlled input so retries and backfills cannot bypass policy checks.

Degraded modes

  • Define the fallback when a dependency is slow: stale cache, partial results, read-only mode, delayed async work, or admission control.
  • Protect the invariant first; reduce freshness, personalization, or analytics quality before risking duplicate or corrupt state.

Testing and rollout

  • Test average, peak, and hot-object traffic; include retry storms, cold caches, lagging workers, and regional dependency loss.
  • Use canaries, shadow reads, dual-write validation, feature flags, and explicit rollback criteria for risky path changes.

Rollout, backfill, and runbooks

  • Make migrations and backfills idempotent, resumable, rate-limited, and visible through progress and error metrics.
  • Write the runbook before launch: owner, dashboards, paging thresholds, mitigation switches, replay steps, and repair commands.

10x evolution

  • For file storage and sync math, state which number forces the next move: cache memory, shard count, write amplification, queue lag, egress, or failover reserve.
  • Add the next layer only when the metric forces it: sharding, regional reads, async replay, hot-key isolation, or stricter backpressure.

Sync operations and conflict drill

The byte store is easy; metadata and sync correctness are the hard parts.

SLOs and metrics

Metadata writes p99 <200ms, sync delta p99 <500ms for hot folders, 99% of device hints delivered within 30s. Watch sync cursor lag, conflict rate, orphan chunks, permission-cache age, and dedup lookup p99.

Degraded modes

If push hints fail, clients poll with backoff. If preview generation lags, raw file sync still works. If dedup index is down, upload new chunks and reconcile duplicates later.

Testing and backfill

Replay metadata change logs into a shadow sync index, chaos test metadata DB failover, load test login sync storms, and backfill permission changes through a versioned ACL invalidation queue.

10x evolution

Add namespace sharding, regional metadata partitions, chunk-index Bloom filters, selective sync, conflict analytics, and lifecycle garbage collection with sampled object existence checks.

Hard-part drill: offline conflict resolution

Two devices edit the same file offline from version 41. The first sync commits version 42; the second sees a version mismatch, uploads its chunks, creates a conflict copy linked to version 41, returns both server and local versions, and emits a metadata event so every device converges without losing either edit.

APIs worth naming

Use an upload session plus conditional commit. Chunks can arrive or retry independently; the commit verifies their hashes and protected references, checks that the base file version is still current, and publishes one manifest. Retrying the same commit returns its recorded version rather than creating duplicates. Interrupted sessions expire through cleanup, while a conflict preserves the uploaded work for the product’s merge or conflict-copy flow.

POST/api/v1/files/uploadStart/resume multipart upload session
POST/api/v1/files/upload/{id}/commitVerify stored chunks; conditionally commit the file-version manifest
GET/api/v1/files/{file_id}/downloadPresigned URLs or ranged stream
POST/api/v1/syncDelta since sync cursor
POST/api/v1/files/{id}/shareUser or link share with ACL
GET/api/v1/files/{id}/versionsVersion history

Change log

How the change log fans out

drives multi-device sync and search, not the upload byte path.

Publishers

Metadata commits append durable journal events.

Every committed metadata change appends to the journal.

metadata-changed

Metadata service

File/folder created, moved, renamed, deleted.

Record an outbox or journal entry in the same transaction as the metadata change, then publish it asynchronously. A crash between commit and broker publication is recovered by the relay. Devices use the stable change position to fetch authoritative deltas.

chunk-committed

Upload service

New chunk hash durably stored.

This event can drive accounting or analytics, but it must not be the sole authority for liveness. A version commit protects its chunk references in authoritative metadata; duplicate or reordered chunk events must not cause premature deletion. Reuse an existing hash only after validating the allowed deduplication scope.

Consumers

Workers notify, index, and audit: must tolerate replay.

Side effects stay off the upload critical path.

metadata-changed

Sync notifier

Push WebSocket/SSE to online clients.

The client still pulls the delta via the sync API: events are hints, not full state.

metadata-changed

Search indexer

Update OpenSearch document.

The index can lag behind the committed catalog because it is off the upload path. Carry a file-version identifier so delayed events cannot resurrect a deleted entry or replace a newer one, and recheck access before showing private results.

metadata-changed

Notification service

Email/push on share or comment.

A notification is an asynchronous reaction to a committed share or comment. Give it a stable event identifier and retry policy so a replay does not repeatedly alert the same recipient. A failed alert must not roll back the underlying file operation.

Simple rule of thumb

Events hint that something changed. Devices still reconcile with a and an authoritative delta API. Define before two offline editors can diverge.

Data model (core tables)

files

id PK
user_id, parent_id
name, path
version, block_refs[]
size_bytes, mime_type

Metadata only; chunk bytes in S3 by hash.

file_versions

file_id, version
block_refs[]
created_at

Immutable snapshots; share chunks across versions.

shared_access

resource_id, type
user_id or share_token
permission, expires_at

Check on every read path.

chunk_index

hash PK
size, ref_count
storage_key

Dedup lookup + GC when ref_count = 0.

Bottlenecks and failure modes

Metadata hot path

Risk: Login sync storm on metadata DB.

Mitigation: Shard by user_id; cache; read replicas for sync reads.

Orphan chunks

Risk: Upload aborted before commit.

Mitigation: GC upload sessions after TTL; ref_count on commit only.

Conflict surprise

Risk: User loses offline edit.

Mitigation: Conflict copy + clear UI; document LWW policy.

Shared link leak

Risk: Old token still works.

Mitigation: Revoke table; short TTL; audit log.

Beginner vs advanced answers

Beginner (5 min)

Keep a transactional catalog of folders, file names, permissions, and versions, while storing large immutable byte objects separately. A file version references its ordered chunk list. Resumable sessions track which chunks reached storage, and an atomic metadata commit makes the new version visible. This lets the system recover an interrupted transfer without presenting a half-uploaded file to other devices.

Advanced (deep dive)

The deeper design follows concurrent versions and their cleanup. A client uploads against a known base version; if another device committed first, a conditional update creates a conflict outcome rather than silently overwriting that edit. Devices consume a metadata journal with durable cursors. Garbage collection deletes chunks only after retained versions, active uploads, and readers can no longer reference them.

Choosing and explaining Cloud file storage

A complete explanation connects the mechanism to a requirement. Describe what improves when you introduce it, which new failure cases become possible, and how you would know that the trade-off is worthwhile.

Explain the core idea

Metadata transaction commits only after chunks are durable.

Files are ordered chunk hashes; storage is content-addressed.

Sync uses cursors; conflicts need an explicit policy.

When it belongs

Design Google Drive, Dropbox, or iCloud-style storage.

They ask about sync, dedup, or sharing permissions.

They probe offline edit conflicts.

How it fails

Metadata points at chunks not yet uploaded.

Full tree scan every sync instead of cursor.

Permission cache stale after revoke.

Trade-offs to weigh

Fixed-size vs content-defined chunking.

Last-writer-wins vs conflict copies.

Strong metadata consistency vs multi-region latency.

Common misunderstandings

Storing file bytes inside the metadata database.

Skipping ACL check on presigned download URLs.

No garbage collection for unreferenced chunks.

Deeper walkthrough

File storage deeper walkthrough

Hard part is metadata, permissions, sync, and versions, not storing bytes in S3.

Requirement refinements

Clarify max file size, folder sharing, offline edits, version retention, public links.

Rule: committed metadata references only durable chunks.

API design details

The upload session records the owner, expected base version, and each chunk hash and size. Verify uploaded bytes against the declared hash before marking a part complete. Final commit conditionally creates the new metadata version only when all required chunks are durable, making a lost response safely retryable with the same operation ID.

A sync cursor marks a position in the namespace change journal, not the current wall clock. Return changes after that position and a next cursor; the device saves the cursor only after applying the page locally. If the cursor predates retained history, request a fresh snapshot and resume from its boundary instead of pretending the device is current.

Data model and storage

Namespace metadata separate from content-addressed chunks.

Versions as metadata snapshots referencing chunk lists.

Scaling strategy

Shard metadata by owner/namespace; CDN for hot shared downloads.

Deduplication lets identical chunks share storage, but scope the dedup index according to tenant privacy and encryption boundaries. Identical plaintext encrypted under different random keys will not have identical ciphertext. Never reveal whether another tenant owns a chunk merely by exposing a dedup lookup result or skipping its authorization checks.

Reliability, recovery, and operations

An abandoned session can leave uploaded chunks with no committed file reference. Reclaim them after a grace period and a reference check that accounts for concurrent commits, retained versions, and active readers. Expiry alone must not delete a chunk that another completed file still uses. Measure orphan bytes and validate collection with sampled restore or download checks.

Monitor sync lag, upload failure rate, orphan chunk count, conflict rate.

Deepening reference

File Storage and Sync: realistic production notes

Beginner mental model: A file storage system is metadata consistency plus chunked object storage plus device sync.

Production scope: The hard part is not only storing bytes. It is reconciling offline edits, permissions, sharing links, version history, deduplication, and efficient sync across devices.

Choose what the first version must guarantee

Start by deciding which file storage and sync capabilities are essential. Describe the main read and write operations before choosing infrastructure. For each operation, identify the stored records it uses and the condition that makes its result correct. A fast response is useful only if it satisfies that condition.

Next, separate work the user must wait for from work that can finish later. Estimate requests per second, storage growth, and the busiest object or customer. Use those estimates to choose one bottleneck to investigate. The calculations below are example workloads with stated assumptions; they are not measured limits of a particular product.

Concrete capacity calculations

Users: 200M DAU. Five percent upload daily = 10M uploaders/day. Upload volume: 50 TB/day.

Chunks: 50 TB/day / 4 MB = about 12.5M chunks/day. Chunk index: 12.5M x 64 bytes = 800 MB/day raw; 5 years is about 1.46 TB before indexes and replication.

Sync checks: 200M users x 3 devices x 20/day = 12B/day = 139K QPS average; push notifications can reduce polling.

Logical storage: 2 EB before dedup. Dedup savings: 30% on 2 EB saves about 600 PB physical storage.

Metadata scale: 1B users x 2K files average = 2T file metadata rows; shard namespace metadata and cache active folders.

Upload throughput: 50 TB/day = about 580 MB/sec average ingest; plan for peak multipliers during business hours.

Scaling to millions of users

Separate metadata transactions from chunk/object storage. Commit file metadata only after required chunks are durable.

Partition namespaces by owner_id or team_id; partition chunks by content hash so duplicate content naturally maps to the same chunk key.

Use a durable change log per namespace so clients sync with a cursor instead of scanning folders.

Cache downloads at the edge only after permission checks issue short-lived signed references.

Handle offline conflicts by preserving both versions rather than silently overwriting.

Sequence and data-flow diagram

Walk this path after the high-level design so it is clear what is synchronous, what is asynchronous, and where the system can degrade safely.

Diagram text: the exact Mermaid definition below preserves the nodes, labels, and connections. Enable JavaScript to view the rendered diagram.
Read the diagram definition
sequenceDiagram
  participant Client
  participant M as Metadata service
  participant O as Object storage
  participant L as Change log
  participant Sync as Sync worker
  Client->>M: Create upload session
  Client->>O: Upload missing chunks
  Client->>M: Commit file manifest
  M->>L: Append namespace change
  Sync->>L: Read changes by cursor
  Sync-->>Client: Notify other devices

Core flow to walk through

1

Upload: split file into chunks, hash chunks, upload missing chunks, commit metadata atomically.

2

Sync: client sends local cursor, server returns ordered change log since that cursor.

3

Share: permission check resolves user ACL, folder inheritance, and optional public link token.

Production readiness

File Storage and Sync: ship, operate, and evolve

Now examine the same request flow during failures and deployments. Tie each operational control to the user behavior it protects.

Observability

Track file storage and sync p95/p99 latency, error rate, saturation, and user-visible freshness separately for read, write, and async paths.

Alert on leading indicators such as queue age, hot-key skew, cache miss storms, reconciliation mismatches, and error-budget burn.

Security and abuse

Enforce authentication, authorization, rate limits, input validation, audit trails, and privacy checks at the service boundary.

Treat abuse controls as a first-class path: throttling, quota isolation, moderation hooks, revocation, and safe handling of sensitive data.

Degraded modes

Name what still works if cache, search, ranking, stream processing, object storage, or a regional dependency is slow.

Prefer stale-but-safe reads, partial results, async retry, admission control, and feature disablement over corrupting core state.

Testing and rollout

Load test average, peak, and hot-object traffic; add failure-injection for retries, timeouts, backlog growth, and dependency outages.

Ship with canaries, shadow reads or dual writes when useful, rollback switches, schema compatibility checks, and replay validation.

Runbooks

Document dashboards, paging thresholds, owner actions, rollback steps, data repair commands, and customer-impact language.

Keep backfills and replays idempotent, resumable, rate-limited, and observable so repair work does not create a second incident.

10x evolution

Say which metric forces the next architecture change: shard count, cache footprint, write amplification, queue lag, p99 latency, or regional failover reserve.

Evolve one bottleneck at a time: partition by access pattern, isolate hot tenants, regionalize reads, add replayable async pipelines, then harden multi-region behavior.

Hard parts worth deepening

Use content-addressed chunks for dedup and resumable upload.

Keep metadata transactions separate from object storage writes; commit only after chunks are durable.

Conflict copies are often better UX than silent last-writer-wins.

Folder moves need careful subtree metadata updates or logical path indirection.

Failure modes and recovery

Upload completes but metadata commit fails; garbage collect unreferenced chunks later.

Two devices edit offline; create conflict versions and let user resolve.

Public share token leaks; support revocation and token rotation.

Hot shared file overloads origin; cache downloads through CDN with permission-aware URLs.

Signals to monitor

Sync lag measures how long a committed change takes to appear on another device. Pair it with metadata transaction latency to distinguish a slow authoritative write from delayed change-log consumption.

Upload resume success shows whether interrupted uploads recover without starting again. Deduplication savings compare logical file bytes with unique stored bytes, while share-permission errors reveal access checks that reject valid users or admit invalid ones.

ChoiceBest whenCost
Chunk dedupLarge files and repeated content are common.More metadata and chunk management.
Whole-file storageFiles are small and simplicity matters.Poor resumability and dedup.
Change-log syncMany clients sync incrementally.Requires durable per-user or per-namespace log.

Try this scenario

Explain how two laptops editing the same offline file converge without losing either version.

Takeaway

Remember the Drive drop: the folder tree is the product. Chunk and dedup the bytes, commit metadata only when storage is durable, fan out through a change log, and let devices catch up with a sync cursor. Protect every download with ACLs, and treat conflicts as a product decision, not an afterthought.

Primary sources

Practice and further reading

Use these exercises to connect the lesson to a design decision. State your assumptions, trace what happens to one request, and explain the rule that must remain true even during a failure. That rule is the design's correctness invariant.

Focus for this lesson: Design chunk upload, metadata atomicity, sync cursors, rename/move, offline conflict, dedup privacy, version recovery, quotas, and garbage collection.

Explain the decision

Why separate file metadata from immutable chunks?

Read the reasoning

Metadata needs transactional namespace operations while chunks need scalable durable blob storage and content/version lifecycle.

Apply it to a production scenario

Metadata commit fails after all chunks upload. What happens?

Read one approach

Keep upload intent and content hashes, retry finalize idempotently, and garbage-collect unreferenced chunks only after a safe grace window.

Work through the numbers

Ten million users store 20 GB each with 30% dedup and 1.5x protection overhead. Estimate physical bytes.

Read the worked calculation

200 PB logical × 0.70 × 1.5 = 210 PB, before versions, metadata, and temporary uploads.

Reason through a failure

What must rename guarantee?

Read the recovery reasoning

Namespace readers see the file at old or new path according to one atomic metadata version, never both as independent authoritative files.