Compression tradeoffs
Compression spends CPU to save bytes, and whether that trade pays depends
entirely on which resource is scarce. On a slow network almost any codec wins;
on a fast local link, compressing can be slower than sending the data raw. The
decision is codec, level, and placement, made from the real bottleneck, not a
default set once and forgotten.
Method
- Identify the scarce resource first. Compress only when bytes cost more
than the CPU to shrink them: a metered or slow link, expensive storage, a
bandwidth-bound transfer. If the link is fast and the CPU is hot, compression
can lose; measure before assuming it helps.
- Pick the codec by the ratio-versus-speed curve. LZ4 and Snappy compress
and decompress fastest at a modest ratio, good for hot internal traffic and
on-disk blocks. Zstd is the strong default: near-LZ4 speed at low levels,
near gzip ratio higher up, tunable across the range. Gzip is the
compatible-everywhere middle. Brotli reaches the best ratio for static web
assets at high CPU cost.
- Tune the level to the access pattern, not the maximum. Compress-once
read-many data (static assets, cold archives) justifies a high level (brotli
11, zstd 19) because the CPU is amortized over every read. Compress-once
read-once streaming data wants a low fast level; a high level there just adds
latency for bytes nobody rereads.
- Place compression where it fits the resource. Compress web responses at
the CDN or gateway edge, database and log storage at rest, internal RPC only
when the payload and link make it pay. Precompress static assets at build
time so the server serves a stored
.br or .gz, not one recomputed per
request.
- Never double-compress or compress the incompressible. Already-compressed
data (JPEG, PNG, MP4, an encrypted or gzipped blob) gains nothing and wastes
CPU; skip it. Content negotiation must not re-gzip a body the origin already
compressed.
- Benchmark on representative data. Ratio and speed swing wildly by
content; measure your real payloads with
zstd -b, a codec benchmark, or
end-to-end timing that counts CPU and transfer together. Choose the point
on the curve that minimizes total time or cost, not peak ratio.
Signals
- Is compression applied only where bytes are scarcer than the CPU to shrink
them?
- Does the codec choice match the speed-versus-ratio need of that path?
- Is the level set from read-many versus read-once, not pinned to maximum?
- Are already-compressed and tiny payloads skipped rather than reprocessed?
Boundaries
This chooses and places the codec. Cutting round trips and moving fewer bytes
overall is io-optimization; the encode step that produces those bytes is
serialization-performance. HTTP-level negotiation of Content-Encoding follows
http-caching and the protocol's own rules.
1---2name: compression-tradeoffs3description: Choose a compression codec and level by weighing size reduction against CPU cost, and place compression where the bytes are actually scarce. Use when deciding whether and how to compress payloads, logs, or stored data, or when compression is burning CPU for little gain.4---56# Compression tradeoffs78Compression spends CPU to save bytes, and whether that trade pays depends9entirely on which resource is scarce. On a slow network almost any codec wins;10on a fast local link, compressing can be slower than sending the data raw. The11decision is codec, level, and placement, made from the real bottleneck, not a12default set once and forgotten.1314## Method15161. **Identify the scarce resource first.** Compress only when bytes cost more17 than the CPU to shrink them: a metered or slow link, expensive storage, a18 bandwidth-bound transfer. If the link is fast and the CPU is hot, compression19 can lose; measure before assuming it helps.202. **Pick the codec by the ratio-versus-speed curve.** LZ4 and Snappy compress21 and decompress fastest at a modest ratio, good for hot internal traffic and22 on-disk blocks. Zstd is the strong default: near-LZ4 speed at low levels,23 near gzip ratio higher up, tunable across the range. Gzip is the24 compatible-everywhere middle. Brotli reaches the best ratio for static web25 assets at high CPU cost.263. **Tune the level to the access pattern, not the maximum.** Compress-once27 read-many data (static assets, cold archives) justifies a high level (brotli28 11, zstd 19) because the CPU is amortized over every read. Compress-once29 read-once streaming data wants a low fast level; a high level there just adds30 latency for bytes nobody rereads.314. **Place compression where it fits the resource.** Compress web responses at32 the CDN or gateway edge, database and log storage at rest, internal RPC only33 when the payload and link make it pay. Precompress static assets at build34 time so the server serves a stored `.br` or `.gz`, not one recomputed per35 request.365. **Never double-compress or compress the incompressible.** Already-compressed37 data (JPEG, PNG, MP4, an encrypted or gzipped blob) gains nothing and wastes38 CPU; skip it. Content negotiation must not re-gzip a body the origin already39 compressed.406. **Benchmark on representative data.** Ratio and speed swing wildly by41 content; measure your real payloads with `zstd -b`, a codec benchmark, or42 end-to-end timing that counts CPU and transfer together. Choose the point43 on the curve that minimizes total time or cost, not peak ratio.4445## Signals4647- Is compression applied only where bytes are scarcer than the CPU to shrink48 them?49- Does the codec choice match the speed-versus-ratio need of that path?50- Is the level set from read-many versus read-once, not pinned to maximum?51- Are already-compressed and tiny payloads skipped rather than reprocessed?5253## Boundaries5455This chooses and places the codec. Cutting round trips and moving fewer bytes56overall is io-optimization; the encode step that produces those bytes is57serialization-performance. HTTP-level negotiation of `Content-Encoding` follows58http-caching and the protocol's own rules.