Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

System Design blueprint · Cloud storage / SaaS

Cloud file storage & sync (Google Drive, Dropbox)

Clients split files into content-hashed chunks, upload only missing chunks to object storage, commit a new file version in a metadata service, and other devices pull changes from a per-user change journal. It must never lose a committed version, silently overwrite a concurrent edit, or expose a file to someone without permission.

Steps
9
Subjective questions
33
Objective questions
33

The problem and the outcome

Problem: Users edit the same files on laptops, phones and the web, often on flaky networks, and expect every device to converge without lost work. Re-uploading whole large files on each change wastes bandwidth and storage.

Outcome: Uploads resume after drops and send only changed chunks. Devices converge within seconds of a change. Conflicts surface as visible conflicted copies instead of silent data loss, and deleted or overwritten files can be restored from versions and trash.

Architecture

Desktop clientsync agent01API gatewayauth + rate limitUpload serviceresumable sessions02Chunk exists?SHA-256 lookup03Object storageimmutable chunksMetadata servicefiles + versions05Metadata DBsharded by userChange journalper-namespace seq06Notification svclong-poll / WS07Other devicesphone, web, laptop08Conflict checkbase rev current?Sharing & ACLpermission check04Trash & GCretention, refcount09chunk hashes + intentcan user write?open upload sessioncheck chunk hashesmissing chunks onlycommit chunk listcompare base revconflicted copytxn: new versionappend change seqnamespace changedpoke: new changeslist changes(cursor)GET chunks, signed URLpurge expired trashdelete refcount=0

How it works, step by step

  1. The desktop agent watches the file system, splits a changed file into fixed-size chunks (for example 4 MB), hashes each chunk with SHA-256, and sends the ordered hash list plus the base revision it edited from.
  2. The upload service opens a resumable session keyed by an upload ID; each chunk upload is idempotent, so after a network drop the client asks which chunks were received and resumes from there.
  3. For each hash the service checks the chunk index; only chunks not already stored are uploaded to object storage, which gives cross-version and (if allowed) cross-user deduplication.
  4. Before any write or read, the ACL service resolves the user's effective permission on the file, including permissions inherited from shared parent folders.
  5. Once all chunks are durable, the metadata service commits a new file version (chunk list, size, hash, author, timestamp) in a single transaction, but only if the client's base revision is still the latest; otherwise it saves the upload as a conflicted copy.
  6. The same transaction appends an entry with a monotonically increasing sequence number to the namespace's change journal, so every change is ordered and replayable.
  7. The notification service tells online devices subscribed to that namespace that something changed; the notification carries no file data, only a hint to sync.
  8. Each device calls list-changes with its last cursor, applies the returned entries in order, and downloads only chunks it does not already have locally via short-lived signed URLs.
  9. Deletes move files to trash with a retention window; background jobs purge expired trash and old versions, decrement chunk reference counts, and delete chunks from object storage only when no version references them.

Tech stack

  • Object storage (Amazon S3, Google Cloud Storage or Azure Blob) for immutable chunks
  • Sharded relational metadata store (MySQL with Vitess, or Spanner/CockroachDB for global consistency)
  • Redis or a key-value store for chunk-hash index and upload session state
  • Kafka or a durable log for change events feeding notifications and search indexing
  • WebSockets or HTTP long-polling for change notifications; APNs/FCM for mobile
  • gRPC between internal services; HTTPS with signed URLs for chunk transfer
  • CDN for hot shared-file downloads

