Data structures and storage engines
Compression tradeoffs
When compressing a payload saves more than it costs, how the common codecs trade size for CPU, and how to measure the trade on your own data.
Compression makes bytes smaller, and every byte you save is a byte you do not send, store or read. The price is CPU time on both ends. Whether compression is worth it depends on how big the payload is, how much CPU you have and where the bottleneck sits.
Concept
Compression ratio: original size divided by compressed size. A 4 KB payload that compresses to 800 bytes has a ratio of 5 to 1. Codec: the algorithm, such as gzip, zstd or lz4.
The big idea
Compression is a trade between three things: size, speed and the CPU you spend. Some codecs compress hard but slowly. Others are fast but save less. You choose the point that fits the bottleneck: network, disk or CPU.
| Codec | Ratio | Speed | Typical use |
|---|---|---|---|
| lz4 | Modest | Very fast | Hot paths where CPU is scarce |
| snappy | Modest | Fast | Hadoop and Parquet |
| zstd | Strong | Fast, tunable level | A strong general default |
| gzip | Strong | Slower | Standard HTTP Content-Encoding |
Walking through a response
Take a 4 KB JSON response. Compressed with gzip at level 6, it might shrink to about 800 bytes, and cost a few hundred microseconds of CPU. These numbers are illustrative.
size saved per response = 4,000 − 800 = 3,200 bytes
CPU per response ≈ 0.3 ms
at 50,000 responses/s:
CPU needed ≈ 50,000 × 0.3 ms = 15 seconds of CPU every second ≈ 15 coresFifteen cores spent on compression is a real cost. That is why reverse proxies and CDNs often own HTTP compression, so the application servers do not pay for it.
Now flip the case. Storing 1 TB of JSON logs at a 5 to 1 ratio saves about 800 GB of disk. A batch job can compress that data during off-peak hours, and the saving is almost always worth the CPU.
Rules of thumb
- Compress multi-kilobyte payloads when CPU is cheaper than the network or the disk.
- Skip compression for tiny messages that are already dense binary. A message of a few dozen bytes may gain nothing, and the CPU is wasted.
- Expect different ratios by format. Text JSON often shrinks 3 to 8 times. Binary Protobuf often shrinks 1.5 to 3 times. Measure your own payloads.
- Use a dictionary for small, repetitive messages. Train a zstd dictionary on sample traffic, ship it once, and compress each message against it. Each small message then shares the common parts.
Order matters
Compress after serialization: serialize to JSON or Protobuf, then compress the bytes. Formats like Parquet already compress each column page internally. Compressing that again with gzip rarely helps and can make things worse.
Measuring the trade
Measure on your own data, at your real size and rate. Check three numbers.
- The compressed size, as a ratio.
- The CPU time per message, on both the encoder and the decoder.
- The effect on the bottleneck, such as network bytes per second or disk used.
If the switch from JSON to Protobuf saves more bytes than a higher gzip level, the format change wins. Profile serialization and compression separately to see which one costs more.
Common mistakes
- Compressing everything by default. Tiny messages and already-compressed data gain little.
- Picking the highest level without measuring. Higher levels can cost much more CPU for a small gain.
- Compressing twice. Gzip on top of Parquet or another compressed format wastes CPU.
- Forgetting the decoder. Both ends pay the CPU, not only the sender.
Check yourself
- Why might compressing a 40-byte binary message make things worse? There is little redundancy to remove, and the codec's fixed overhead can make the output larger, while CPU is still spent.
- A 4 KB response compresses to 800 bytes. At 1,000 responses per second, how many bytes per second are saved? 3,200 × 1,000 = 3.2 MB per second.
Key takeaways
- Compression trades CPU for bytes. Pick a codec that fits the bottleneck.
- Multi-kilobyte payloads usually gain; tiny dense messages usually do not.
- Measure the ratio and the CPU cost on your own data.
- Compress after serialization, not on top of formats that already compress.
Further learning
Next, read serialization pitfalls for the production bugs that come from the formats and their encodings, including integers in JSON and checksums that are not security.
Related
Serialization, schemas and compression
How data becomes bytes for the wire and for disk, how formats like JSON, Protobuf and Avro differ, how to change a schema safely, and when compression pays. Start here for data formats.
Schema evolution
How to change a record's shape without breaking the producers and consumers that use it. Backward and forward compatibility, safe Protobuf and Avro changes, and schema registry modes.
Text vs binary formats
What serialization is, why a service's data format sets its size and cost, and how JSON compares with Protobuf, Avro and Parquet on the same record.
How a SQL query executes
How a database plans and runs a query, which access paths and join algorithms it chooses between, and how to read EXPLAIN ANALYZE when a query is slow. Start here for query performance.