Markdown Editor

File Sync System Design Template (Reference Design)

45-minute path, content-defined chunking, per-account dedupe, commit protocol, journal cursors and push, three-tree conflict handling, failure modes

시스템 설계전체LBFS content-defined chunking (SOSP 2001); public Dropbox engineering write-ups (cited)designfilesyncmath

사용법: Use it when designing a sync folder, backup client or any service that keeps files in step across devices. Fill the chunking, dedupe scope and conflict rules first, with product and support. The main pitfall is last-writer-wins, which silently drops a concurrent edit.

미리보기

System Design: [File sync service name]

Reference design for a cloud file sync service in the style of consumer and business "sync folder" products: a desktop and mobile client keeps a local folder in step with the cloud and with the user's other devices. It covers content-defined chunking (as introduced by the Low-Bandwidth File System, SOSP 2001), content-addressed deduplication and its privacy side channel, the commit protocol between metadata and block storage, change journals and push notifications, and conflict handling with a three-tree model. It follows the structure of the System Design Document template, adds a 45-minute interview path, access-pattern and failure-mode tables and a cited "How real systems do it" box that paraphrases public engineering write-ups, and is pre-filled with a worked design to adapt. Replace every [bracketed] value and every row marked Example; values marked Example are assumptions, not benchmarks.

Document control

FieldValue
Document ID[SDD-SYNC-001]
System / feature[File sync and sharing]
Version[0.1]
Status[Draft / In review / Approved / Implemented / Superseded]
Owner[@owner]
Author(s)[@author]
Reviewers[@reviewer-1], [@reviewer-2]
Last updatedYYYY-MM-DD
Classification[Internal]
DifficultyAdvanced
Clients in scope[Windows, macOS, Linux desktop; iOS and Android on-demand]
Related[Object storage design], [Notification service design], [ADR: chunking scheme]

Approvals

