Gzip vs Brotli: Compression Algorithms for the Web
Intermediate
Every time you load a web page, the HTML, CSS, and JavaScript files traveling from server to browser are almost certainly compressed. Compression is one of the most effective performance optimizations available: it reduces transfer sizes by 60-90%, cuts bandwidth costs, and directly improves page load times. For decades, gzip was the undisputed standard for web compression. Then in 2015, Google introduced Brotli, a newer algorithm purpose-built for the web. Today, both algorithms coexist across the internet, each with distinct strengths. Understanding their differences is essential for anyone working with CDN compression configurations or optimizing web delivery pipelines.
What Is the History Behind Web Compression?
The story of web compression begins with Phil Katz, who in 1989 created the DEFLATE algorithm for his PKZIP archival tool. DEFLATE combined two established techniques: LZ77 (named after Abraham Lempel and Jacob Ziv, who published their sliding-window compression method in 1977) and Huffman coding (Robert Huffman's 1952 variable-length encoding). DEFLATE was formalized as an internet standard in RFC 1951 in May 1996.
In 1992, Jean-loup Gailly and Mark Adler built gzip (GNU zip) as a free, patent-unencumbered replacement for the Unix compress utility. Gzip wrapped the DEFLATE algorithm with a simple header and checksum format, specified later in RFC 1952. The pair also created zlib, a portable C library implementing DEFLATE that became foundational infrastructure across nearly every programming language and operating system. When the HTTP protocol needed a content encoding mechanism, gzip was the natural choice. HTTP/1.0 introduced the Content-Encoding header, and by the time HTTP/1.1 was formalized in RFC 2616 (June 1999), gzip was already the dominant web compression format.
For over two decades, gzip reigned unchallenged. Then in September 2015, Google engineers Jyrki Alakuijala and Zoltan Szabadka published a new compression format called Brotli (named after a Swiss pastry, Bretzeli). Specified in RFC 7932, Brotli was designed from the ground up to compress web content more efficiently than DEFLATE. The IETF registered Brotli as the br content encoding for HTTP, and browsers began adopting it quickly: Chrome 49 (March 2016), Firefox 44 (January 2016), and eventually Safari 11 (September 2017).
How Does Gzip Compression Work?
Gzip compression operates through the DEFLATE algorithm in two stages. First, LZ77 scans a sliding window of recent data (up to 32 KB in gzip) looking for repeated sequences. When it finds a match, it replaces the duplicate string with a back-reference: a (distance, length) pair pointing to the earlier occurrence. For example, if the string <div class="container"> appears multiple times in an HTML file, the second and subsequent occurrences are replaced by compact pointers to the first.
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
Second, Huffman coding assigns variable-length binary codes to the resulting symbols. Frequently occurring symbols get shorter codes, while rare symbols get longer ones. This entropy coding stage squeezes out the remaining redundancy that LZ77 did not eliminate.
Gzip offers nine compression levels (1-9). Level 1 prioritizes speed with minimal compression effort: the LZ77 matching uses a short hash chain and accepts the first reasonable match. Level 9 performs exhaustive searching for the longest possible matches within the sliding window, spending significantly more CPU time. The default level is 6, which represents the practical sweet spot: it achieves roughly 95% of the compression ratio of level 9 while running several times faster.
The key limitation of gzip is its 32 KB sliding window. The algorithm can only find duplicate strings within a 32,768-byte range of previously seen data. For large web assets with repeated patterns spread across the file, many compression opportunities are missed.
How Does Brotli Compression Work?
Brotli improves on DEFLATE in three fundamental ways. First, it uses a much larger sliding window, up to 16 MB compared to gzip's 32 KB. This 500x larger context allows Brotli to find duplicate strings across much greater distances in the input, which is especially beneficial for large JavaScript bundles and CSS frameworks where patterns repeat at wide intervals.
Second, Brotli includes a built-in static dictionary of approximately 13,000 common strings found in web content. This dictionary contains frequent HTML tags (<div>, <span>, </a>), CSS properties (font-size, background-color, margin-top), JavaScript keywords (function, return, undefined), and common English words. When compressing web content, Brotli can reference these dictionary entries instead of encoding common strings from scratch. This dictionary is especially powerful for small files where gzip has little prior context to build upon.
Third, Brotli uses second-order context modeling for its entropy coding stage. While Huffman coding in gzip treats each symbol independently, Brotli considers the probability of a symbol based on the two preceding bytes. This context-dependent approach produces tighter statistical models and smaller output.
Brotli defines twelve compression levels (0-11). Levels 0-4 are designed for real-time compression and compete directly with gzip on speed. Levels 5-9 offer progressively better compression at increasing CPU cost. Levels 10-11 perform exhaustive matching searches that can be 10-50x slower than gzip-9, but they produce the smallest possible output. This wide range makes Brotli suitable for both dynamic real-time compression (at low levels) and offline pre-compression of static assets (at level 11).
How Do Compression Ratios and Speed Compare?
The tradeoff between compression ratio and compression speed is the central consideration when choosing between gzip and Brotli. Benchmark data across typical web assets reveals clear patterns that inform practical deployment decisions.
For a typical 200 KB uncompressed JavaScript bundle, gzip at level 6 compresses it to approximately 64 KB (68% reduction), taking about 2.5 milliseconds. Brotli at level 4 compresses the same file to about 58 KB (71% reduction) in roughly 3 milliseconds. Brotli at level 11 achieves approximately 42 KB (79% reduction), but takes 80-150 milliseconds. The 21% size difference between Brotli-4 and Brotli-11 is significant for high-traffic static assets but comes at a 30-50x speed penalty.
For HTML documents, Brotli's static dictionary provides an even larger advantage. A typical 50 KB HTML page compresses to about 11 KB with gzip-6 versus 8.5 KB with Brotli-4, a 23% improvement. The dictionary pre-encodes thousands of common HTML strings, giving Brotli a substantial head start.
CSS and JavaScript benefit similarly from Brotli's dictionary, which contains common property names, selectors, and language keywords. Web fonts, images, and other binary formats see minimal differences between the two algorithms because their content has little overlap with Brotli's text-oriented dictionary.
How Does Accept-Encoding Negotiation Work?
The mechanism by which browsers and servers agree on a compression format is part of HTTP content negotiation. When a browser sends a request, it includes an Accept-Encoding header listing the compression formats it supports, with optional quality values indicating preference:
Accept-Encoding: br, gzip, deflate
This header tells the server that the client supports Brotli (br), gzip, and raw deflate. The order implies preference: Brotli is listed first. The server inspects this header, selects the best available encoding, compresses the response body, and sets the Content-Encoding header to indicate what it chose:
Content-Encoding: br
Vary: Accept-Encoding
The Vary: Accept-Encoding header is critical for CDN cache hierarchies. It tells intermediate caches that the response varies based on the client's Accept-Encoding value, so separate copies must be stored for each encoding variant. Without the Vary header, a CDN might serve a Brotli-compressed response to a client that only supports gzip, causing a decoding failure.
An important browser security constraint: Brotli is only available over HTTPS. All major browsers strip br from the Accept-Encoding header on plain HTTP connections. This restriction was a deliberate design decision to prevent middleboxes (proxies, firewalls, and network appliances) that do not understand Brotli from corrupting responses. Since HTTPS connections are encrypted end-to-end, middlebox interference is not possible.
How Do CDNs Implement Compression at the Edge?
Modern CDNs implement sophisticated compression strategies that use both gzip and Brotli in different contexts. Understanding this pipeline is essential for optimizing CDN compression configurations.
The CDN compression pipeline typically works in two modes. For dynamic content (API responses, server-rendered HTML), the edge node receives an uncompressed response from the origin and compresses it in real-time. Speed is paramount here, so CDNs use moderate compression levels: typically gzip-6 or Brotli-4. The compressed response is served to the client and cached with appropriate Vary headers so that future requests for the same encoding variant can be served directly from cache.
For static assets (JavaScript bundles, CSS files, fonts), a different strategy applies. Many CDN providers support pre-compressed uploads: you compress files offline at Brotli-11 during your build pipeline and upload both the original and pre-compressed versions. When a Brotli-capable client requests the asset, the CDN serves the pre-compressed file directly, consuming zero CPU at the edge. Clients that only support gzip receive a version compressed at the edge or from a pre-compressed gzip variant.
Major CDN providers including Cloudflare, Fastly, AWS CloudFront, and Akamai all support both gzip and Brotli. Cloudflare enables Brotli by default for all plans and uses a custom-optimized Brotli implementation for dynamic compression. Fastly allows granular control over compression levels and supports on-the-fly Brotli via VCL configuration. CloudFront added Brotli support in September 2020 and automatically negotiates the best encoding.
What Compression Level Should You Use in Practice?
Choosing the right compression level depends on your use case. Here are practical recommendations based on how web infrastructure teams typically configure their stacks:
Static assets served via CDN: Pre-compress with Brotli-11 during your CI/CD build step. The compression happens once, offline, and the result is served millions of times. The slow compression speed of level 11 is irrelevant because it runs during build, not during request handling. Use tools like the brotli command-line utility or build plugins (webpack's compression-webpack-plugin, Vite's vite-plugin-compression) to generate .br files alongside your assets.
Dynamic HTML/API responses: Use Brotli level 4-5 for real-time compression if your server or CDN supports it. At these levels, Brotli compresses nearly as fast as gzip-6 while producing 10-15% smaller output. If Brotli is not available or CPU is constrained, gzip-6 remains an excellent choice. Avoid gzip levels 7-9 in production: the compression improvement over level 6 is less than 2%, while CPU usage increases by 50-100%.
Very large responses (multi-megabyte JSON feeds, data exports): Consider gzip-1 or Brotli-1 for maximum throughput. The compression ratio is still 50-60%, and compression speed exceeds 200 MB/s, keeping latency negligible even for large payloads.
How Do You Configure Gzip and Brotli on Common Servers?
Server configuration for compression is straightforward but requires attention to detail. In Nginx, gzip is built in and enabled with the gzip on; directive. Brotli requires the ngx_brotli module (either compiled from source or installed via a package manager). A typical configuration sets gzip_comp_level 6; and brotli_comp_level 4;, with MIME type filters to avoid compressing already-compressed formats like JPEG, PNG, and WOFF2.
In Apache, mod_deflate handles gzip compression (despite its confusing name, it produces gzip-format output by default). Brotli support arrived with mod_brotli in Apache 2.4.26 (June 2017). Both modules are configured via AddOutputFilterByType directives in .htaccess or the server configuration.
Node.js servers can use the built-in zlib module for gzip or the iltorb / brotli npm packages for Brotli. Express middleware like compression and shrink-ray-current handle Accept-Encoding negotiation and response compression automatically. For production deployments, however, offloading compression to a reverse proxy or CDN is more efficient than compressing in the application process.
What Are the Browser Support Considerations?
As of 2025, Brotli enjoys broad browser support. Chrome has supported Brotli since version 49 (March 2016), Firefox since version 44 (January 2016), Edge since version 15 (April 2017), Safari since version 11 (September 2017), and Opera since version 36. According to Can I Use data, global Brotli support exceeds 97% of web traffic.
The remaining gap consists primarily of older embedded browsers, some enterprise environments running outdated Internet Explorer versions, and automated HTTP clients (bots, scripts, curl without the --compressed flag). For these cases, gzip serves as a universal fallback. A well-configured server or CDN automatically falls back to gzip when the client's Accept-Encoding header does not include br.
One nuance worth noting: some older corporate proxies and security appliances may strip or modify the Accept-Encoding header on non-HTTPS connections. Since Brotli requires HTTPS anyway, this is rarely an issue in practice, but it reinforces the importance of HTTPS adoption for optimal compression.
What Does the Future Hold for Web Compression?
Several developments are shaping the next generation of web compression. Zstandard (zstd), developed by Yann Collet at Facebook and standardized in RFC 8478, offers compression ratios comparable to Brotli with decompression speeds rivaling LZ4. Chrome added experimental zstd support behind a flag in 2023, and the zstd content encoding was registered with IANA. If browser adoption accelerates, zstd could become a third option alongside gzip and Brotli.
Shared dictionaries represent another frontier. The Compression Dictionary Transport proposal (under active development in the IETF) allows servers to provide custom dictionaries that clients cache and use for subsequent requests. This approach extends Brotli's static dictionary concept: instead of a fixed set of common web strings, the server provides a dictionary tailored to its specific content. For sites with highly repetitive page structures, shared dictionaries could reduce compressed sizes by an additional 30-50% beyond Brotli-11.
The interplay between compression and HTTP protocol evolution also matters. HTTP/3, built on the QUIC protocol, uses QPACK header compression (derived from HPACK in HTTP/2) for header fields, while body compression via Content-Encoding remains unchanged. The shift to UDP-based transport in QUIC does not affect how gzip and Brotli operate at the content encoding layer.
How Should You Choose Between Gzip and Brotli?
The practical answer in 2025 is straightforward: use both. Configure your server or CDN to prefer Brotli when the client supports it (over HTTPS) and fall back to gzip otherwise. Pre-compress static assets at Brotli-11 during your build pipeline for maximum savings. Use moderate levels (Brotli-4 or gzip-6) for dynamic content where real-time compression speed matters.
Monitor the impact with web performance tools: compare transfer sizes in the browser's Network tab, check the Content-Encoding response header, and track your CDN's compression ratio metrics. Most CDN dashboards report bandwidth savings from compression, which directly translates to reduced egress costs and faster page loads for users worldwide.
The choice between gzip and Brotli is no longer either/or. With universal browser support for Brotli and mature server-side tooling, the modern web compression stack leverages both algorithms where each excels: Brotli for maximum compression of static assets, and either algorithm at moderate levels for dynamic content where speed and ratio must balance.