Zum Inhalt springen
Core Web Vitals specialists
Server-Performance

Brotli or Zstandard: Faster Web Compression 2026

Brotli, Zstandard or Gzip for web compression in 2026: which method delivers the smallest transfer size and fastest response - static and dynamic alike.

12 min read KompressionBrotliZstandardTTFBServer-Optimierung

Every byte a server delivers has to travel down the wire to the browser before the first content becomes visible. Text compression is the lever that shrinks exactly this transfer size - and therefore acts directly on Time to First Byte and Largest Contentful Paint. For years the answer was simply Gzip or Brotli. Since 2024, Zstandard (zstd) has arrived as a third option, available as an HTTP content encoding in the major browsers (Can I use). In the HTTP Archive analysis, 37 percent of mobile HTML documents are already compressed with Brotli, while 11 percent send no compression at all (HTTP Archive Web Almanac). This article places Gzip, Brotli and zstd in their proper roles: which one produces the smallest files for static build assets, where zstd shines for dynamic HTML and JSON APIs, how content-encoding negotiation works correctly and how to measure the real byte savings.

Text Compression 2026: Fewest Bytes, Fastest ResponseMobile HTML compression (Web Almanac)Gzip52%Brotli37%none11%Brotli on 37% of pages, 11% with no compression at allCompression throughput (Zstandard project)zstd -1510 MB/sGzip -1105 MB/sabout 5x faster compression than Gzipdecompression stays fast at every levelStatic: Brotli 11 smallest files | Dynamic: zstd about 4x faster | Fallback: GzipStatic build assetsBrotli level 11smallest file, compressed onceDynamic HTML / JSONzstd level 12-19fast, low CPU loadOld clients / HTTPGzipuniversal fallbackContent-Encoding negotiation and fallback chainClient sends Accept-Encoding: zstd, br, gzip -> server picks best shared method, otherwise GzipChrome 123+Edge 123+Firefox 126+Safari 26+(Can I use)

Why Text Compression Decides LCP and TTFB

HTML, CSS and JavaScript are text formats with high redundancy - recurring tags, class names, keywords and whitespace. That very redundancy compresses well. A typical HTML response shrinks with modern compression to a quarter or a fifth of its size, and JavaScript bundles often compress even more. Fewer transferred bytes mean fewer roundtrips in TCP slow start and a shorter time until the document is fully received. Because the browser can only discover further resources after the HTML has arrived, a smaller HTML response moves the entire downstream loading chain forward.

The link to user experience is well documented. Google describes Time to First Byte as one of the values that caps Largest Contentful Paint - if the HTML arrives late, even the largest visible element cannot appear early (Google web.dev). And the economic effect is measurable: improving mobile load time by just 0.1 seconds raised the retail conversion rate by up to 8.4 percent (Deloitte). Compression is therefore not a detail for purists but a building block that co-decides Core Web Vitals and revenue.

Compression acts exactly at the latency-critical point

The biggest effect of a smaller transfer size appears on slow and distant connections - mobile, weak WiFi, international access. There, every extra kilobyte costs noticeable time, while on a fibre line it disappears into the noise. Compression therefore pays off most where the probability of a bounce is already highest.

Gzip, Brotli and Zstandard at a Glance

The three relevant methods differ less in goal than in the trade-off between compression ratio and computational cost. Gzip is the oldest and most universal standard: supported by every browser and server, fast, with solid ratios. Brotli was developed by Google and standardized as RFC 7932 (IETF RFC 7932); at a high level it achieves the best text compression ratios of the three. Zstandard originated at Meta, is standardized as RFC 8878 (IETF RFC 8878) and, in the HTTP world, has been usable as the zstd content encoding since 2024. Its hallmark is a very wide range between very fast and very strong compression, tunable via the level.

A look at raw speed makes zstd's character clear. In the Zstandard project's benchmark, zstd at its default level compresses at around 510 MB/s, while the comparable zlib Gzip level reaches only about 105 MB/s - roughly 5 times faster at a slightly better ratio (Zstandard project benchmark). Important for server use: zstd's decompression speed stays consistently high across all levels (Zstandard project benchmark), so a higher compression level does not slow the client down.

Gzip: the universal standard

Understood by every client, fast and resource-friendly. For old browsers, unencrypted connections and as a fallback layer, Gzip remains the reliable base of any compression strategy.

Brotli: smallest text files

At maximum level Brotli produces the smallest files of the three methods for HTML, CSS and JavaScript (IETF RFC 7932). The price is a high compression time that only amortizes with one-time pre-compression.

Zstandard: fast and flexible

