JSON is the most compressible payload there is: repeated keys, repeated punctuation, ASCII digits. The compression (https://github.com/expressjs/compression 2,805 ) middleware negotiates gzip, deflate or br from the request's Accept-Encoding and streams the body through node:zlib; version 1.8.2 supports Brotli on every maintained Node release.
app.use(compression()); // npm i compression; threshold 1kb
app.use(compression({ threshold: '4kb', filter: (req, res) => !res.getHeader('X-No-Zip') }));The same 300-record list, requested with three different Accept-Encoding values:
| Accept-Encoding | Content-Encoding | Bytes on the wire | Throughput | Avg latency |
|---|---|---|---|---|
| none (no middleware) | identity | 27,314 | 4,218 req/s | 11.35 ms |
| identity | identity | 27,314 | — | — |
| gzip | gzip | 3,563 | 2,720 req/s | 17.88 ms |
| br | br | 2,574 | 3,163 req/s | 15.27 ms |
Gzip removed 87% of the bytes and Brotli 91% — 27 KB down to 2.5 KB — while throughput fell from 4,218 to 2,720 requests per second with gzip. Brotli was faster than gzip here because the middleware defaults to a low Brotli quality level, at which the algorithm compresses better and cheaper than zlib's default level 6. The trade looks bad only over loopback, where bandwidth is free; over a 4G link the 24 KB you do not send saves the client far more than 2 ms of server CPU.
Leave the 1 KB threshold alone: compressing a 200-byte error body adds a header and a zlib stream for nothing. Do not compress twice — if nginx 75 has gzip on for proxied responses (Running Behind nginx), drop the middleware. And never compress a secret sitting next to attacker-controlled input, which is the BREACH attack: use filter to exclude routes that echo a query parameter beside a CSRF token.