I make targeted use of content encoding in hosting by planning MIME types, compression levels and fallbacks properly and measuring the effect with metrics; this allows me to significantly reduce loading time and bandwidth load. With the right combination of Breadstick and Gzip I get better core web vitals, stable delivery and less CPU overhead at peak times.
Key points
The following aspects control the effective implementation and provide me with a quick Overview.
- Breadstick for text, Gzip as fallback
- HTTPS activate, Vary Set correctly
- Binary files exclude, MIME types Define
- steps balance, CPU spare
- Caching couple, Monitoring use
What is HTTP Content Encoding?
I compress response data on the server side and mark the result with the header Content encoding, while the client can be configured via Accept-Encoding signals its capabilities. This shrinks HTML, CSS, JavaScript and JSON before transmission, which reduces RTTs and makes the display faster. I focus on text-based resources because images, videos and archives bring little gain with additional HTTP compression. This technique has a direct effect on TTFB, LCP and data costs because fewer bytes pass through the network. Configured correctly, the method increases the number of users that can be served simultaneously per host and noticeably reduces the abandonment rate.
Gzip vs. Brotli: differences and use
I combine both methods because they have different strengths and together they create a hybrid solution. Brotli often delivers very good ratios at levels 5-7 and outperforms gzip for text files with around 15-25 % smaller results. Gzip shines with very fast on-the-fly compression and offers the best compatibility, even for older clients. Brotli requires HTTPS, which I use by default anyway; if the client accepts „br“, Brotli wins, otherwise gzip takes effect. For additional classification, the Comparison Brotli vs. Gzip with practical application scenarios.
| Criterion | Gzip | Brotli (br) | Application note |
|---|---|---|---|
| compression ratio | Good, solid Sizes | Very good, often smaller | Preferred for text if CPU headroom is available |
| Speed | Very fast on-the-fly | Slower at high levels | Select moderate levels 5-7 |
| Compatibility | Broad, even older Clients | Modern browsers, only via HTTPS | Force HTTPS, fallback to gzip |
| Typical contents | Dynamic HTML, JSON | Static text bundles | Drive hybrid: Prioritize Brotli, gzip fallback |
Recommended hosting strategies
I consistently activate HTTPS so that Breadstick and clearly define the relevant MIME types: text/html, text/css, application/javascript, application/json, image/svg+xml. I deactivate HTTP compression for binary files such as JPEG, PNG, WebP, AVIF, MP4, ZIP or PDF because additional CPU time is of little use there. I set the server priority so that „br“ comes first and gzip automatically takes over if a client does not accept Brotli. For highly dynamic responses, I often use gzip on-the-fly to cushion CPU peaks. On staging and build pipelines, I precompress large static bundles so that Origin has less work to do.
HTTP/2 and HTTP/3: Prioritization and header compression
I take into account that content encoding for bodies interacts with HPACK (HTTP/2) and QPACK (HTTP/3) for headers. Headers are binary and efficiently compressed anyway, so the biggest leverage is clearly in the body. With HTTP/2/3, I also benefit from better multiplexing performance: smaller, compressed resources block the line less and can be prioritized for delivery. I make sure that important render assets (CSS, critical JS) are prioritized and delivered early in compressed form so that the browser can render quickly.
I supplement server priorities and any set weightings with a clean chunking strategy: With on-the-fly compression, I keep TTFB stable by sending the first bytes early instead of optimizing for maximum final size. This keeps interaction and LCP reliably fast, even when there are load peaks.
Negotiation in detail: Accept encoding, q-values and Vary
I value Accept-Encoding exactly and note q-values (quality factors) if a client offers several methods. In this way, I implement the sequence „br, gzip“ consistently and remain compatible when clients announce Brotli with a lower q-value. Vary: Accept-Encoding so that caches keep variants separate. Behind proxies and CDNs, I verify whether the cache keys contain accept encoding or are supplemented by rule so that gzip and br versions are not mixed.
I also keep an eye on the risk of a variant explosion: If a project combines many Vary factors (e.g. language, cookie status and encoding), the cache matrix explodes. I therefore reduce Vary to the bare minimum, normalize accept encoding on the server side and use clear rules so that I can achieve speed without unnecessary cache duplicates.
Security aspects: BREACH/CRIME and sensitive content
I do not compress responses that contain confidential, unpublished or easily correlatable secrets together with user-controllable inputs. This is due to side-channel attacks such as BREACH/CRIME, that can draw conclusions about secret tokens from differences in size. For login pages, CSRF token carriers or payment flows, I specifically deactivate content encoding or ensure through strict separation that secret values are not compressed together with reflected parameters.
Where there is no other way, I use additional countermeasures: I minimize repeatable structures, scatter random data, or deliver different components separately to make correlation more difficult. The principle remains: Performance is important, but security is non-negotiable - I structure responses in such a way that compression does not become an attack surface.
Compression levels and CPU load
I choose moderate levels because too high levels unnecessarily tie up CPU for on-the-fly responses and delay the time-to-first-byte; Brotli 5-7 and gzip 5-6 often prove their worth. For very frequently requested, static bundles, precompression at a higher level is worthwhile because the server only generates the file once and then delivers it directly. It is still important to monitor the real load: I reduce the levels slightly during peaks to keep throughput and response times stable. I use sensible defaults, but adjust according to traffic patterns, hardware and application profile. I summarize more in-depth considerations regarding levels and processor load under Compression levels and CPU load together.
Precompression in the build: Fingerprinting, ETags and Cache-Busting
I pre-compress large, static bundles (CSS/JS/JSON/SVG) in the build and provide them with content hashes in the file name. This way I can set aggressive cache control headers and at the same time ensure that the server delivers .br and .gz directly from disk. With fingerprinting ETag and file name match anyway; I then often do without ETag and set to immutable and long max-age values to minimize the load on the Origin.
It is important to correctly assign the MIME types and Content type-header for the compressed variants. I make sure that the server does not accidentally deliver „application/octet-stream“, but retains the original type. For dynamic templates, I use microcaches and separate their validity cleanly from the long-lived, pre-compressed assets so that I can keep the CPU requirements clearly under control.
Example configurations on the server
I activate the modules for gzip and Brotli, then define clean type lists and exceptions and set the levels. In Apache, Nginx and LiteSpeed, the logic follows the same pattern: check accepted methods, set priority, whitelist types, blacklist binary formats, set Vary: Accept encoding. For static assets, I use file variants with extensions such as .br and .gz, which the server delivers depending on the client without recompressing. I compress dynamic templates on-the-fly, but combine this with microcaches so that the CPU does not repeat identical work every second. Unit and smoke tests ensure that headers, caching and ETag/Vary work together correctly.
Cleverly combining caching and content encoding
I combine HTTP compression with browser and edge caches so that clients can use already compressed variants for longer. I use Cache-Control, ETag and Last-Modified to control validity windows, while I set Vary: Accept-Encoding so that proxy chains separate variants correctly. For dynamic platforms, I cache already rendered and compressed responses, eliminating both generation and compression. In this way, I stabilize load peaks, save CPU and bandwidth and keep LCP and FID reliably low. I always check whether stale-while-revalidate and stale-if-error bring advantages without risking inconsistent states.
Cache keys and variant control
I define clear cache keys at CDN and proxy level: in addition to path and host, I take into account accept encoding, but avoid superfluous parameters. Where necessary, I normalize headers (e.g. I remove exotic accept-encoding combinations or set server rules that evaluate „br, gzip“ as the default). In this way, I prevent fragmentation and achieve high Hit-Rates. For country-specific or language-dependent delivery, I decouple content changes from compression so that Vary factors do not multiply each other.
I also check how ETags are handled: Weak ETags (W/) can lead to misunderstandings under certain circumstances with different compression. If the CDN is the primary cache, I often use strong ETags or even a pure file name hash and avoid fluctuating validation logic.
Monitoring and testing the compression
I check in the browser DevTools whether the response header Content encoding is set correctly and how large the resource is before and after compression. In the waterfall, I can see whether reduced bytes noticeably shorten the blocking of the main resources. Pagespeed tools help me to determine whether text compression is active and where additional potential lies dormant. On the server side, I monitor CPU, load, bandwidth and response times in order to adjust levels and rules in a targeted manner. Regular spot checks with different clients ensure the compatibility of older devices.
Diagnosis in practice: headers, sizes and stumbling blocks
I test specifically with different accept encoding headers and compare response sizes. It is important to me that there is no double compression (e.g. Origin compresses and CDN compresses again). I check whether dynamic responses have a Transfer encoding: chunked works cleanly and whether the pre-compressed files Content-Length fits exactly. If inconsistent sizes occur, I correct priorities, remove unnecessary filters or adjust modules that influence each other.
In addition, I watch out for problem cases such as deflate without Zlib headers or exotic clients that accept Gzip but decompress incorrectly. In multi-proxy chains, I observe whether an intermediate proxy unpacks content and forwards it unchanged; in such installations, I make sure that „Vary“ is preserved and that no transparency proxies unintentionally change the response.
Cleanly tune CDN and compression
I decide whether the CDN compresses itself or takes variants from the origin and keep this choice consistent. If the CDN delivers gzip or Brotli, depending on the client, I ensure correct Vary handling and separate cache keys. I optimize the transfer via TLS termination, Brotli support at the edge and rules for static bundles. It remains important that there is no double compression anywhere, as this leads to errors and loss of time. I clearly document the chain of origin, CDN and browser so that each point reliably fulfills its task.
Streaming, range requests and large files
I make a strict distinction between compressible text resources and large binary files that are often retrieved via range request (e.g. videos, PDFs for partial retrievals). Range and compression do not get along well with on-the-fly bodies, as the byte offset in the compressed stream does not correspond to the original file. I therefore omit the compression for such formats and instead deliver clean Accept ranges, so that the client can jump efficiently.
For server sent events or other streaming formats, I keep the buffers small in a controlled manner and optimize the payload rather than the compression level. The aim is not to worsen latencies by buffering too aggressively. Where JSON streams make sense, I check whether batched responses are more useful than continuous streaming - compression then works better and saves CPU.
Compress WordPress setups effectively
I primarily rely on server-side compression and only add a few, clearly configured plugins so that I don't create any duplicate tasks. Minification of HTML, CSS and JS before compression reduces the output size and noticeably increases the rate. Full page cache and object cache reduce rendering and compression work for recurring requests. For media, I check formats and quality before uploading and do not rely on HTTP compression during transmission. A repeatable deployment process creates compressed variants in the build to minimize delivery effort.
Expand file types: XML, feeds and sitemaps
I don't forget text-based but often overlooked formats: application/xml, application/rss+xml, application/atom+xml and application/manifest+json benefit significantly from compression. Sitemaps and feeds are often heavily frequented by crawlers - here I save bandwidth and reduce load on the origin. I explicitly whitelist these types and verify after rollout that they are delivered compressed and correctly cached.
Choose threshold values and file sizes sensibly
I define a minimum size from which I compress at all, so that very small responses are not slowed down by overhead. For APIs, I pay attention to JSON form, caching headers and streaming behavior, because the interaction strongly influences the benefits of compression. For large bundles, I separate critical and optional so that browsers start rendering early and have less to decompress. I also check server-specific limits, such as buffers and timeouts, to avoid side effects. The following page provides me with specific information on limit values Compression thresholds in hosting, which I adapt to my own project profile.
Briefly summarized
I use a Hybrid strategy from Brotli and gzip, prioritize text content for compression and keep binary files out. Moderate levels, correctly set Vary and clear type lists provide me with the best ratio of file size, CPU consumption and compatibility. Caching on the browser, CDN and server side noticeably increases the effect and protects against peak loads. Continuous monitoring shows me where I need to sharpen up and where defaults are sufficient. With this consistent implementation, I save bandwidth in euros, reduce loading times and support better core web vitals for every project.


