Introduction
Modern enterprise systems — collaboration platforms, document management, CAD repositories and content delivery networks — need robust file synchronization that works at scale. Users expect near-real-time sync across many devices, efficient use of bandwidth, reliable version history, and safe conflict handling. A naive upload-everything approach soon breaks: it consumes bandwidth, increases storage cost and forces long sync delays.
This article describes a production-ready architecture and implementation patterns for a High-Scale File Sync Service that:
Detects local and server-side changes efficiently
Transfers only deltas (changed chunks) instead of whole files
Tracks versions, parents, and history reliably
Resolves conflicts safely and provides clear UX for users
Works offline and supports resumable syncs
Scales horizontally and secures data at rest and in transit
Examples and code snippets use Angular for the client and .NET (ASP.NET Core) for the backend. Diagrams follow the block-style format you chose.
Goals and Non-Goals
Goals
Minimise uploaded bytes using chunking and delta/diff transfer
Provide exact version history with facile replay and rollback
Support concurrent edits with deterministic conflict strategies
Keep sync latency low and resource usage predictable
Offer robust retry, resume and partial-sync behaviour
Non-Goals
This article does not implement an OT/CRDT merge engine for arbitrary binary formats (that is complex and format-specific). For text documents, CRDTs or operational transform approaches are recommended separately.
High-Level Architecture
┌──────────────────────────────┐
│ Angular Client(s) │
│ (Detect change, chunking, │
│ delta upload, conflict UI) │
└───────────────┬──────────────┘
│ HTTPS / WebSocket / SignalR
▼
┌───────────────┴──────────────┐
│ Sync Gateway API │
│ (auth, request validation, │
│ routing, tenant resolution)│
└───────┬────────────┬─────────┘
│ │
│ ▼
│ ┌──────────────┐
│ │ Sync Engine │
│ │ (delta, queue,│
│ │ versioning) │
│ └────┬─────────┘
│ │
┌───────▼──────┐ ┌─▼──────────┐
│ Chunk Storage│ │ Metadata DB│
│ (object store│ │ (versions, │
│ S3/Blob) │ │ locks, refs)│
└──────────────┘ └─────────────┘
│ │
▼ ▼
CDN / Edge / Monitoring,
Backup Metrics, Audit
Core Components
1. Change Detector (Client Side)
Detect file changes using file system watchers or application-level events. For robust delta transfer, compute chunk-level hashes:
Split file into fixed-size chunks (e.g., 4 MiB) or use variable-size rolling chunks (Rsync-style; better for insertions).
Compute SHA-256 (recommended) per chunk. Keep list
chunkHashes[].
Client sends minimal metadata: file id (or path), file size, last-modified, chunkHashes, and root hash.
Why chunk hashing on client?
Server compares hashes to its latest version and requests only missing chunks.
It reduces unnecessary transfers on large files with small edits.
2. Delta Engine (Server Side)
Delta Engine determines which chunks are new and responds with an upload plan:
missingChunks = clientChunkHashes - serverKnownHashesServer returns upload URLs (pre-signed) for only missing chunks or an instruction to send a binary patch (bsdiff) depending on algorithm chosen.
3. Chunk Storage / Blob Store
Store chunks in object store (S3, Azure Blob, GCS) using content-addressable keys: sha256(chunk) or fileId/version/chunkIndex. Content-addressable storage avoids duplication across tenants and versions.
Keep two stores conceptually:
Chunk store: immutable chunk blobs
File manifests: metadata that lists chunk sequence for a particular file version (Merkle root, chunk list)
4. Version Manager / Manifest
A version manifest records:
fileId,versionId,parentVersionId,chunkHashes[],createdBy,createdAt,changeTyperootHash(Merkle root computed over chunk hashes)
Manifest is small JSON; write it to metadata DB atomically once all missing chunks uploaded.
5. Conflict Resolver
If two clients modify the same base version concurrently:
Detect by comparing the base
parentVersionId.Strategies:
Forking: create parallel versions and present both to user for manual merge.
Auto-merge for text: use three-way merge if file is text and merges cleanly.
Manual resolve: preserve both versions, mark conflict and show UI to merge or choose.
Prefer preserving both versions rather than deleting or silently overwriting.
Chunking Strategies and Delta Algorithms
Fixed-size chunking
Simple, fast, predictable offsets.
Poor for insertions (shifts all subsequent chunks).
Rolling hash / Content-defined chunking
Uses Rabin fingerprinting to find boundaries that remain stable with insert/delete.
Used by rsync, Dropbox. Better delta detection for many real-world edits.
Binary diffs
If both sides have similar versions, bsdiff/xdelta produce compact binary patches.
Require both versions locally or server-assisted chunk comparison. Good for very specific binary formats.
Merkle Tree for Integrity
Arrange chunk hashes into a Merkle tree; store root in manifest.
Helps detect tampering and quickly verify integrity on client or server.

Join the conversation! Your thoughts help the community grow.