With a single library, zstd covers the range from very fast to very strong (IETF RFC 8878). This breadth makes it especially attractive for dynamic responses compressed in real time.

The market data mirrors these roles. For JavaScript, Brotli has now overtaken Gzip and sits at around 45 percent of mobile deliveries versus 41 percent for Gzip; zstd appears at about 1 percent, only at the start of its adoption (HTTP Archive Web Almanac). In practice this means zstd complements the stack, it does not replace Brotli and Gzip. Combining the three methods by role extracts the maximum - a core theme of every server optimization.

Compressing Static Assets: Brotli at Maximum Level

Static build assets - the shipped JavaScript bundle, the CSS file, SVG icons - are generated once during the build and then delivered unchanged millions of times. That is the ideal case for expensive but maximal compression. At Brotli level 11 the smallest file emerges; the fact that compression takes seconds rather than milliseconds is irrelevant, because it happens only once at deployment. The web server then serves the pre-compressed .br file directly, without recomputing per request.

Pre-compress instead of on the fly

The decisive trick for static assets is pre-compressing at build time. Generate a .br and a .gz variant next to each file and let the web server serve the matching one. Clients then get the smallest possible file without the server spending CPU time compressing on every request - a standard step in our frontend optimization.
nginx.conf
# Serve pre-compressed files directly (ngx_brotli + gzip_static)
brotli_static on;    # serves an existing .br file
gzip_static on;      # fallback: existing .gz file

# Only on the fly where no pre-compression exists (dynamic)
brotli on;
brotli_comp_level 5;               # moderate level for real time
brotli_types text/html text/css application/javascript application/json image/svg+xml;

# Keep cache variants separated per encoding
add_header Vary Accept-Encoding always;

For static assets the choice is therefore clear: Brotli 11 as the pre-compressed variant, Gzip 9 as the fallback for clients without Brotli. zstd brings little advantage here, because compression time does not matter anyway and Brotli 11 delivers the slightly smaller file. The gain lies in the long cache lifetime: once compressed, the file is served with Cache-Control: immutable for months - an interplay we describe in detail in caching strategies with Varnish and Redis.

Compressing Dynamically: Where zstd Shines

Dynamic responses are a completely different case. Personalized HTML, an API's JSON responses, server-rendered pages with changing content - all of it is created anew per request and must be compressed in real time while the user waits. Here it is not the last compression level that counts but the ratio of saved bytes to spent CPU time. This is exactly the discipline in which zstd plays to its strength: at medium levels it reaches ratios close to Brotli, yet compresses considerably faster.

The order-of-magnitude difference is significant. Brotli at maximum level 11 is too slow for real-time compression; at a high level, zstd compresses comparable content around 4 times faster than Brotli 11, with only a marginally larger file (Zstandard project benchmark). For a JSON API delivering thousands of responses per second, that means noticeably less CPU load per request - compute time that benefits the backend and thus Time to First Byte.

  • Pre-compress static build assets with Brotli 11, provide Gzip 9 as a fallback
  • Compress dynamic HTML and JSON in real time - zstd at a medium to high level or Brotli 4 to 6
  • Set the compression level by CPU load, not by the theoretical maximum ratio
  • Exclude already compressed formats (JPEG, WebP, AVIF, ZIP, WOFF2) from compression
  • Leave very small responses under about one kilobyte uncompressed - the overhead is not worth it
  • Verify encoding choice and compression level against real responses after deployment

Do not re-compress compressed data

Images in JPEG, WebP or AVIF, videos, ZIP archives and WOFF2 fonts are already compressed. Sending them through Gzip, Brotli or zstd again costs CPU time and, in the worst case, even enlarges the response (MDN Web Docs). Compression belongs exclusively on text formats such as HTML, CSS, JavaScript, JSON, XML and SVG.

Brotli and Zstandard in Direct Comparison

The following comparison summarizes when each method is the better choice. What matters is the split between once-generated static files and per-request dynamic responses - not the question of which algorithm is universally best.

CriterionBrotli (level 11)Zstandard (medium to high)
Text compression ratiohighest of the three methodsclose to Brotli, marginally larger
Compression speedlow, seconds per MBhigh, about 4x faster than Brotli 11
Decompressionfastfast and level-independent
Ideal usestatic build assetsdynamic HTML and JSON
Standardized asIETF RFC 7932IETF RFC 8878
Browser content encodingnearly universalfrom Chrome and Edge 123, Firefox 126, Safari 26