RoleNameDecisionDate
Tech lead[@name][Approved / Changes requested]YYYY-MM-DD
Staff / principal engineer[@name][Decision]YYYY-MM-DD
Client platform lead[@name][Decision]YYYY-MM-DD
SRE / storage[@name][Decision]YYYY-MM-DD
Security and privacy[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summary
0.1YYYY-MM-DD[@name]First draft for design review
0.2YYYY-MM-DD[@name]Example: Switched from fixed 4 MB blocks to content-defined chunks after the edit-pattern study
0.3YYYY-MM-DD[@name]Example: Limited deduplication to one account after the privacy review
1.0YYYY-MM-DD[@name]Example: Approved

Contents

1. Overview

1.1 Problem statement

[Example: Our first sync client uploads whole files on every save and polls the server every 60 seconds. A one-line change to a 200 MB design file re-uploads 200 MB, laptops on hotel Wi-Fi fall hours behind, and when two devices edit the same file the later upload silently replaces the earlier one. Support logs about 400 "lost edit" tickets a month.]

1.2 Proposed solution

[Example: The client splits files into content-defined chunks (average 1 MB, bounded 256 KB to 4 MB) and identifies each chunk by its SHA-256 hash. A save becomes a commit of the file's ordered chunk list to the metadata service; the server answers with the chunks it does not already have in the account, the client uploads only those to the block service, and the commit completes with an optimistic-concurrency check on the file's parent revision. Each committed change is appended to a per-namespace journal, and a notification service tells the user's other online devices to pull changes since their cursor. Conflicting edits never overwrite: the losing version is saved beside the original as a conflicted copy.]

1.3 Decisions requested from reviewers

IDQuestionRecommended optionSection
Q-01Example: Fixed blocks or content-defined chunks?Content-defined, average 1 MB7.1
Q-02Example: Deduplicate across all users or per account?Per account, to close the cross-user side channel7.2
Q-03Example: How do devices learn about changes?Persistent connection per device plus journal cursor; poll as fallback7.3
Q-04Example: What happens on a conflicting edit?Keep both; the later commit becomes a conflicted copy7.4
[Q-nn][Question][Option][Section]

1.4 45-minute interview path

Use this order when the document serves an interview or a short design review. The written sections below are the long form of each step.

MinutesCoverOutput on the whiteboard
0 to 5Scope: upload, sync across devices, share a folder, version history; below-the-line items (2.3)Four user actions
5 to 10Estimates: stored bytes, commits per second, connected devices, metadata rows (section 3)Four numbers with consequences
10 to 15Interface: commit with chunk list, upload chunk, list changes since cursor (section 4)Three calls
15 to 25High-level design: client, metadata service, block service, object storage, notifications (section 6)One diagram
25 to 40One deep dive: chunking and the commit protocol (default, 7.1 and 7.5), or conflict handling (7.4), or notifications at scale (7.3)Options, choice, reason
40 to 45Failures (partial upload, metadata shard down), the 10x row in section 10Two failure rows

Start the default deep dive with the naive answer, upload the whole file on every change, and show the cost of a small edit to a large file. Then try fixed-size blocks and show that inserting one byte shifts every later block. Finish with content-defined chunking and the "commit, need chunks, upload, commit again" protocol.

2. Requirements

2.1 Core functional requirements

IDRequirementPriority
FR-01Example: Sync additions, edits, renames, moves and deletes between the cloud and every linked deviceMust
FR-02Example: Upload only changed content after a small edit to a large fileMust
FR-03Example: Propagate a change to the user's other online devices quicklyMust
FR-04Example: Never silently overwrite a concurrent edit; keep both versionsMust
FR-05Example: Share a folder with other users with view or edit rightsMust
FR-06Example: Keep file versions and deleted files restorable for 30 daysMust
FR-07Example: Resume interrupted uploads and downloadsMust
FR-08Example: Selective sync and files-on-demand placeholders on desktopShould
[FR-nn][Requirement][Must / Should / Could]

2.2 Non-functional requirements

IDQualityTargetMeasured as
NFR-01DurabilityExample: No committed file version lost; 11 nines object durability from the storage layerStorage provider figures plus audit scrubbing
NFR-02Sync latencyExample: Small change visible on another online device within 5 s (p95)Synthetic two-device canary
NFR-03Bandwidth efficiencyExample: A 1 KB insertion in a 200 MB file uploads at most 8 MBClient benchmark
NFR-04CorrectnessExample: Zero silent overwrites; every conflict produces a conflicted copyRandomised simulation tests (7.6)
NFR-05AvailabilityExample: Metadata API 99.95% monthly; clients keep working offlineAPI success rate
NFR-06Client footprintExample: Idle CPU under 1%; hashing throttled on batteryClient telemetry (opt-in)
[NFR-nn][Quality][Target][Measurement]

2.3 Below the line (out of scope)

Name these explicitly so reviewers and interviewers do not pull the design toward them.

  • [Example: real-time co-editing inside documents (see the collaborative editing design)]
  • [Example: full-text search over file contents]
  • [Example: client-side end-to-end encryption (would disable server-side deduplication and previews)]
  • [Example: the object storage system itself (see system-design/design-object-storage)]
  • [Item deferred, with the release that will take it]

3. Capacity estimation

3.1 Assumptions

InputSymbolValueSource
Registered active usersUUExample: 10 millionProduct plan
Daily active usersDDExample: 4 millionProduct plan
Linked devices per uservvExample: 2.5Pilot data
Average stored bytes per useruuExample: 12 GBPilot data
Saving from per-account deduplicationggExample: 20%Pilot data
Erasure-coding overheadooExample: 1.4xStorage layer
File commits per daily active user per dayccExample: 20Pilot data
New bytes uploaded per commit (after dedupe)nnExample: 0.6 MBPilot data
Other devices that download each changemmExample: 1.5Pilot data
Files per userFuF_uExample: 8 000Pilot data
Share of a daily user's devices online at peakwwExample: 0.6Pilot data

3.2 Storage

Slogical=U×u=107×12 GB=120 PB,Sraw=Slogical×(1−g)×o=120×0.8×1.4=134.4 PBS_{logical} = U \times u = 10^{7} \times 12 \ \text{GB} = 120 \ \text{PB}, \qquad S_{raw} = S_{logical} \times (1 - g) \times o = 120 \times 0.8 \times 1.4 = 134.4 \ \text{PB}

Consequence: content belongs in an erasure-coded object store; the sync service never stores bytes itself, only chunk references.

3.3 Commit and transfer rate

C=D×c=4×106×20=8×107 commits/day,rˉ=8×10786 400≈926/s,rpeak=3rˉ≈2 778/sC = D \times c = 4 \times 10^{6} \times 20 = 8 \times 10^{7} \ \text{commits/day}, \qquad \bar{r} = \frac{8 \times 10^{7}}{86\,400} \approx 926/\text{s}, \qquad r_{peak} = 3\bar{r} \approx 2\,778/\text{s}
FlowFormulaPer dayRate
UploadC×nC \times n48 TB4.4 Gbit/s average, 13.3 Gbit/s at peak
DownloadC×n×mC \times n \times m72 TB6.7 Gbit/s average
Change notificationsC×mC \times m120 millionAbout 4 170/s at peak

Consequence: uploads and downloads go straight between clients and the block service in the nearest region; metadata servers never proxy bytes.

3.4 Metadata

Nfiles=U×Fu=107×8 000=8×1010,M=8×1010×300 B=24 TBN_{files} = U \times F_u = 10^{7} \times 8\,000 = 8 \times 10^{10}, \qquad M = 8 \times 10^{10} \times 300 \ \text{B} = 24 \ \text{TB}

With an average of 1.6 chunks per file (most files are one small chunk, large files have many), files reference about 128 billion chunks, or about 102 billion unique chunks after the 20% deduplication saving; a chunk index entry of 64 B makes the chunk index about 6.6 TB. A commit costs about 5 metadata writes (file row, version row, chunk references, journal entry, quota), so peak writes are about 13 900/s. Consequence: shard metadata by namespace from day one; 64 shards hold about 375 GB and take about 217 writes/s each at peak.

3.5 Connected devices

Nconn=D×v×w=4×106×2.5×0.6=6×106N_{conn} = D \times v \times w = 4 \times 10^{6} \times 2.5 \times 0.6 = 6 \times 10^{6}

At 100 000 idle persistent connections per notification server that is 60 servers, or 90 with 1.5x headroom. Consequence: notifications are a separate tier from the metadata API.

3.6 Summary

QuantityEstimateDesign consequence
Stored content120 PB logical, 134.4 PB rawErasure-coded object storage
CommitsAbout 2 800/s at peakMetadata sharded by namespace
Transfer48 TB up, 72 TB down per dayDirect client-to-block-service transfers
Metadata80 billion file rows, 24 TB64 shards to start
Connections6 million concurrentDedicated notification tier, 90 servers

4. API design

4.1 Interfaces

InterfaceOperationPurpose
Metadata APIPOST /v1/namespaces/{ns}/commitsCommit a file version as an ordered chunk list
Block APIPUT /v1/chunks/{sha256} (or a pre-signed URL)Upload one chunk; idempotent by hash
Block APIGET /v1/chunks/{sha256}Download one chunk
Metadata APIGET /v1/namespaces/{ns}/changes?cursor=List journal entries after a cursor, paged
NotificationWS /v1/notify with namespace cursorsPush "namespace changed" signals
Metadata APIPOST /v1/namespaces/{ns}/movesAtomic move or rename by file ID
Sharing APIPOST /v1/sharesMount a shared namespace for another user

4.2 Commit request and responses

The client sends the path, the stable file ID, the revision it edited (its parent) and the chunk hashes in order. The commit is idempotent through the Idempotency-Key header so a retried commit never creates two versions.

{"file_id": "f_5Q2M8X", "path": "/Projects/brochure.indd", "parent_rev": 41, "size": 209715200, "chunks": ["9a1f3c", "77be02", "c4d815"], "client_mtime": "2026-10-30T08:12:44Z", "device_id": "dev_mac_02"}

If any chunk is unknown in the account, the server answers 409 with the missing hashes, and the client uploads them and retries:

{"type": "https://api.example.com/problems/need-chunks", "title": "Chunks missing", "status": 409, "missing": ["c4d815"]}

If parent_rev is no longer the latest revision, the server answers with a conflict problem that carries the current revision, and the client follows 7.4. The chunk hashes above are shortened for the example; real requests carry full 64-character SHA-256 values.

5. Data model

5.1 Entities

A namespace is a user's root or a shared folder; it is the unit of sharding, journaling and permission.

5.2 Storage choices

DataStoreKeyMain queriesWhy
Namespaces, files, versions, journalExample: Sharded relational database, 64 shardsns_idCommit transaction, list changes after cursorOne namespace's commit is a single-shard transaction
Chunk indexSharded key-value store(account_id, chunk_hash)Which chunks exist, reference countsPoint lookups, high volume
Chunk contentErasure-coded object storageOpaque blob keyGet and put by keyDurable and cheap at petabyte scale
Device cursorsNotification tier memory plus client local databasedevice_id, ns_idWho to notifyRebuilt from clients on reconnect
Client stateLocal embedded database on each devicePath and file IDRemote, local and synced trees (7.4)Works offline

5.3 Access patterns

Access patternFrequencyKey or index that serves itPartition key rationale
Commit a file versionAbout 2 800/s at peakns_id shard, row for (ns_id, file_id)A namespace never spans shards, so the commit is one local transaction
Find missing chunksEvery commitChunk index by (account_id, chunk_hash)Account scope matches the dedupe scope (7.2)
List changes since cursorEvery notification, every reconnectJournal (ns_id, journal_id) rangeMonotonic journal IDs per namespace make the cursor a single number
Download a chunk72 TB/dayBlob key from the chunk indexObject storage spreads keys itself
Restore a deleted fileRare(ns_id, file_id) with deleted=true, versions kept 30 daysSame shard as the live file
Fan out a change to devicesAbout 4 170/s at peakSubscriptions by ns_id on notification serversShared folders notify every member's devices through one key

6. High-level design

Metadata and content take separate paths: small, consistent writes to the metadata service; large, idempotent transfers to the block service.

ComponentResponsibilityScales by
File watcherDetect local changes from operating system events, with periodic rescansOne per device
Chunker and hasherSplit files into content-defined chunks and hash themDevice CPU, throttled
Sync plannerCompare remote, local and synced trees and plan uploads, downloads and conflictsOne per device
Metadata serviceCommits, journal, moves, permissionsStateless instances over 64 shards
Block serviceAuthenticated chunk transfer, hash verificationStateless instances per region
Notification serviceHold device connections and push change signalsConnections, 100 000 per server
Chunk garbage collectorDelete chunks with zero references after the retention periodBatch workers

7. Detailed design

The deep dives in this section, each with options, choice and reason:

Deep diveOptions consideredChoiceReasonSection
ChunkingWhole file; fixed-size blocks; rsync-style rolling diff; content-defined chunksContent-defined chunks, average 1 MBInsertions change only nearby chunks7.1
Deduplication scopeNone; per account; globalPer accountMost saving, no cross-user side channel7.2
Change notificationPolling; long polling; persistent connectionPersistent connection plus journal cursorSeconds of latency without polling cost7.3
ConflictsLast writer wins; lock files; keep bothKeep both with a conflicted copyNo silent data loss7.4

7.1 Chunking

SchemeSmall insertion in a 200 MB fileNotes
Whole file200 MB uploadedSimple, wasteful
Fixed 4 MB blocks50 blocks; an insertion at 100 MB shifts every later boundary, so 25 blocks (100 MB) changeSimple, parallel hashing; good for appends and in-place edits only
Content-defined chunks, average 1 MBAbout 200 chunks; boundaries move with the content, so about 2 chunks (about 2 MB) changeBoundaries chosen by a rolling hash over a small window

Content-defined chunking slides a rolling hash (for example a Rabin fingerprint) over a small window of bytes and declares a boundary wherever the hash matches a chosen bit pattern. Because boundaries depend on content, not on offsets, an insertion only affects the chunks around it. Minimum and maximum sizes (here 256 KB and 4 MB) stop pathological inputs, such as long runs of zeros, from producing tiny or huge chunks. Each chunk is hashed with SHA-256; the hash is its identity everywhere in the system.

7.2 Deduplication and its side channel

When chunks are deduplicated across all users, an upload that completes instantly tells the uploader that someone already stored that content. Harnik, Pinkas and Shulman-Peleg (IEEE Security and Privacy, 2010) showed that this lets an attacker test whether a specific file, or a file with a guessed secret in it, exists in other users' storage. This design deduplicates within one account only: versions of the same file, copies and moves are the bulk of the saving (the 20% in 3.1), and no answer about other users' content ever leaves the server. Shared folders deduplicate within the namespace owner's account.

7.3 Change journal and notifications

Every commit appends an entry with the next journal_id to its namespace's journal in the same transaction as the file update. A device keeps one cursor (the last journal_id applied) per namespace. The notification service only sends "namespace X changed"; the device then calls list changes since cursor. Notifications are therefore hints: a lost or duplicated signal costs at most one extra call, and correctness rests entirely on the journal. Clients that cannot keep a WebSocket open fall back to long polling, and every client also pulls on reconnect and every 10 minutes as a safety net.

7.4 Conflict handling with three trees

The client keeps three trees in its local database: the remote tree (what the server last reported), the local tree (what is on disk) and the synced tree (the last state where both agreed). The synced tree is the merge base: comparing each side with it shows which side changed.

Remote vs. syncedLocal vs. syncedAction
UnchangedChangedUpload (commit with parent_rev from synced)
ChangedUnchangedDownload and apply
ChangedChanged, same content hashMark synced, nothing to transfer
ChangedChanged, different contentConflict: keep remote as the file, save local as a conflicted copy
DeletedChangedEdit wins: re-upload as a new file at the same path
ChangedDeletedEdit wins: download the remote version again

Moves and renames use the stable file_id, so a rename on one device and an edit on another merge cleanly. The server enforces the same rule: a commit whose parent_rev is stale is rejected, never applied over the newer revision. The conflicted copy is named [name] (conflicted copy, [device], YYYY-MM-DD).[ext] so users can find it.

7.5 Commit protocol

The block service verifies that uploaded bytes hash to the name they were uploaded under, so a buggy or hostile client cannot poison the chunk store. Chunks uploaded but never committed are deleted by the garbage collector after 24 hours.

7.6 Testing sync correctness

Sync bugs are rare interleavings: a rename during an upload, a delete during a download, a crash between two steps. Run the planner with a deterministic scheduler against a simulated file system and server, generate random operation sequences from a seed, and check invariants after each step (no file lost, trees converge, no silent overwrite). A failing seed reproduces the bug exactly.

7.7 How real systems do it

How real systems do it (paraphrased, not copied). In "Streaming File Synchronization" (Dropbox tech blog, Nipunn Koorapati, 10 July 2014), Dropbox describes splitting files into 4 MB blocks identified by SHA-256 hashes. A client commits a file's list of block hashes to a metadata server, which replies with the blocks it still needs; the client uploads those to a block server and commits again. The post explains how letting other devices start fetching blocks before the commit finishes improved multi-device sync time. In "Rewriting the heart of our sync engine" (Sujay Jayakar, 9 March 2020), Dropbox explains why it rebuilt its desktop sync engine in Rust: files gained stable identifiers, moves became atomic, and most logic moved onto one deterministic control thread so that pseudorandom simulation tests could reproduce any failure from its seed. A companion post, "Testing sync at Dropbox" (Isaac Goldberg, 20 April 2020), describes the remote, local and synced trees used as a merge base, the model adopted in 7.4. This design differs on one point: it uses content-defined chunks instead of fixed blocks to cut re-uploads after insertions. Read the originals in 12.3.

8. Scalability and performance

ConcernApproachLimit before redesign
Metadata writes64 shards by namespaceExample: about 2 000 writes/s per shard, 9x current peak
Very large shared namespacesJournal paging; split hot namespaces onto dedicated shardsExample: namespaces above 50 million files
Chunk transfersParallel chunk uploads (4 per file), resumable by chunkClient uplink
Notifications100 000 connections per server; subscriptions by namespaceFan-out for namespaces shared with thousands of members
Client hashingRehash only files whose size or modification time changedVery large files on slow disks

Sync latency budget for a small change between two online devices (NFR-02, 5 s p95):

StepBudget
File watcher debounce1.0 s
Chunk and hash (small file)0.2 s
Commit, need chunks, upload, commit1.2 s
Notification push0.5 s
List changes and download1.0 s
Headroom1.1 s

9. Reliability, security and operations

9.1 Failure modes

ComponentFailureDetectionBlast radiusMitigationRTO
Metadata shardPrimary failsCommit error rate per shardNamespaces on one of 64 shards cannot commit; clients queue locallySynchronous replica failover; clients retry with idempotency keysExample: 30 s
Block serviceRegion outageTransfer error rateUploads and downloads in that regionClients switch to another region; object storage is multi-zoneExample: 5 min
Notification tierServer crashConnection count dropDevices on that server miss pushesReconnect with backoff, pull since cursor on reconnectExample: 1 min
ClientCrash mid-uploadNot needed on serverOne device's pending changesLocal state DB is transactional; resume per chunkExample: next start
Garbage collectorDeletes a referenced chunkScrubber finds missing blobFiles that use the chunkTwo-phase delete (mark, wait 7 days, delete); restore from versioned bucketExample: 4 h
Client releaseBug corrupts local treesSpike in conflicted copies or rescansUsers on the new versionStaged rollout, kill switch, full rescan rebuilds treesExample: 24 h
[Component][Failure][Signal][Scope][Mitigation][Time]

9.2 Security and privacy

ThreatControl
Learning other users' content through deduplicationPer-account dedupe scope (7.2)
Chunk poisoning (bytes that do not match the hash)Block service verifies SHA-256 on upload
Stolen device keeps syncingDevice unlinking revokes tokens and can wipe the local folder at next contact
Over-sharingShare links expire by default; audit log of share changes
Data at restEncryption at rest with keys per storage unit; TLS in transit
Malware in shared foldersVersion history and bulk restore after mass changes; alert on mass encryption patterns
[Threat][Control]

9.3 Observability

SignalMetric or logAlert threshold
Sync latencyCanary pair end-to-end timeAbove 5 s p95 for 10 min
Commit conflictsStale parent_rev rejections per 1 000 commitsDoubling vs. 7-day baseline
Conflicted copies createdPer client versionSpike after a release
Need-chunks ratioCommits answered with missing chunksSudden drop (dedupe broken) or rise
Orphan chunksUploaded but uncommitted after 24 hAbove 1% of uploads
Scrubber errorsBlobs failing checksumAny

9.4 Cost estimate

ItemUnit costQuantityMonthly cost
Object storage[$/PB-month]134.4 PB raw[$]
Egress for downloads[$/TB]About 2 160 TB (72 TB x 30)[$]
Metadata database[$/shard-month]64 shards with replicas[$]
Notification servers[$/instance-month]90[$]
Total[$]

10. Trade-offs and alternatives

DecisionOptionsChosenWhyWhat we give up
ChunkingFixed 4 MB; content-definedContent-defined, average 1 MBInsertions upload about 2 MB instead of 100 MB in the 7.1 exampleAbout 4x more chunk references than 4 MB blocks
Dedupe scopeGlobal; per accountPer accountCloses the side channelLower saving on popular shared files
ConsistencyEventual everywhere; strong per namespaceStrong per namespace, journal orderedSimple client logic, atomic movesCross-namespace moves need a two-step protocol
NotificationsPolling; push plus cursorPush plus cursorSeconds, not minutes6 million connections to run
ConflictsLast writer wins; locks; keep bothKeep bothNo silent lossUsers must merge conflicted copies
What changes at 10x / 0.1x10x (about 27 800 commits/s, 60 million connections): grow to about 640 shards or a distributed SQL store keyed by namespace, regional notification tiers, and per-namespace journals split by subtree for the largest shared folders. 0.1x (about 280 commits/s): one replicated relational database, a single notification cluster and a managed object store; polling every 30 s is acceptableReview at each doubling of commitsMetadata shards and connections grow first[Note]
[Decision][Options][Chosen][Why][Cost]

11. Delivery plan and risks

11.1 Milestones

MilestoneScopeExit criterionTarget date
M1Metadata service, block service, desktop client with fixed chunkingSimulation tests green for 10 million seedsYYYY-MM-DD
M2Content-defined chunking and per-account dedupeNFR-03 met on benchmark filesYYYY-MM-DD
M3Notifications and journal cursorsNFR-02 met on canary pairsYYYY-MM-DD
M4Shared folders and mobile files-on-demandBeta users report zero lost edits for 30 daysYYYY-MM-DD

11.2 Rollout and rollback

[Example: Release the client to 1% of users, then 10%, 50% and 100%, each stage held for 7 days and gated on the conflicted-copy rate and rescan rate. The server keeps accepting the old commit format for two client versions, so a client rollback needs no server change.]

11.3 Risks

IDRiskLikelihoodImpactMitigationOwner
R-01Example: A client bug deletes files across devicesLowHighMass-delete detection pauses sync and asks the user; 30-day restore[@name]
R-02Example: Large shared namespaces overload one shardMediumMediumDedicated shards for top namespaces; journal paging[@name]
R-03Example: Hashing drains laptop batteriesMediumLowThrottle on battery; skip unchanged size and time[@name]
R-04Example: File systems differ in case sensitivity and path rulesHighMediumNormalise names, detect case-only conflicts, per-OS tests[@name]
[R-nn][Risk][L / M / H][L / M / H][Mitigation][@name]

12. Appendices

12.1 Open questions

IDQuestionOwnerDue
OQ-01Example: Offer end-to-end encrypted folders, accepting no dedupe or previews there?[@name]YYYY-MM-DD
OQ-02Example: How long are versions kept on paid plans?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

12.2 Glossary

TermMeaning
NamespaceA root folder (a user's own or a shared folder) that is the unit of journaling and permission
ChunkA piece of file content identified by its SHA-256 hash
Content-defined chunkingChoosing chunk boundaries from the content with a rolling hash, so edits move few boundaries
JournalOrdered list of changes per namespace; the cursor is the last applied entry
Synced treeThe client's record of the last state where local and remote agreed; the merge base
Conflicted copyA second file holding the losing side of a concurrent edit
Parent revisionThe revision a client edited, checked at commit for optimistic concurrency
[Term][Meaning]

12.3 References

ReferenceUse
Muthitacharoen A., Chen B., Mazieres D., "A low-bandwidth network file system", SOSP 2001, pp. 174-187, doi:10.1145/502034.502052Content-defined chunking with Rabin fingerprints and minimum and maximum chunk sizes, 7.1
Harnik D., Pinkas B., Shulman-Peleg A., "Side Channels in Cloud Services: Deduplication in Cloud Storage", IEEE Security and Privacy 8(6), pp. 40-47, 2010, doi:10.1109/MSP.2010.187Dedupe side channel, 7.2
Koorapati N., "Streaming File Synchronization", Dropbox tech blog, 10 July 20147.7
Jayakar S., "Rewriting the heart of our sync engine", Dropbox tech blog, 9 March 20207.6, 7.7
Goldberg I., "Testing sync at Dropbox", Dropbox tech blog, 20 April 2020Three trees in 7.4
Collaborative Editing System Design (system-design/design-collaborative-editing)Real-time co-editing, out of scope here
Notification Service System Design (system-design/design-notification-service)Push delivery patterns
Distributed Key-Value Store System Design (system-design/design-distributed-kv-store)Chunk index store
Photo Sharing System Design (system-design/design-photo-sharing)Blob storage and upload patterns
Object Storage System Design (system-design/design-object-storage)Erasure-coded store behind the block service
Distributed File System Design (system-design/design-distributed-file-system)Server-side file system alternative to client sync
Back-of-Envelope Estimation and Capacity Model (system-design/back-of-envelope-estimation)Method for section 3

Standard and licence note

Based on common industry practice for file synchronisation and on the published papers and engineering write-ups cited in 12.3. The Dropbox posts are paraphrased in 7.7 only; no text, figures or code were copied, the fictional service and every number in this template are illustrative examples computed for this design, and nothing here describes any company's current system. Original text written for this collection. Template licence: MIT.

관련 템플릿