Save Compression Tradeoffs: LZ4 vs Zstd on Game Servers, Measured

Every game server that persists a world eventually compresses something: a save snapshot, a backup archive, a rotated log. The default is almost always gzip, chosen for portability rather than speed, and it quietly converts a two-second autosave into an eight-second stall. On a survival node where autosaves run every few minutes, that stall is felt by every connected player. This article measures the real cost of gzip, LZ4, and Zstd on game save workloads and gives you a decision rule.

The Three Algorithms in One Line Each

  • gzip / zlib: high-ish ratio, slow, single-threaded, ubiquitous. Bad default for live saves.
  • LZ4: 400-700 MB/s per core, low ratio (~1.8-2.2x on save data). Ideal when latency matters more than disk space.
  • Zstd: tunable across the whole curve; levels 1-3 hit LZ4-like speed at better ratio, levels 10+ approach gzip ratio at multi-threaded speed.

Representative Benchmarks

The numbers below come from compressing a 420 MB month-old Rust world save and a 180 MB modded Minecraft region set on a 4.0 GHz core. Treat them as ratios to reproduce on your own data, not absolutes.

AlgorithmCompress speedDecompress speedRatio
gzip -628 MB/s95 MB/s3.4x
LZ4 (fast)560 MB/s2,900 MB/s2.0x
Zstd -3310 MB/s1,100 MB/s2.7x
Zstd -942 MB/s1,050 MB/s3.3x
Zstd -193 MB/s900 MB/s3.6x

What the Ratios Mean in Wall-Clock Time

At 420 MB, gzip takes roughly 15 seconds of CPU to compress and 4.4 seconds to read back. LZ4 takes under a second to compress and under 0.2 seconds to decompress. That is the entire argument. If you compress on every autosave, gzip injects 15 seconds of CPU contention into a tick loop that needs to stay under 50 ms per tick. LZ4 makes the same operation nearly free, at the cost of about 40% more disk consumption. On a modern NVMe, extra disk is cheap; tick stalls are not.

Decision Rules by Workload

  • Live autosaves (in-loop): LZ4. Never gzip. The point is to keep the stall invisible.
  • Nightly backups: Zstd -9 to -12, multi-threaded. You have minutes of headroom and want the space back.
  • Cold archives to object storage: Zstd -19 or gzip -9. Once a year, the CPU cost is irrelevant.
  • Log rotation: Zstd -3. Logs compress well and rotate frequently enough that speed matters.
  • Player-facing downloads (mod packs): Zstd with long-range matching; ratio directly cuts transfer time.

Multi-Threading and Where It Bites

Zstd supports multi-threading (-T0 uses all cores), LZ4 has a parallel variant (lz4mt), and gzip is stubbornly single-threaded unless you use pigz. On a server where the sim thread is the bottleneck, spawning eight compression threads on the same CCD as the sim thread can starve it. Pin compression workers to a separate CCD or lower their CPU weight with a cgroup so they yield to the tick loop.

Storage and IO Interaction

Compression is a CPU-for-IO trade. On a slow SATA SSD, compressing before writing can actually be faster end-to-end because you write less data, even though you burn CPU. On NVMe with power-loss protection, write bandwidth is rarely the limit, so uncompressed or LZ4 is usually optimal. Measure both: the crossover depends on your drive’s write throughput and your CPU’s spare capacity, and it moves as your world grows.

Implementing It

Most server software lets you choose or disable internal compression; check your config for a compression level or “compress save” flag and set it to fast or off. For backup tooling, switch from tar czf to tar --use-compress-program="zstd -3 -T4". For panel-managed instances, verify the panel is not silently using gzip on every autosave.

Bottom Line

Use LZ4 for anything on the critical path and Zstd for anything off it. gzip is a default, not a decision. Pair this with fast local storage from our dedicated server platform, and review the backup and snapshot strategy so compression choices support your RPO instead of sabotaging it.

Leave a Reply