The browser-support row is the reason zstd is a complement, not a replacement. As an HTTP content encoding, zstd is understood by Chrome and Edge from version 123, by Firefox from 126 and by Safari from 26 (Can I use). Older clients do not know it and could not decompress a zstd response - which is why the server must fall back cleanly to Brotli or Gzip for them. One more detail: browsers send Accept-Encoding: zstd only over HTTPS, not over unencrypted HTTP (MDN Web Docs).

Negotiating Content-Encoding Cleanly

Which method is used is not decided by the server alone but by a negotiation between client and server. In every request the browser announces via the Accept-Encoding header which methods it understands - for example zstd, br, gzip. The server picks the best shared method, compresses the response accordingly and signals the encoding actually used in the response's Content-Encoding header (MDN Web Docs). If the client understands none of the preferred methods, the chain falls back to Gzip and, in the extreme, to uncompressed delivery.

HTTP negotiation
# Browser request (modern version, over HTTPS)
GET /api/products HTTP/2
Accept-Encoding: zstd, br, gzip

# Server response - zstd chosen
HTTP/2 200 OK
Content-Type: application/json
Content-Encoding: zstd
Vary: Accept-Encoding

Do not forget Vary: Accept-Encoding

So that intermediate caches and CDNs do not accidentally deliver a zstd response to a client that only understands Gzip, the server must send Vary: Accept-Encoding. This header instructs caches to keep a separate variant per encoding. Without it, broken responses threaten a portion of visitors - a classic configuration mistake we check for specifically in our technical analysis.

Building the Fallback Chain Correctly

A robust compression strategy in 2026 is a staged chain, not a single decision. It starts with the strongest method the client understands and falls back in an orderly way when a prerequisite is missing. That way every visitor gets the smallest response their browser can process, without excluding any client from delivery.

  1. Static assets: pre-compressed Brotli 11, otherwise pre-compressed Gzip 9
  2. Dynamic responses to modern clients over HTTPS: zstd at a medium to high level
  3. Dynamic responses to clients with Brotli but without zstd: Brotli at level 4 to 6
  4. Clients without Brotli and zstd, and unencrypted connections: Gzip
  5. Very old or exotic clients without any compression: uncompressed delivery

The appeal of this chain lies in its asymmetric risk-reward profile: modern browsers get the full speed advantage, older ones lose nothing because the fallback is lossless. This way of thinking - use the most modern technique without excluding anyone - runs through all performance work, from the protocol to resource prioritization. How a similar principle pays off during connection setup is shown in the piece on HTTP/3 and QUIC.

Measuring the Real Byte Savings

Compression is an optimization you should measure rather than guess. The most important value is the actually transferred size per response - visible in the browser's developer tools as transferred size versus decoded size. The ratio of the two immediately shows how strongly a response was compressed and whether it is compressed at all. The Content-Encoding header additionally reveals which method the server actually chose.

For a reliable assessment a single glance is not enough. You compare the methods on the same representative documents - the largest HTML response, the main JavaScript bundle, the API's largest JSON responses. Only this comparison shows whether moving from Gzip to Brotli or introducing zstd for dynamic responses delivers the expected gain and how it affects CPU load and Time to First Byte. In practice the switch pays off most where large text responses meet many users (project experience).

It is not the theoretical maximum ratio that decides, but the smallest response the respective client can process losslessly - measured on real documents, not on synthetic test files.

Principle of our compression audits

The Optimal Compression Stack for 2026

The best compression stack in 2026 is not an either-or but a deliberate division of labour. Brotli at maximum level delivers the smallest static files and belongs in the build process. zstd compresses dynamic HTML and JSON quickly and efficiently, relieving the server under load. Gzip remains the universal fallback layer that excludes no one. Above all sits correct negotiation with a clean Vary header, so that caches and CDNs do not mix the variants.

Compression is a building block, not a cure-all. It shrinks the transfer size but changes nothing about a slow database, an overloaded frontend or a bloated DOM. Its full value emerges only in concert with a fast backend, sensible caching and lean markup - such as reducing the DOM size and a well-used back-forward cache. In our performance projects we set up the compression stack as part of server optimization: Brotli for assets, efficient zstd or Gzip for dynamic responses - without driving up server load and with proven byte savings.

Sources and Studies

This article is based on data from: HTTP Archive Web Almanac (Compression and JavaScript chapters), IETF RFC 8878 (Zstandard Compression and the application/zstd media type), IETF RFC 7932 (Brotli Compressed Data Format), MDN Web Docs (Content-Encoding and Accept-Encoding), Can I use (browser support for zstd content encoding), the Zstandard project benchmark, Google web.dev (TTFB and LCP) and Deloitte Milliseconds Make Millions. The practical figures cited are based on project experience and vary with the starting situation.