gzip vs zstd vs xz vs lz4: picking a compressor in 2026

Four single-file compressors, four very different trade-offs between speed and size. Which to use for backups, builds, logs and distribution, with real numbers and the commands.

formatscompressioncomparisonlinux

On Unix-like systems, compressing a file and archiving several files are separate jobs. tar bundles; something else compresses the bundle. For thirty years that something else was gzip. Today there are four serious candidates, and the best choice depends on a question people rarely ask explicitly: how many times will this file be decompressed, compared with how many times it is compressed?

The four, in one paragraph each

gzip (1992) is the compatibility baseline. Deflate compression, single-threaded by default, moderate ratio, moderate speed, and understood by everything from embedded firmware to every web server on the planet. .tar.gz is the shape most source code has shipped in since the 1990s.

xz (2009) is the ratio champion. LZMA2 compression finds long-range redundancy and produces the smallest files of the four, typically 20 to 30 percent smaller than gzip. The price is time: compression is slow and decompression, while faster, is still the slowest of the group. Linux distributions used it for packages for a decade for exactly that reason.

Zstandard (2016) is the one that changed the question. At its default level it matches gzip’s ratio while decompressing three to five times faster; at high levels it approaches xz’s ratio at a fraction of xz’s time. It is multi-threaded, has a dictionary mode for small records, and has been adopted by the Linux kernel, Arch, Fedora, Btrfs, ZFS, Parquet and HTTP (Content-Encoding: zstd in every browser since 2024).

LZ4 (2011) is the speed extreme. It skips entropy coding entirely, which makes decompression run at memory-bandwidth speed, several gigabytes per second per core, and compression nearly as fast. The ratio is the worst of the four, around 10 to 20 percent larger than gzip. It lives inside filesystems, databases and kernels where compression is a transparent speed trick, not a storage decision.

bzip2 deserves a mention only to retire it: slower than xz at compressing, slower than gzip at decompressing, and beaten on ratio by xz. Nothing new should use it.

The numbers that matter

Representative figures for a mixed source tree and logs (the exact values move with the data; the ordering does not):

Ratio (smaller is better) Compress Decompress
lz4 1.00 (largest) very fast fastest
gzip -6 0.80 slow moderate
zstd -3 0.78 fast fast
zstd -19 0.66 slow fast
xz -6 0.62 very slow slow

Two things stand out. Zstandard at its default beats gzip on every axis at once, which is why “just use zstd” is the correct default answer for new work. And Zstandard’s decompression speed barely changes with level, so paying for -19 once at build time costs nothing for every later reader; that is the property xz lacks.

By job

Distributing software or data that many people will download. Compress once, decompress thousands of times, so ratio and decompression speed both matter. zstd -19 is the modern answer; xz if the consumers’ tooling is old and every megabyte counts; gzip only if you genuinely cannot know what will unpack it.

Backups and snapshots. Written once, read rarely, but written every night. zstd -3 with -T0 (all cores) is fast enough to compress inline and small enough to matter. ZFS and Btrfs users get the same effect transparently with compression=zstd.

Logs, caches and anything on a hot path. Written and read constantly; CPU time is the cost. lz4, or zstd -1. Both are fast enough to be invisible.

Container layers, package managers, CI artifacts. Pulled far more than pushed. zstd, which is why Docker, apt, rpm and pacman have all moved to it.

Anything a web server sends. Brotli or zstd for HTTP, with gzip as the fallback for ancient clients. Pre-compress static assets at the highest level; serve them without recompressing.

Commands

# Tarballs: GNU tar picks the compressor from the flag or the extension
tar --zstd -cf src.tar.zst src/      # compress
tar -xf src.tar.zst                  # modern tar detects the format on extract
tar -I 'zstd -19 -T0' -cf src.tar.zst src/   # max ratio, all cores

tar -czf src.tar.gz src/             # gzip
tar -cJf src.tar.xz src/             # xz
tar -I lz4 -cf src.tar.lz4 src/      # lz4

# Single files
zstd -T0 bigfile                     # default level 3, keeps the original
zstd -19 --rm bigfile                # best, removes the original
zstd -d bigfile.zst                  # decompress
xz -9 -T0 bigfile
gzip -9 bigfile
lz4 -9 bigfile                       # high-compression mode, same fast decoder

# Convert without an intermediate file
gzip -dc old.tar.gz | zstd -19 -T0 -o new.tar.zst
xz -dc old.tar.xz   | zstd -19 -T0 -o new.tar.zst

Telling them apart

Each has an unmistakable signature at offset 0: gzip 1F 8B, xz FD 37 7A 58 5A 00, Zstandard 28 B5 2F FD, LZ4 04 22 4D 18, bzip2 42 5A 68 (BZh). Modern tar and file read these and do the right thing regardless of the extension, and so does the detector; a .gz that is really .zst is a renaming mistake, not a problem.

The tar signature itself is at offset 257 (ustar), which you will only see after decompressing; before that, the file looks like whatever compressed it.

The one-paragraph recommendation

Use Zstandard unless something specific stops you. Pick -3 for things you write often, -19 for things you distribute, -1 or LZ4 for things on a hot path. Keep producing .tar.gz for public source releases if your users might be on old systems, and read .tar.xz from the last decade without complaint. Do not start anything new in bzip2.