2026-09-11
Every so often you need to hand someone a patch between two binary files — a 40 GB game update, a firmware image, an ISO, a database snapshot — and you don't have rsync at both ends. diff is useless. bsdiff loves the answer but wants 8× your file size in RAM and refuses to stream. Git's binary diffs live inside packfiles, not on disk.
The right tool has been sitting in your distro since Y2K: xdelta3, Josh MacDonald's implementation of VCDIFF (RFC 3284). It produces portable patch files, streams, handles files bigger than RAM, and is on the shortlist of tools ROM hackers, indie game studios, and update-server operators actually use in production.
# make a patch between two versions
xdelta3 -e -s v1.iso v2.iso v1_to_v2.vcdiff
# reconstruct v2 from v1 + patch
xdelta3 -d -s v1.iso v1_to_v2.vcdiff v2.reconstructed.iso
sha256sum v2.iso v2.reconstructed.iso # identical
That's it. The -s flag names the source. Encoding is a single pass; decoding is fast because the format is optimized for the reader, not the writer.
The default source window is 64 MB. Feed xdelta3 a 4 GB source with the defaults and your patch will be almost as big as the target — it's only comparing against tiny slices at a time. Blow the window up to at least the size of the source:
xdelta3 -e -9 \
-B $(stat -c %s v1.iso) \
-W 16777216 \
-s v1.iso v2.iso v1_to_v2.vcdiff
-B is the source window (RAM budget for the reference), -W is the target buffer, -9 asks for maximum effort. On a real 3.5 GB game update I benchmarked, the defaults gave a 2.9 GB patch; -B 4G -9 gave 41 MB.
# patch a tarball on the fly
tar -c newtree/ | xdelta3 -e -c -s old.tar > delta.vcdiff
# apply, still streaming
xdelta3 -d -c -s old.tar delta.vcdiff | tar -x
Combined with mbuffer or pv, you can pipe deltas across an ssh link without ever materializing intermediates. This is how you ship a database dump diff without doubling your disk usage.
xdelta3 -e -9 -S djw -s old.bin new.bin patch # djw = built-in Huffman
xdelta3 -e -9 -S lzma -s old.bin new.bin patch # if built with LZMA
VCDIFF already deduplicates repeated regions; secondary compression squeezes the residual literals. On text-heavy binaries (SQL dumps, structured logs) LZMA shaves another 40–60%.
xdelta3 is the boring, portable, streamable, one-file answer. It has been shipping game patches since Half-Life 2 was new, and it will outlive most of the JavaScript runtime you're trying to save bytes on.
xdelta3 -e -9 -B $(stat -c %s src) -s src dst patch; just remember the default source window is 64 MB and quietly ruins every large-file benchmark you run without -B.
