01 — Prior Art: How Dropbox (and Others) Sync

Answers: How does Dropbox sync work? Plus the lessons we take from Syncthing (P2P) and rsync (delta), and what BitVault adopts vs rejects. Designing a sync engine without studying these is malpractice; the failure modes are subtle and hard-won.


1. Dropbox: the legacy engine and why it was rewritten

Dropbox’s original “Sync Engine Classic” represented sync as outstanding activity — a set of in-flight operations (uploads, downloads) keyed by path. Two structural flaws drove a four-year, ground-up rewrite (codename Nucleus, shipped ~2020, written in Rust):

  1. Path-keyed nodes: a rename of a folder became O(n) deletes + adds for every descendant — slow, and a correctness minefield under concurrency.
  2. Activity, not state: representing what’s in flight makes it nearly impossible to reason about correctness after crashes, reorderings, and offline edits. There was no canonical “what should be true” to recompute from.

2. Nucleus: three trees + a planner (the model we adopt)

Nucleus persists state, as three trees, each an internally-consistent filesystem snapshot:

Tree Meaning
Remote latest state of the user’s Dropbox in the cloud
Local last observed state on disk
Synced last state known to be fully synced between Remote and Local (the merge base)

“The Synced Tree is the key innovation that lets the system unambiguously derive the correct sync result.” By comparing Local and Remote each against Synced, you know whether a node changed locally, remotely, or both.

The Planner is the core algorithm: it takes the three trees (collectively the “Canopy”) and outputs a series of operations that incrementally converge them. After each operation, the Synced tree advances toward the others. Other notable choices:

3. Dropbox: how clients learn about remote changes (the protocol)

Dropbox’s change-detection protocol (public API mirrors the internal design):

We adopt this almost verbatim (07, ADR-0024): cursor over our change journal (ADR-0008), a lightweight notification to trigger pulls, jitter against thundering herds, and a 409-style cursor-reset recovery path.

4. Dropbox: how file content moves (delta)

Dropbox splits files into ~4 MiB content blocks, hashes each, and uploads only blocks whose hashes are new (“Streaming File Synchronization”), with block-level dedup across a user’s files. We do the same with content-defined chunking (storage/02) — CDC is more robust to inserts than fixed blocks — and per-tenant dedup (storage/03).

5. Syncthing: the P2P contrast (and why we’re not P2P)

Syncthing synchronizes a cluster of peers with no central authority, via the Block Exchange Protocol (BEP):

What we take: the conflicted-copy naming convention, the edit-beats-delete safety, and “scan is authoritative.” What we reject: version vectors and a global-model merge — BitVault has a central authority (the server journal), which gives a total order for free, so we use the simpler, stronger three-tree + cursor model and avoid per-file vector clocks. (Version vectors would be mandatory if BitVault were peer-to-peer; it is not.)

6. rsync: the delta alternative we don’t need (but should understand)

rsync computes a delta when only the receiver knows its own bytes: the receiver splits its file into fixed blocks and sends a weak rolling checksum (Adler-32) + strong checksum (MD4) per block; the sender rolls the weak checksum over every byte offset, and on a weak match verifies the strong checksum, then sends references + literal data.

7. Lessons → BitVault decisions

Lesson (source) BitVault decision
State (3 trees) beats activity (Dropbox) Three-tree planner (ADR-0022)
Node IDs, not paths (Dropbox) Stable node IDs; O(1) renames (08)
Cursor + longpoll + 409 reset (Dropbox) Cursor over journal + notify + reset (ADR-0024)
Block-level dedup delta (Dropbox) CDC + per-tenant dedup (storage/03)
Conflicted copies, edit-beats-delete (Syncthing) Same policy (ADR-0026)
Scan is authoritative (both) Watcher-as-hint + rescan (ADR-0025)
Central authority avoids vector clocks (vs Syncthing) Server journal = total order (ADR-0022)
Pure planner enables exhaustive testing (Dropbox) Planner is a pure function; property-tested

References