Key design decisions

  • Separate data plane (chunks in object storage) from control plane (metadata DB), so metadata stays small, transactional and fast while bytes scale cheaply.
  • Chunks are content-addressed and immutable; a file version is just an ordered list of chunk hashes, which makes dedup, versioning and resumable upload fall out naturally.
  • Shard metadata by namespace (a user's root or a shared folder) so a folder's changes stay on one shard and a single ordered change journal per namespace is possible.
  • Notifications are hints, not data: devices always reconcile by pulling from a cursor, so missed or duplicated notifications never cause divergence.
  • On concurrent edits to binary files, keep both versions as a conflicted copy rather than attempting a merge; real-time co-editing is a separate system using OT or CRDTs.

Common mistakes

  • Deleting chunks as soon as a file is deleted, while a version in trash or another user's deduplicated file still references them; always use reference counts plus a grace period.
  • Cross-user dedup can leak information (an attacker can test whether a known file exists by watching upload behaviour); scope dedup per user or encrypt chunks per tenant when that matters.
  • Last-writer-wins on metadata silently destroys edits made offline; require a base revision on every commit.
  • Fanning out a change to millions of members of a large shared folder synchronously; push notifications must be async and coalesced per device.
  • Treating renames and moves as delete plus create, which forces full re-downloads and breaks sharing links; model them as metadata-only operations on stable file IDs.

What to measure

  • Sync latency: time from commit on one device to the change applied on another (p50/p99)
  • Upload resume success rate and bytes re-sent after interruption
  • Dedup ratio: logical bytes stored versus physical bytes in object storage
  • Conflicted-copy rate per thousand commits
  • Metadata commit p99 latency and change-journal consumer lag

Most-asked interview questions

Subjective questions 33

1How would you design upload so a 10 GB file survives a flaky mobile connection?Asked almost every time

I would split the file on the client into fixed-size chunks, hash each one, and open an upload session that returns an upload ID. Each chunk is uploaded with its hash and index, and the server stores it idempotently, so retrying the same chunk is harmless. If the connection drops, the client asks the session which chunks are confirmed and continues from the gaps, in parallel if bandwidth allows. The server verifies each chunk's hash before accepting it. Only after every chunk is durable does the client commit the file version to the metadata service, so a half-finished upload never appears as a real file. Abandoned sessions expire, and their orphaned chunks are garbage-collected unless another version already references them through dedup.

2How do devices stay in sync, and what happens when two people edit the same file offline?Asked almost every time

Every committed change is appended to a per-namespace journal with an increasing sequence number. Each device keeps a cursor. A notification service tells online devices that the namespace changed, and the device pulls changes since its cursor and applies them in order. Because notifications are just hints, a missed one only delays sync; it never causes divergence. For conflicts, each commit carries the revision the client edited from. If that revision is no longer current, the server does not overwrite. It keeps the existing version and saves the incoming one as a conflicted copy with the device name, so both users see both versions. Merging binary files automatically is unsafe; live co-editing of documents is a different system using operational transforms or CRDTs.

3Why use fixed-size chunks rather than content-defined chunking, and when would you switch?Asked almost every time

Fixed 4 MB chunks are simple, fast to compute and easy to index. They work well for files that are appended to or rewritten in place. Their weakness is insertion: add one byte near the start and every later boundary shifts, so every later hash changes and almost the whole file uploads again. Content-defined chunking runs a rolling hash, such as Rabin or FastCDC, over a sliding window and cuts wherever the hash matches a pattern. Boundaries then follow the content, so an insertion changes only one or two chunks. The costs are variable chunk sizes, more client CPU, and the need for minimum and maximum chunk bounds. I would start with fixed-size chunks and move to CDC only if measurements show real dedup gains for documents or backup-style workloads.

4Why use optimistic concurrency with a base revision instead of locking files during edits?Asked almost every time

Locks need the holder to stay reachable. A laptop that goes offline would hold its lock forever, or a lease would expire in the middle of an edit. Most files are never edited by two people at the same moment, so optimistic concurrency suits this workload. The client sends the revision it edited from, and the commit does a compare-and-set against the file's current revision inside the metadata transaction. If they match, the new version becomes current. If not, another writer won, and we save the upload as a conflicted copy instead of overwriting anything. The common case costs almost nothing, and the scheme stays correct during network partitions. Advisory locks can be added for particular apps, but they are a convenience, not the safety mechanism.

5Walk me through the core tables of the metadata service.Asked almost every time

The core tables are: - namespaces: id, owner, type (user root or shared folder). - file_entries: namespace_id, file_id, parent_id, name, is_folder, current_revision, deleted_at. - file_versions: file_id, revision, size, content_hash, author, created_at, ordered chunk list. - chunks: hash, size, storage key, refcount, state. - journal: namespace_id, seq, file_id, operation, revision. - acl: resource_id, principal, role. - upload_sessions: upload_id, user, expected hashes, expiry. The journal key is (namespace_id, seq) and the versions key is (file_id, revision). A unique constraint on (namespace_id, parent_id, name) for live entries stops duplicate names. Everything except the chunk index is sharded by namespace_id, so a commit stays a single-shard transaction.

6What privacy risk does cross-user deduplication create, and how do you mitigate it?Asked almost every time

If the server tells a client that a chunk already exists, the client learns that someone stored that exact content. This is a confirmation-of-file attack. An attacker can test guesses, such as a known document with one field varied, and see which variant skips upload. A second risk is a client that knows only a hash claiming to own the content. Mitigations: - Restrict dedup to within a user or organization. - Do dedup server-side only, where the client always uploads and the server stores the chunk once silently. This trades away bandwidth savings. - Never let knowing a hash grant access. A commit may only reference chunks the user actually uploaded or already owns. Many designs restrict cross-user dedup for these reasons.

7Describe the race between deduplication and garbage collection, and how you prevent data loss.Asked almost every time

The dangerous sequence is: 1. A chunk's refcount drops to zero. 2. A new upload checks the index, sees the chunk exists, and skips uploading it. 3. GC deletes the chunk. 4. The commit then references a missing chunk, and that version is unreadable. To prevent it, GC first marks the chunk tombstoned, so dedup checks treat it as absent. GC then waits a grace period longer than the maximum upload session lifetime, rechecks that the refcount is still zero, and only then deletes. The commit transaction verifies every referenced chunk is present and not tombstoned, and increments refcounts atomically. If verification fails, the client is told to re-upload. A periodic mark-and-sweep audit catches refcount drift.

8How would you model sharing and permissions for nested folders?Very often asked

I would store ACL entries on files and folders: principal, role such as viewer, commenter or editor, and who granted it. Effective permission is the strongest grant found on the item or any ancestor, unless a folder explicitly limits inheritance. Checking that on every request by walking the tree is expensive, so I would cache resolved permissions per user and folder and invalidate them when an ACL or a move changes the ancestry. Shared folders become their own namespace with their own change journal, so members subscribe to that journal instead of copying data. Link sharing uses an unguessable token mapped to a role and an optional expiry. Downloads still go through a permission check before the service issues a short-lived signed URL to object storage.

9How would you shard the metadata service, and what breaks with a hot namespace?Very often asked

I would shard by namespace ID. Each user root and each shared folder is its own namespace. A commit touches the file entry, the version row and the journal of one namespace, so it is a local transaction with no two-phase commit. The journal sequence comes from a per-namespace counter updated in that same transaction. The chunk index is different: it is keyed by hash, so I would shard it by hash prefix, which spreads load evenly. A huge team folder can outgrow one shard or serialize on its counter. Options are moving it to a dedicated shard or splitting large subtrees into child namespaces. Moves between namespaces become a multi-step, idempotent saga with a durable move record.

10Give me a back-of-envelope estimate for this system.Very often asked

I would state my assumptions out loud, because they are illustrative, not real figures. Assume 100 million users, 10 percent active daily, each changing 20 files a day: - Commits: 200 million a day, about 2,300 per second on average. I would plan for a peak several times higher. - Upload bytes: if the average new data after dedup is 1 MB per commit, that is roughly 200 TB a day. - Metadata: each version row is a few hundred bytes plus its chunk list, so it is tiny next to the blobs. - Connections: concurrent notification connections roughly equal the number of online devices. The takeaway is that a sharded database handles metadata QPS. Object storage bandwidth and capacity dominate cost, and reads such as list-changes and downloads outnumber writes.

11How do cursors work, and what happens when the journal is compacted past a client's cursor?Very often asked

A cursor is an opaque, ideally signed, token that encodes the namespace and the last sequence number the client applied. list-changes returns entries after that number, up to a page limit, along with a new cursor and a has_more flag. The journal cannot grow forever, so old entries are compacted to keep only the latest state per file, or are dropped after a retention window. If a client presents a cursor older than retained history, the server returns a reset error. The client then does a full paged listing and reconciles it against its local database by revision and hash. It must not delete or overwrite local edits that have not synced yet; those are uploaded with their base revision as usual.

12How would you handle encryption at rest and key management for chunks and metadata?Very often asked

All traffic uses TLS. Chunks are encrypted at rest with envelope encryption: data keys encrypt the chunks, and master keys held in a KMS wrap the data keys. Master keys can then rotate without re-encrypting every chunk. File names and paths are sensitive too, so the metadata store is also encrypted. Key scope is a trade-off. Per-user keys give strong isolation and allow crypto-shredding, where destroying a user's key makes their data unreadable, which helps with deletion requests. However, per-user keys block cross-user dedup. Convergent encryption, where the key is derived from the chunk content, restores dedup but brings back the confirmation-of-file risk. Access to the KMS is tightly audited and restricted to the storage services.

13Why hand clients signed URLs for chunk downloads, and what are the risks?Very often asked

Signed URLs let bytes flow straight from object storage or a CDN to the device, so application servers never stream file data and scale only with metadata traffic. The flow is: the metadata service checks the ACL first, then signs a URL scoped to one chunk object, GET only, with an expiry of a few minutes. The risk is leakage. Anyone holding the URL can fetch that chunk until it expires, and an issued URL cannot be recalled after a permission is revoked. Short TTLs bound that exposure. Scoping each URL to a single chunk limits the damage. Chunk keys are hashes, so they are not guessable, but security must come from the signature, not obscurity. Clients also verify the hash of whatever they download.

14Design the notification service that tells devices to sync.Very often asked

Devices hold a WebSocket or long-poll connection to a fleet of gateways. Each gateway records which namespaces its connections subscribe to in a shared registry. A commit writes an outbox row in the same transaction as the journal entry. A relay publishes that row to a message bus. Fan-out workers look up which gateways hold subscribers and push a tiny hint, such as the namespace and latest sequence number. Delivery can be lossy, because a device always calls list-changes on reconnect and periodically, so a dropped hint only delays sync. Bursts are coalesced, so a hundred commits in one second produce one hint. Gateways are stateful, so deploys drain them gradually and clients reconnect with jittered backoff.

15What happens if a client crashes after uploading chunks but before committing the version?Very often asked

The chunks sit in object storage, but no version references them yet. Nothing is visible to other devices, because the commit is the only point at which a version exists, so nobody sees a half-uploaded file. The upload session records the received chunks with an expiry. When the client restarts, it resumes with the same upload ID, finds that everything is already received, and commits. If the session expires first, those chunks are orphans. Garbage collection removes chunks that have zero references and are older than a grace period. That grace period matters: dedup may have pointed another in-flight session at the same chunk, so GC must never delete a chunk that a live session might still commit.

16How would you cache ACL decisions without making revocation unsafe?Very often asked

Resolving effective permission means walking ancestor folders, which is expensive, so I would cache computed results by user and resource, tagged with an ACL version. Any sharing change on a folder bumps the version for that subtree and publishes an invalidation, so stale entries are ignored. For safety, the high-risk paths re-check the authoritative store or use a very short TTL: committing a version, issuing a signed URL, and adding a namespace subscription. On revocation, the namespace is removed from the user's subscriptions, and their client deletes the local copy on its next sync. I would be honest in the interview that bytes already downloaded to a former collaborator's device cannot be recalled; revocation only protects future access.

17How do you make renaming or moving a folder with 100,000 files cheap?Very often asked

If every file stored its full path, a folder rename would rewrite 100,000 rows. Instead, each entry stores a parent_id, and paths are computed when needed. A move then updates one row, the folder's parent and name. It also writes one journal entry, and clients apply it by re-parenting locally. The transaction must check for cycles, rejecting a move of a folder into its own descendant. It must also check name uniqueness in the destination. Inherited permissions change automatically because resolution walks the new ancestors, though ACL caches for that subtree need invalidating. Moving across namespaces, for example into a shared folder, is heavier. It copies metadata into the target namespace, reuses chunks by reference, and removes the source, all as an idempotent saga.

18How does the client apply changes so that a crash mid-sync never corrupts local state?Very often asked

The client keeps a local database, often SQLite, holding its cursor and, for each file, the path, synced revision and content hash. It applies entries in sequence order. For each one: 1. It skips the entry if the local revision is already equal or newer, which makes reprocessing idempotent. 2. If the local file's hash differs from the last synced hash, the user edited it, so the client must not overwrite. It keeps the local edit and uploads it with its base revision, which triggers the normal conflict path. 3. Otherwise it downloads missing chunks, writes to a temp file, verifies the hash, atomically renames it into place, and updates the database. The cursor advances only after those writes are durable, so a crash means replaying a few entries, which is harmless.

19How do you guarantee that a committed version is never lost?Very often asked

The commit is acknowledged only after two things hold. First, every referenced chunk is confirmed durable in object storage, which replicates across failure zones. Second, the metadata transaction is synchronously replicated to a quorum or a standby in another zone. Beyond that: - Metadata has backups and point-in-time recovery, and the journal makes changes replayable. - Background scrubbing re-reads chunks, verifies hashes and repairs from replicas. - Cross-region disaster recovery is usually asynchronous, so the recovery point is not zero. Zero loss across regions requires synchronous cross-region commits, which add latency. - Version history and trash protect against user mistakes, and GC never deletes anything a retained version still references.

20What metrics and alerts would you put on this system?Very often asked

Key metrics: - Server side: commit latency and error rate, conflict rate, upload resume and abandonment rate, list-changes latency, notification delivery lag, GC backlog, and object storage error rates. - End to end: sync lag, the time from a commit to another device applying it, measured through client telemetry. - Integrity: refcount audit mismatches, hash verification failures, and any download that hits a missing chunk. That last one should be zero and should page immediately, because it means data loss. - Security: ACL denial spikes and unusual share or download patterns. I would define SLOs on commit success, commit latency and sync lag at a high percentile.

21Why must the server recompute chunk hashes instead of trusting the client?Very often asked

If the server trusted the client's claimed hash, a malicious client could upload garbage labelled with the hash of a popular chunk. With deduplication, every other file referencing that hash would then read the garbage, which is index poisoning. The upload service therefore computes SHA-256 over the received bytes and rejects any mismatch before the chunk enters the index. It also stores an object storage checksum for transport integrity. On download, the client verifies each chunk's hash, and the version records a whole-file hash for end-to-end verification. Background scrubbing re-verifies chunks at rest. These checks together catch bugs, bit rot and attacks.

22A shared folder has thousands of members. How do you avoid writing every change into every member's journal?Very often asked

Copying each change into each member's personal journal would turn one commit into thousands of writes. Instead, the shared folder is its own namespace with its own journal. A commit writes once. Each client tracks a separate cursor for every namespace it has mounted. When someone joins the share, their root namespace gets a single mount entry, and their client then syncs the shared namespace from the start. Only notification fan-out scales with membership, and it is lightweight, coalesced and lossy. Permission checks happen against the shared folder's ACL. When a member is removed, an unmount entry is written and their subscription is dropped.

23A new user installs the app with a million existing local files. How do you handle the first sync?Very often asked

The client hashes files in the background with CPU and disk throttling, so the laptop stays usable. It uploads small files first, because they give quick visible progress. Dedup checks are batched, sending hundreds of hashes per request, and only missing chunks upload, with bounded parallelism and resumable sessions. Commits are batched too, while each file still gets its own version and base-revision check. On the server, bulk APIs, per-account rate limits and quota reservations stop one huge account from monopolizing a shard. Progress is checkpointed in the local database, so a restart resumes instead of re-hashing everything.

24Why create a conflicted copy rather than automatically merging concurrent edits?Often asked

The sync service treats files as opaque bytes. It does not understand spreadsheet, image or database formats, and merging their bytes would very likely corrupt them. A conflicted copy keeps both versions intact, so no committed work is lost or silently overwritten, and the user decides which to keep. The copy's name includes the author's device or name and the date, so it is easy to find. Real-time co-editing products use a different model: operational transformation or CRDTs on a structured document, not whole-file sync. A sync product could later add format-aware merging for plain text, but the safe default is to preserve both sides.

25A user edits one byte in a 2 GB file. How much gets uploaded, and can you do better?Often asked

With fixed 4 MB chunks, only the chunk containing that byte changes. The client re-hashes the file, finds one new hash, and uploads about 4 MB instead of 2 GB. The new version reuses every other chunk by reference. To do better, we could compute a binary delta inside that chunk against the previous version, rsync-style, and send only the difference. The server or a worker then rebuilds the chunk. That saves bandwidth at the cost of CPU and complexity, which may matter on mobile. Compressing chunks before upload also helps for compressible data. Note that re-hashing 2 GB on the client is itself a cost; storing per-chunk modification metadata can help skip unchanged regions.

26How would the system help a user recover from ransomware that encrypted their synced files?Often asked

The ransomware's changes sync as ordinary new versions, but old versions are retained, so the original data is still there. The journal shows exactly which files changed and when. We can offer a bulk restore of a namespace to a point in time just before the attack. That restore creates new versions pointing at the old chunk lists, so it rewrites no history and costs almost no storage. Detection helps too: a burst of many files rewritten within minutes, often with high-entropy content or renamed extensions, can trigger an alert and pause sync from that device. The retention window must be long enough for users to notice the attack.

27How would you enforce storage quotas and limit abuse?Often asked

Quota should count the logical bytes of versions a user owns, not the physical bytes after dedup. Otherwise usage would depend on what other people store, which users cannot see or predict. The upload session reserves quota when it opens, so parallel uploads cannot overshoot, and the commit finalizes the reservation. Retained old versions and trash may or may not count, depending on product policy. Per-user and per-device rate limits on commits and list-changes protect shared shards. Public links can be abused for malware distribution, so they need download rate limits, scanning and a takedown path. Because of dedup, takedown removes the offending versions, and chunks are then freed only through normal refcounting.

28What makes the desktop file-system watcher hard to get right?Often asked

Watcher events are unreliable and messy: - They are coalesced or dropped. Linux inotify can overflow its queue, and macOS FSEvents batches changes. The agent therefore needs periodic rescans that compare size, mtime and, when in doubt, hashes. - Apps often write a temp file and then rename it, or write a file in several bursts. The agent debounces until the file is stable and ignores known temp patterns. - Files may be locked or still being written, so the agent retries later. - Cross-platform problems include case-insensitive file systems, characters that are invalid on Windows, path length limits, and symlinks. All of these can cause name collisions that must be resolved without losing data.

29After a regional outage, millions of clients reconnect at once. How do you avoid a thundering herd?Often asked

On the client side, reconnects and list-changes retries use exponential backoff with full jitter, and they honour Retry-After headers. On the server side, admission control and load shedding protect the metadata shards, with commits prioritized over background polling. Notification gateways come back gradually rather than all at once. list-changes must stay cheap: it is an index range scan on namespace and sequence, with page limits. Devices that are far behind simply catch up over several pages. Feature flags can temporarily slow down non-essential work such as thumbnails or GC. We would rehearse this recovery scenario in game days, not discover it during a real outage.

30How do retention, legal holds and account deletion requests interact?Often asked

Account deletion removes the user's metadata, decrements the refcounts of their chunks, and lets GC delete chunks nobody else references. Crypto-shredding per-user keys, where used, makes any remaining copies unreadable quickly. Chunks shared with other users through dedup remain, because those users still own that content. A legal hold is a flag on an account or resource that purge and GC jobs must check before deleting any version or trash entry. Holds override normal retention. Backups expire on their own schedule, so the deletion policy should state how long data may persist in backups. Every purge is logged for audit.

31What would end-to-end encryption change in this design?Often asked

With end-to-end encryption, clients encrypt chunks with keys the server never sees. That removes cross-user dedup and server-side previews, full-text search, thumbnails and malware scanning. It also means lost keys cannot be recovered by the provider. Sharing requires wrapping the folder key with each recipient's public key. Revoking someone means rotating keys for future versions, while anything they already downloaded stays readable to them. The server still sees metadata such as sizes, timing, and possibly names unless those are encrypted too. Conflict detection still works, because revisions are plain metadata. A common compromise is to offer E2EE as an optional vault for sensitive folders.

32How would you support files-on-demand so a laptop does not download everything?Often asked

The client still applies the full journal, but it creates placeholder files using OS integration: the Cloud Files API on Windows and File Provider on macOS. Placeholders carry name, size and dates but no content. When a user or app opens one, the OS calls the client, which fetches the needed chunks through signed URLs and hydrates the file. Users can pin folders to keep them fully downloaded offline. Unpinned content can be evicted by least-recently-used order when disk space runs low. Mobile apps typically default to on-demand. A local edit to a hydrated file uploads normally with its base revision.

33How would you test a sync engine to be confident it never loses data?Often asked

I would build a deterministic simulation that runs clients, server and network in one process with a seeded random scheduler. It injects drops, reordering, crashes and clock skew while random users create, edit, move and delete files. After each run it checks invariants: - No committed version is ever lost. - No edit is overwritten without a matching base revision. - All devices converge to the same tree. - Permissions are never bypassed. Failing seeds replay exactly, which makes bugs debuggable. Property-based tests cover the planner logic. Before release, a new engine can shadow-run against the old one and compare decisions, then roll out in stages with telemetry on conflicts and errors.

Objective questions 33

1Why are file chunks usually stored content-addressed by their hash?Asked almost every time
  1. AIt encrypts the chunk automatically
  2. BIdentical chunks are stored once and can be verified on upload and downloadCorrect answer
  3. CIt makes object storage faster than a database
  4. DIt removes the need for a metadata service

Why: Using the hash as the key lets the system skip uploading chunks it already has and verify integrity. A metadata service is still needed to map files and versions to chunk lists.

2Why does the client send the base revision it edited from along with the hash list?Asked almost every time
  1. ASo the server can choose which object storage region to use
  2. BSo the server can skip ACL checks for the owner
  3. CSo the server can detect a concurrent edit and avoid overwriting itCorrect answer
  4. DSo the server can compress the new chunks

Why: The commit is a compare-and-set against the current revision. A mismatch means someone else committed first, so the upload becomes a conflicted copy instead of an overwrite.

3At commit time, the client's base revision is no longer the latest. What should the metadata service do?Asked almost every time
  1. ASave the upload as a conflicted copyCorrect answer
  2. BMerge the two versions byte by byte
  3. COverwrite the latest version, because the last writer wins
  4. DReject the upload and delete its chunks

Why: A conflicted copy preserves both edits, so nothing committed is lost or silently overwritten.

4When is the metadata service allowed to commit the new file version?Asked almost every time
  1. ABefore upload starts, to reserve the revision number
  2. BAfter all other devices have downloaded the file
  3. CAs soon as the first chunk is received
  4. DOnly after all referenced chunks are durably storedCorrect answer

Why: Committing before the chunks are durable could publish a version whose data does not exist, which would break the never-lose-a-version guarantee.

5A device was offline and missed several push notifications. What keeps it consistent?Very often asked
  1. AThe server resends every missed notification in order
  2. BIt re-downloads the whole account
  3. CIt pulls all journal entries after its last saved cursorCorrect answer
  4. DIt waits for the next edit by another device

Why: Notifications are only hints. Durable, ordered change journals with client cursors let any device catch up exactly from where it left off.

6When is it safe to delete a chunk from object storage?Very often asked
  1. AAfter 24 hours, regardless of other files
  2. BNever; chunks must be kept forever
  3. CAs soon as the user deletes the file
  4. DWhen no live version, trash entry or other file references it, after a grace periodCorrect answer

Why: Because of dedup and versioning, many files can share a chunk. Reference counting plus a grace period prevents deleting data that something still needs.

7With fixed 4 MB chunking, one byte is inserted at the start of a 100 MB file. What happens?Very often asked
  1. AEssentially every chunk boundary shifts, so nearly all chunk hashes changeCorrect answer
  2. BOnly the first chunk changes
  3. CNo chunks change, because SHA-256 ignores offsets
  4. DOnly the last chunk changes

Why: Fixed boundaries are tied to byte offsets, so an insertion shifts all later content across boundaries. Content-defined chunking avoids this.

8Why does the push notification carry only a hint and no file data?Very often asked
  1. APush protocols cannot carry binary data
  2. BNotifications are lossy, and the change journal via list-changes is the source of truthCorrect answer
  3. CFile data must be encrypted, and hints need no encryption
  4. DHints are cheaper to store in object storage

Why: Devices always reconcile through list-changes with their cursor, so a lost hint only delays sync. Keeping data out of pushes also keeps permission checks in one place.

9What is the main purpose of the per-namespace monotonically increasing sequence number in the change journal?Very often asked
  1. ATo generate chunk hashes
  2. BTo give changes a total order that devices can resume from with a cursorCorrect answer
  3. CTo measure storage quota
  4. DTo count the files in the namespace

Why: A cursor holds the last sequence number applied, so a device can fetch exactly the later entries, in order, and replay them.

10Which shard key best keeps a commit within a single-shard transaction?Very often asked
  1. AChunk hash
  2. BUpload timestamp
  3. CDevice ID
  4. DNamespace IDCorrect answer

Why: The file entry, version and journal rows of one commit all belong to one namespace, so sharding by namespace keeps the transaction local.

11Why should the upload service recompute SHA-256 on the received bytes?Very often asked
  1. ATo pick the storage tier
  2. BTo stop a malicious client from poisoning the dedup index with wrong data under a valid hashCorrect answer
  3. CTo speed up the upload
  4. DBecause clients cannot compute SHA-256

Why: With dedup, a fake chunk stored under a popular hash would corrupt every file that references that hash.

12Which attack is a key risk of client-visible cross-user deduplication?Very often asked
  1. ASQL injection
  2. BConfirmation-of-file, learning whether specific content already exists on the serviceCorrect answer
  3. CClickjacking
  4. DDNS rebinding

Why: If uploads skip chunks that already exist, a client can infer that someone else stored that exact content.

13Which property should a chunk download signed URL have?Very often asked
  1. AScope to the user's whole bucket
  2. BReuse across all users for CDN efficiency
  3. CShort expiry and scope limited to a single object and the GET methodCorrect answer
  4. DNo expiry, so clients can cache it forever

Why: An issued URL cannot be revoked, so a short TTL and narrow scope limit exposure if it leaks or permission changes.

14When is it safe to physically delete a chunk?Very often asked
  1. AWhen the chunk is older than 30 days
  2. BWhen the file's owner logs out
  3. CImmediately when a file is moved to trash
  4. DWhen its refcount is zero, it has been tombstoned, and a grace period longer than any upload session has passedCorrect answer

Why: The tombstone and grace period prevent the race where an in-flight upload has deduplicated against a chunk that GC is about to delete.

15Sharing a folder with thousands of members should avoid which design?Very often asked
  1. AKeeping a separate cursor per mounted namespace
  2. BCopying every change into each member's personal journalCorrect answer
  3. CCoalescing notifications
  4. DMaking the shared folder its own namespace

Why: Per-member copies turn one commit into thousands of writes. A separate shared namespace writes each change once.

16Why must the new file version and its journal entry be written in the same transaction?Very often asked
  1. ABecause the journal stores the chunk bytes
  2. BTo avoid needing ACL checks
  3. CTo reduce storage cost
  4. DSo a version can never exist without a journal entry, which would leave devices unaware of it, and vice versaCorrect answer

Why: Atomicity guarantees every committed change is ordered and discoverable through list-changes.

17A folder is shared with you, and you open a file three levels below it. What decides your access?Very often asked
  1. AOnly the root folder of the owner's drive
  2. BThe ACL of the folder you last opened
  3. CYour effective permission from explicit grants plus those inherited from ancestor foldersCorrect answer
  4. DOnly the file's own ACL entry

Why: Permissions on a shared parent folder flow down to its descendants, so resolution walks the ancestors.

18What makes renaming a folder that contains many files a cheap operation?Often asked
  1. ARe-uploading the folder's chunks
  2. BLocking the whole namespace
  3. CStoring a full path string on every file
  4. DStoring parent_id pointers and computing paths when neededCorrect answer

Why: With parent pointers, a rename updates one row and one journal entry instead of every descendant.

19A client's cursor is older than the journal's retained history. What should happen?Often asked
  1. AThe server silently returns an empty list
  2. BThe client deletes all local files
  3. CThe server returns a reset, and the client does a full listing and reconciles without discarding unsynced local editsCorrect answer
  4. DThe client resumes from sequence zero of a new journal

Why: A full resync restores correctness, and preserving local unsynced edits avoids data loss.

20How does a resumable upload recover after a network drop?Often asked
  1. AThe client switches to a new upload ID and discards the old one
  2. BThe client restarts the whole file from byte zero
  3. CThe client asks the session which chunks were received and uploads only the restCorrect answer
  4. DThe server guesses the missing chunks

Why: Idempotent chunk uploads under a stable upload ID let the client query progress and continue from there.

21What reliably connects a committed transaction to the notification pipeline?Often asked
  1. AWriting an outbox row in the same transaction and relaying it to a message busCorrect answer
  2. BHaving clients poll object storage
  3. CCron-scanning all files every hour
  4. DSending the push before the transaction commits

Why: The transactional outbox ensures an event exists if and only if the commit happened, with no dual-write gap.

22What does convergent encryption enable, and at what cost?Often asked
  1. ASmaller chunks, at the cost of more metadata
  2. BPerfect forward secrecy, at the cost of no dedup
  3. CFaster uploads, at the cost of weaker TLS
  4. DDedup of encrypted chunks, at the cost of reintroducing the confirmation-of-file riskCorrect answer

Why: Deriving the key from the content makes identical plaintext produce identical ciphertext, which allows dedup but also allows guessing.

23In what order should a device apply entries returned by list-changes?Often asked
  1. AAlphabetically by path
  2. BStrictly in increasing sequence numberCorrect answer
  3. CIn any order, applied in parallel
  4. DLargest files first

Why: Operations such as create, move and delete depend on order, and applying them in sequence order makes the result deterministic and replayable.

24When should a commit be acknowledged to the client?Often asked
  1. AWhen the metadata transaction is durably replicated and all chunks are confirmed storedCorrect answer
  2. BWhen the request reaches the load balancer
  3. CWhen the version is written to the primary's in-memory cache
  4. DWhen a notification has been sent

Why: Acknowledging earlier could lose a committed version if a node fails.

25Over time, chunk refcounts may drift because of bugs. What is a standard safeguard?Often asked
  1. AA periodic mark-and-sweep audit comparing references from versions against refcountsCorrect answer
  2. BDoubling all refcounts
  3. CDeleting chunks older than one year
  4. DDisabling GC permanently

Why: An independent sweep from the source of truth, the versions, detects and repairs counter errors.

26Millions of clients reconnect after an outage. Which client behaviour most reduces the spike?Often asked
  1. AOpening several connections per device
  2. BRetrying immediately in a tight loop
  3. CExponential backoff with random jitterCorrect answer
  4. DReconnecting exactly on the minute

Why: Jitter spreads retries over time, so recovering servers are not overwhelmed in synchronized waves.

27What is a major consequence of end-to-end encryption for this service?Often asked
  1. AUploads no longer need chunking
  2. BThe server cannot dedup across users or generate previews and search indexesCorrect answer
  3. CIt removes the need for TLS
  4. DIt makes conflict detection impossible

Why: Without access to plaintext, server-side features that inspect content stop working.

28A user's access is revoked 2 minutes after they received a signed URL with a 5-minute expiry. What is true?Often asked
  1. AThe URL can still fetch that chunk until it expiresCorrect answer
  2. BThe URL stops working immediately
  3. CThe URL now returns a different file
  4. DThe object storage deletes the chunk

Why: Signed URLs are bearer tokens validated by signature and expiry, which is why TTLs are kept short.

29How should storage quota be measured for a user?Often asked
  1. ALogical bytes of the versions the user owns, reserved when the upload session opensCorrect answer
  2. BBytes downloaded per month
  3. CPhysical bytes after cross-user dedup
  4. DNumber of files only

Why: Logical bytes are predictable to users, and reserving quota up front prevents parallel uploads from overshooting.

30What is the size of a SHA-256 digest?Sometimes asked
  1. A128 bits
  2. B160 bits
  3. C512 bits
  4. D256 bitsCorrect answer

Why: SHA-256 produces a 256-bit, or 32-byte, digest.

31Which transport suits pushing sync hints to desktop clients?Sometimes asked
  1. ASMTP email
  2. BA WebSocket or long-poll connectionCorrect answer
  3. CFTP
  4. DBatch files over SFTP

Why: Persistent or long-poll connections let the server signal online devices with low latency.

32File-system watcher events can be dropped or coalesced. What should the desktop agent also do?Sometimes asked
  1. ATrust events only
  2. BDisable sync when an event is missed
  3. CUpload every file hourly
  4. DPeriodically rescan and compare size, mtime or hashesCorrect answer

Why: A rescan catches changes that lossy watcher APIs missed.

33A user tries to move a folder into one of its own subfolders. What should the metadata service do?Sometimes asked
  1. AMove only the files and not the folders
  2. BAllow it and fix it later
  3. CDuplicate the folder
  4. DReject it after a cycle check inside the transactionCorrect answer

Why: Allowing the move would create a cycle and detach the subtree from the root, so it must be rejected.

Track your progress through every blueprint in your dashboard.

Start learning