Skip to content
Go back

Compression in 2026: zstd Changed the Game

· Updated:
By KingPin 8 min read
Compression in 2026: zstd Changed the Game
Contents

The Compression Triangle Nobody Wanted

For most of the 2010s, Linux compression was a depressing trade-off between three bad options.

gzip, Fast enough to not hate your life, but the compression ratio is basically “well, it’s smaller than before.” In our measurements gzip -6 shrank a 256 MiB SQL dump to about 20% of its size and a container image to about 36%, and that’s the low end of the modern field. The upside: every system on Earth has gunzip. You will never be stranded.

bzip2, Better ratio than gzip. Also 2 to 11 times slower to compress in our tests, and the slowest of the bunch to decompress. A bzip2 backup job on a big dataset is the kind of thing you start before lunch and check on after your afternoon standup. If the ratio gain was worth the wait… honestly, usually it wasn’t.

xz, The nuclear option. Excellent compression ratios. Also painfully slow at its high levels. For years it ran on one core, CPU-maxed, “maybe tomorrow” territory for large datasets (xz gained a -T threads option in 5.2.0 in 2014, and only made it the default in 5.6.0 in 2024). You used it for distribution tarballs and release artifacts, things you compress once and decompress occasionally. Never for anything time-sensitive.

Every choice was a compromise. Then 2016 happened.

Facebook Dropped a Gift on the World

Yann Collet at Facebook released Zstandard (zstd) 1.0 in 2016, and the pitch sounded too good: gzip speed or better, with much better ratios.

We later measured it. zstd vs lz4 vs gzip vs xz: Measured runs 19 configs on four public 256 MiB data sets (single thread, median of 3 runs, zstd 1.5.7, xz 5.8.4, gzip 1.14, bzip2 1.0.8). An earlier version of this post showed a benchmark table we could not trace to a test run, so we replaced it with these numbers:

Single threadLogs ratioSQL dump ratioContainer image ratioCompress speed (SQL dump)
gzip -612.5x5.11x2.80x53 MiB/s
bzip2 -920.5x6.40x3.12x13 MiB/s
zstd -316.2x5.22x3.00x228 MiB/s
zstd -1924.0x6.94x3.82x1.9 MiB/s
xz -624.0x7.25x4.19x3.1 MiB/s

zstd -3 is 4 to 6 times faster than gzip -6 to compress, decompresses faster too, and gets a better ratio on every compressible data set. bzip2 still gets a better ratio than zstd -3, but it pays for that with compression 13 to 45 times slower than zstd -3 and the slowest decompression in the test.

The high end surprised us. zstd -19 does not beat xz at its own game: single-threaded xz -6 was faster than zstd -19 on every compressible data set, and smaller on two of three. Where zstd wins is the restore. zstd -19 output decompressed 3.6 to 6.5 times faster than xz -6 output. You pay at compress time, not decompress time, which matters for anything you compress once and restore under pressure.

Who Already Made the Switch

You’re probably already using zstd without realizing it.

The Linux kernel can compress its modules with zstd (CONFIG_MODULE_COMPRESS_ZSTD, since 5.13) and can boot from a zstd-compressed kernel image.

Docker can push image layers as zstd (docker buildx build --output type=image,compression=zstd,...). It is opt-in: the buildx default is still gzip, because older registries and runtimes can’t read zstd layers.

Btrfs and ZFS both support zstd as transparent filesystem compression (Btrfs since kernel 4.14, OpenZFS since 2.0). zstd beats zlib on speed and ratio. ZFS still defaults to lz4, which compresses about 2 times faster than zstd -1 in our tests at a worse ratio, a fair trade for a filesystem that compresses every write.

Basic Usage, It’s Exactly What You’d Expect

Terminal window
# Compress a file
zstd file.txt
# Creates file.txt.zst, keeps original
# Decompress
unzstd file.txt.zst
# or: zstd -d file.txt.zst
# Compress in-place (remove original)
zstd --rm file.txt
# Decompress to stdout
zstd -dc file.txt.zst | less

The .zst extension. Clean, unambiguous. No legacy baggage.

Level Tuning, This Is Where It Gets Interesting

zstd has 22 compression levels. Default is 3.

Terminal window
# Default (level 3): faster than gzip, better ratio
zstd file.tar
# Faster than default, slightly worse ratio
zstd -1 file.tar
# Middle ground
zstd -9 file.tar
# High compression (slower)
zstd -19 file.tar
# Ludicrous mode
zstd --ultra -22 file.tar

