Compression

Overview

Response compression is applied per backend via HAProxy filters. Different backends can use different algorithms, allowing you to optimize compression for each upstream service’s content type.

Algorithms

AlgorithmSourceDescription
gzipHAProxy nativeWidely supported, good ratio for text
deflateHAProxy nativeStandard deflate encoding
raw-deflateHAProxy nativeRaw deflate without zlib header
brotliRust Lua moduleBetter ratio than gzip for text, supported by modern browsers
zstdRust Lua moduleFast compression with good ratio, growing browser support
Brotli and zstd require global toggle

Brotli and zstd are provided by a Rust Lua module and require the compression_enabled global toggle to be on. Gzip and deflate are HAProxy native and always available.

Per-Backend Configuration

SettingDescription
compression_algorithmnone, gzip, deflate, raw-deflate, brotli, or zstd
compression_qualityBrotli quality (0-11, higher = better ratio, slower)
compression_levelZstd level (1-22, higher = better ratio, slower)
compression_windowBrotli window size (10-24)
compression_content_typesComma-separated MIME prefixes to compress
compression_offloadStrip Accept-Encoding from the backend request

Filter Behavior

The compression filter only activates when all of the following are true:

  • Request method is GET or POST
  • Client sends a supported Accept-Encoding header
  • Response status is 200
  • Response has no existing Content-Encoding header
  • Response has no Cache-Control: no-transform header
  • Response Content-Type matches the configured compression_content_types

When compression is applied:

  • Strong ETags are converted to weak ETags (the body has changed)
  • Transfer-Encoding switches to chunked
  • Content-Length is removed (the length is now unknown)

Global Toggle

To enable brotli and zstd:

  1. Navigate to Settings > Global Options
  2. Enable compression_enabled
  3. Save and Apply
Performance impact

High compression levels (brotli quality 11, zstd level 22) are CPU-intensive. Start with moderate settings (brotli quality 4, zstd level 3) and increase only if you have CPU headroom and need better ratios.

FCGI Limitation

FastCGI backends

Brotli and zstd (the Lua filter) are skipped for FastCGI backends due to an HAProxy 3.4 bug. Native gzip and deflate are unaffected and work normally with FastCGI backends.

Step-by-Step: Enable Compression

  1. Navigate to Settings > Global Options
  2. Enable compression_enabled
  3. Save

Step-by-Step: Configure Per-Backend Compression

  1. Navigate to Core > Backends and open the backend
  2. Scroll to Compression Configuration
  3. Set compression_algorithm to brotli
  4. Set compression_quality to 4 (good balance of ratio and speed)
  5. Set compression_content_types to text/,application/javascript,application/json,image/svg
  6. Enable compression_offload (so the backend doesn’t also try to compress)
  7. Save and Apply

Verification

  1. Test with brotli support:

    curl -k -H "Accept-Encoding: br" -sI https://localhost/ | grep -i content-encoding

    Expect content-encoding: br.

  2. Test with gzip fallback:

    curl -k -H "Accept-Encoding: gzip" -sI https://localhost/ | grep -i content-encoding

    Expect content-encoding: gzip (brotli not supported by the client, falls back to gzip if configured).

  3. Test with no encoding:

    curl -k -H "Accept-Encoding: identity" -sI https://localhost/ | grep -i content-encoding

    Expect no content-encoding header.

  4. Check compression ratio:

    curl -k -H "Accept-Encoding: br" -s https://localhost/ | wc -c
    curl -k -H "Accept-Encoding: identity" -s https://localhost/ | wc -c

    Compare the sizes to verify compression is working.

Next Steps