2026-07-03
You know the problem. Your nightly build produces a 4 GB ISO. You've got last week's copy sitting on disk. Only about 80 MB has actually changed. Yet curl and wget will happily redownload the entire thing, and rsync refuses to help unless the other end runs an rsync daemon or gives you SSH. Meanwhile you're staring at a plain nginx that serves static files and nothing else.
zsync — written by Colin Phipps in 2004, still shipping in every major distro — is rsync's algorithm ported to run entirely over HTTP Range requests. The server side is just a static file host. All the intelligence lives in the client and a small precomputed checksum file.
The workflow is two commands:
# On the server, once per release:
zsyncmake -o ubuntu-26.04.iso.zsync ubuntu-26.04.iso
# On the client:
zsync https://releases.example.com/ubuntu-26.04.iso.zsync
The .zsync file is a small (a few MB for a 4 GB target) index of rolling checksums for every block of the source file. The client reads it, then scans any file matching ubuntu-*.iso in the current directory using the same rolling checksum. Whatever blocks match, it reuses. Whatever doesn't, it grabs with a single batched HTTP Range request against the real file URL embedded in the .zsync.
Point it at an unrelated file and it'll still find whatever coincidental blocks match:
$ zsync -i ubuntu-25.10.iso https://.../ubuntu-26.04.iso.zsync
reading seed file ubuntu-25.10.iso: **************
Read 4194304 KB. Target 82.7% complete.
downloading from https://.../ubuntu-26.04.iso:
################## 100.0% 38.2 MBps
verifying download...checksum matches OK
used 3467 local, fetched 727 remote
82.7% of the target was reconstructed from last release's ISO. Only 727 MB actually crossed the wire. No daemon, no SSH key, no torrent swarm — just Range: bytes=... against the same nginx you already had.
The genuinely clever bits nobody mentions:
zsync -i old1.iso -i old2.iso ... — hand it every candidate you've got. It'll pick blocks from whichever seed has them.zsyncmake -Z operates on .gz files in a way that preserves rsync-friendliness across the gzip boundary — normally a nightmare because a one-byte insertion changes every downstream byte in the gzip stream.Where zsync earns its keep in 2026: internal artifact mirrors (CI produces a 6 GB Docker export nightly, developers pull deltas), disk image golden-master distribution, database dump snapshots, ML model weights that shift a few layers between checkpoints. Anywhere a large file changes slowly and lives behind a boring web server.
What zsync won't do: encrypted transports of the delta plan (the .zsync reveals block hashes), streaming decompression during download, or peer-to-peer swarming. For that, look at casync — systemd's content-addressed successor concept — but be warned it demands a very different server-side story. zsync's charm is that it demands nothing of your server that a 1998 Apache install didn't already provide.