For most backup and transfer use cases, level 3 is the right answer. You’re already beating gzip’s ratio at gzip’s speed. Levels 1-3 are everyday drivers. Levels 10-19 are for “I have time and I want the ratio.” Level 22 is for when you enjoy suffering slightly.

Parallel Compression, The Part bzip2 Wishes It Had

This is the one that changes the math on large datasets:

Terminal window
# Use all available CPU cores
zstd -T0 bigarchive.tar
# Use 4 cores explicitly
zstd -T4 bigarchive.tar
# High compression + all cores
zstd -19 -T0 massive.tar

-T0 detects and uses the number of physical cores (add --auto-threads=logical to count hyperthreads too). In our tests, zstd -3 -T4 on four physical cores compressed about 4 times faster than one thread, with an identical ratio. bzip2’s parallel version (pbzip2) exists but it’s a separate binary and not universally available. xz has native threads too (xz -T0), and since xz 5.6.0 it uses them by default.

Every time I see someone running a bzip2 backup job in 2026 I want to send them this article.

tar + zstd, The Archive You Actually Want

tar got native zstd support in version 1.31 (2019). Most modern Linux systems have it.

Terminal window
# Create archive
tar --zstd -cvf archive.tar.zst directory/
# Extract
tar --zstd -xvf archive.tar.zst
# Alternative: pipe to zstd manually (works on older tar)
tar -cvf - directory/ | zstd -T0 > archive.tar.zst
# Extract the manual way
zstd -dc archive.tar.zst | tar -xvf -
# Check your tar version supports --zstd
tar --version

If --zstd isn’t available on your system, the pipe approach works everywhere. The -I flag lets you specify the compression program:

Terminal window
tar -I zstd -cvf archive.tar.zst directory/
tar -I "zstd -19 -T0" -cvf archive.tar.zst directory/

Streaming, Ship Data Faster

This is where zstd’s decompression speed shines. Compress on one end, decompress on the other, minimal CPU overhead at the destination:

Terminal window
# Copy a large file over SSH with compression
cat bigfile | zstd | ssh remotehost "zstd -d > /destination/bigfile"
# Database dump over the wire
pg_dump mydb | zstd | ssh remotehost "zstd -d | psql targetdb"
# Or with tar, streaming a directory
tar -cvf - /data/dir | zstd -T0 | ssh remotehost "zstd -d | tar -xvf - -C /restore/"

The fast decompress speed means the receiving end barely notices the CPU cost. You’re essentially getting compression for free on the destination side.

When to Still Use the Old Formats

Look, I’m not here to tell you to rewrite all your scripts tonight. Here’s the decision table:

Use CaseUse ThisWhy
Everyday backupszstd -3Fast, good ratio, parallel
Maximum archival compressionxz -6 or zstd -19xz compresses faster and usually smaller; zstd decompresses 3.6-6.5x faster
HTTP transfer encodinggzipUniversal browser/server support
Log files you rotatezstdFast enough to not add cron lag
Distribution tarballsxzUniversal expectation, tooling
Sharing with random external systemsgzipEvery system has gunzip, zero risk
Filesystem-level compression (Btrfs/ZFS)lz4 or zstd (low level)lz4 when CPU is the limit, zstd for a better ratio
Docker imageszstd (opt-in)Faster layer decompression, but the buildx default is still gzip for compatibility

Keep using gzip when: compatibility with old or external systems is a hard requirement. HTTP Content-Encoding: gzip is the lingua franca of the web. That’s not changing.

Keep using xz when: you’re making a tarball that’ll go on a distro mirror and you need to hit the smallest possible size. One-time compress, rare decompress, xz’s pain point disappears. Use xz -6, not -9: in our tests -9 gained under 3% and needed 675 MiB of RAM to compress versus 95 MiB.

Stop using bzip2 when: now. Today. Unless something explicitly requires it. There is no scenario where bzip2 beats zstd on both ratio and speed simultaneously. It doesn’t exist.

One Install, Zero Regrets

Terminal window
# Debian/Ubuntu
sudo apt install zstd
# RHEL/Fedora/Rocky
sudo dnf install zstd
# Arch
sudo pacman -S zstd
# Check version
zstd --version

Most modern distros already have it. You might already be done.


The compression landscape finally has a sensible default. zstd didn’t win by being flashy, it won by solving the actual problem: nobody wants to choose between speed and ratio. Facebook’s engineers said “what if you didn’t have to?” and then proved it.

Your 2 AM restore job will thank you.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Self-Hoster's Disaster Recovery: When Everything Goes Wrong at Once
Next Post
Ollama Keep Alive: Unload Models from VRAM

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts