Technology

Brotli and Gzip Compression Settings for Faster Core Web Vitals

When we review slow sites on our infrastructure at dchost.com, one pattern appears again and again: HTML, CSS and JavaScript are being sent completely uncompressed or with poorly tuned settings. Core Web Vitals like LCP and TTFB suffer, even though the server itself is not overloaded. The quickest win in many of these audits is simply configuring Brotli and Gzip compression settings correctly on Nginx, Apache or LiteSpeed.

In this article, we will focus on practical, real-world tuning. We will look at how compression affects Core Web Vitals, when Brotli is better than Gzip (and when it is not), and how to configure each major web server so that you get maximum benefit without burning CPU. All examples are written from the perspective of running real production workloads on shared hosting, VPS, dedicated servers and even colocation environments, just like we do every day at dchost.com.

How Compression Affects Core Web Vitals

Before touching configuration files, it helps to connect Brotli and Gzip to the metrics your SEO and marketing teams care about, especially Core Web Vitals. If you have not yet read it, our article Core Web Vitals and hosting: how server choices impact TTFB, LCP and CLS is a good companion to this guide.

The most important relationships:

  • LCP (Largest Contentful Paint): Often depends on how quickly the HTML document and render-blocking CSS/JS arrive. Compressing these assets directly shortens download time, especially on slower connections.
  • TTFB (Time To First Byte): Compression itself does not reduce TTFB, but overly aggressive settings can increase TTFB if the server spends too long compressing each response. Good tuning is about balancing CPU cost and size savings.
  • INP/FID (Interaction metrics): Smaller JavaScript bundles load and execute sooner. Compression does not change CPU execution time, but it reduces the network component of the delay.
  • CLS: Compression does not directly affect layout stability, but faster CSS and fonts help the page stabilize quicker.

In practice, we usually see 20–30% total transfer size reduction when Gzip is configured correctly, and often 10–20% extra savings when Brotli is enabled for modern browsers. On high-latency mobile connections, this can be the difference between a mediocre and a green LCP score.

Brotli vs Gzip: What You Really Need to Know

Both Brotli and Gzip compress HTTP responses and are negotiated via the Accept-Encoding and Content-Encoding headers. But there are important differences you should keep in mind when tuning your stack.

Compression efficiency and CPU cost

At similar CPU cost, Brotli usually produces smaller files than Gzip, especially for text-based content like HTML, CSS and JavaScript. But Brotli’s higher levels can be very CPU intensive. For dynamic responses you generate on every request, you must be conservative.

Useful mental model:

  • Gzip levels 1–9 (Nginx/Apache): sweet spot for dynamic content is usually 3–6.
  • Brotli levels 0–11 (Nginx/Apache/LiteSpeed): sweet spot for dynamic content is usually 3–6; very high levels are better reserved for precompressed static assets.

For static files (CSS/JS built at deploy time), you can precompress with Brotli level 9–11 and store the resulting .br files on disk. The CPU cost is paid once during build, not on every request.

Browser support and HTTPS requirement

  • Gzip is universally supported (desktop and mobile, modern and legacy).
  • Brotli (br) is supported by all major modern browsers, but typically only over HTTPS.

That is why most production setups use this strategy:

  • Enable Brotli first for modern HTTPS traffic.
  • Keep Gzip as a fallback for older or non-Brotli clients.

If you are still enabling HTTP/2 and HTTP/3 on your servers, have a look at our guide on how HTTP/2 and HTTP/3 affect SEO and Core Web Vitals. Compression, modern HTTP protocols and TLS settings work best when tuned together.

What to compress (and what not to)

Compression improves performance most when applied to text-based responses:

  • HTML, JSON, XML
  • CSS, JavaScript
  • SVG, some font formats (WOFF/WOFF2 – WOFF2 is already compressed but small extra gains are possible)

It is usually not useful (or even harmful) to compress already-compressed binary formats:

  • JPEG, PNG, WebP, AVIF images
  • MP4, WebM videos
  • ZIP, PDF and similar archives

If you are still sending large unoptimized images, compression alone will not save you. Combine these settings with a proper image strategy like we described in our WebP/AVIF and image SEO guide.

Tuning Brotli and Gzip on Nginx

Nginx is very flexible for compression, but configuration can become confusing across http, server and location blocks. Here is a clean approach we often use on VPS and dedicated servers at dchost.com.

Step 1: Enable modules

Most modern Nginx packages ship with Gzip support by default. Brotli may require:

  • Installing an Nginx build with Brotli support, or
  • Loading a Brotli dynamic module (e.g. ngx_brotli).

Check with:

nginx -V 2>&1 | grep -i brotli

If you see Brotli configured as a module, you can enable it; otherwise you must install a package or build including Brotli first. In another article we walked through this in detail: TLS 1.3, OCSP stapling and Brotli on Nginx.

Step 2: Baseline Gzip settings

In your main Nginx config (often /etc/nginx/nginx.conf), inside the http {} block:

http {
    gzip on;
    gzip_comp_level 4;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_vary on;

    gzip_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/x-javascript
        application/json
        application/xml
        application/rss+xml
        application/atom+xml
        application/xhtml+xml
        application/xml+rss
        image/svg+xml
        font/ttf
        font/otf
        font/woff
        font/woff2;

    # ... rest of your http config ...
}

Notes:

  • gzip_comp_level 4 is a good starting point. Increase to 5–6 if CPU usage is low and your pages are large.
  • gzip_min_length 1024 avoids compressing tiny responses where overhead outweighs the benefit.
  • gzip_vary on adds Vary: Accept-Encoding, which is important for proxies and CDNs.

Step 3: Brotli settings for dynamic responses

Once Brotli is available, add:

http {
    # Existing gzip settings ...

    brotli on;
    brotli_comp_level 4;
    brotli_types
        text/plain
        text/css
        text/javascript
        application/javascript
        application/x-javascript
        application/json
        application/xml
        application/rss+xml
        application/atom+xml
        application/xhtml+xml
        application/xml+rss
        image/svg+xml
        font/ttf
        font/otf
        font/woff
        font/woff2;
}

This configuration:

  • Uses Brotli level 4 for a good balance between CPU and size.
  • Leaves Gzip enabled as a fallback for clients that do not support br.

For very busy dynamic sites, you can even start with brotli_comp_level 3 and test CPU load.

Step 4: Precompressed static assets

For build pipelines (React/Vue SPA, Laravel Mix, Webpack, Vite), generate .br and .gz files at deploy time. For example:

# Example with Brotli CLI
find dist -type f ( -name '*.js' -o -name '*.css' -o -name '*.html' ) 
  -exec brotli -f -q 10 {} ;

# Example with gzip
find dist -type f ( -name '*.js' -o -name '*.css' -o -name '*.html' ) 
  -exec gzip -f -k -9 {} ;

Then in Nginx, enable serving the precompressed files:

http {
    gzip_static on;    # Use file.js.gz if it exists
    brotli_static on;  # Use file.js.br if it exists
}

With this pattern, the heaviest compression runs only during build or deploy, not on end-user requests, which is ideal for Core Web Vitals and server stability.

Step 5: Testing Nginx compression

Use curl to verify which encoding you receive:

curl -I -H 'Accept-Encoding: gzip' https://example.com/

curl -I -H 'Accept-Encoding: br' https://example.com/

In the response headers, confirm:

  • Content-Encoding: gzip or Content-Encoding: br
  • Vary: Accept-Encoding

Then run a full-page test with tools such as PageSpeed Insights or WebPageTest. As a reference, see our guide on how to properly test your website speed so you interpret the results correctly.

Tuning Brotli and Gzip on Apache (mod_deflate, mod_brotli)

On Apache, Gzip is handled by mod_deflate and Brotli by mod_brotli. Configuration can live in the main server config or in .htaccess (with some limitations).

Step 1: Enable the modules

In your Apache config (e.g. httpd.conf or apache2.conf):

LoadModule deflate_module modules/mod_deflate.so
LoadModule brotli_module  modules/mod_brotli.so

Restart Apache after enabling:

systemctl restart httpd   # or apache2

Step 2: Gzip (mod_deflate) configuration

In the global config or a virtual host:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE 
        text/plain 
        text/html 
        text/xml 
        text/css 
        text/javascript 
        application/javascript 
        application/x-javascript 
        application/json 
        application/xml 
        application/xhtml+xml 
        application/rss+xml 
        application/atom+xml 
        image/svg+xml 
        font/ttf 
        font/otf 
        font/woff 
        font/woff2

    # Exclude already compressed formats
    SetEnvIfNoCase Request_URI 
        .(?:gif|jpe?g|png|webp|avif|mp4|mp3|ogg|pdf|zip|gz|bz2|rar)$ 
        no-gzip dont-vary

    # Compression level (1–9)
    DeflateCompressionLevel 4

    # Add proper Vary header
    Header append Vary Accept-Encoding env=!dont-vary
</IfModule>

This setup keeps compression at a moderate level and avoids re-compressing heavy binaries.

Step 3: Brotli (mod_brotli) configuration

For Apache 2.4+ with mod_brotli available:

<IfModule mod_brotli.c>
    BrotliCompressionQuality 4        # 0–11
    BrotliWindow 16                   # reasonable default

    AddOutputFilterByType BROTLI_COMPRESS 
        text/plain 
        text/html 
        text/xml 
        text/css 
        text/javascript 
        application/javascript 
        application/json 
        application/xml 
        application/xhtml+xml 
        application/rss+xml 
        application/atom+xml 
        image/svg+xml 
        font/ttf 
        font/otf 
        font/woff 
        font/woff2

    # Ensure Vary header
    Header append Vary Accept-Encoding
</IfModule>

Apache will negotiate between Brotli and Gzip based on the client’s Accept-Encoding header. You can safely have both modules active.

Step 4: .htaccess example

If you are on shared hosting and only have .htaccess access, you can add a simplified version:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/css 
        application/javascript application/json image/svg+xml
</IfModule>

<IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css 
        application/javascript application/json image/svg+xml
</IfModule>

Keep in mind that some directives (like DeflateCompressionLevel) may require being set in the main config depending on your Apache configuration.

Step 5: Testing Apache compression

Again, use curl or browser DevTools:

  • Look at the Network tab, check a CSS or JS file, and verify Content-Encoding is gzip or br.
  • Confirm the Response Size in DevTools is significantly lower than the original.

Brotli and Gzip on LiteSpeed/OpenLiteSpeed

LiteSpeed (and OpenLiteSpeed) integrate compression into the server core. If you are running WordPress with LiteSpeed Cache, some settings are also exposed through the plugin, but the server-level configuration determines the baseline behaviour.

Server-level compression settings

In the LiteSpeed WebAdmin console (usually on port 7080), navigate to:

  • Configuration → Server → Tuning (or similar, depending on version).

Key directives:

  • Enable Compression: set to Yes.
  • Compressible Types: list of MIME types (similar to Nginx/Apache examples above).
  • Gzip Compression Level: 1–9; start at 4.
  • Brotli Compression: enable if available; set quality around 4 for dynamic responses.

LiteSpeed automatically handles negotiation between Brotli and Gzip for you. The main tuning is deciding which types to compress and at what levels.

Virtual host and context overrides

You can override settings per virtual host or context. For example, in a virtual host configuration you might disable compression for a specific download directory:

<context /downloads>
    compress      0
</context>

This is useful if you serve large binary files that gain nothing from compression.

LiteSpeed Cache plugin (WordPress)

If you run WordPress with LiteSpeed Cache, the plugin has a Browser or Optimization section that can toggle Gzip/Brotli. However:

  • We recommend controlling compression primarily at the server level and using the plugin features for page cache and asset optimization.
  • Ensure you do not have conflicting settings (for example, the plugin trying to disable server-level compression).

For a broader performance strategy on LiteSpeed-based hosting, see our article on speeding up WordPress with LiteSpeed Cache on shared hosting.

Practical Tuning Strategy Across All Web Servers

Regardless of whether you use Nginx, Apache or LiteSpeed, the high-level strategy is very similar. Here is how we approach Brotli and Gzip tuning on real projects at dchost.com.

1. Prioritize the right content types

Focus on compressing:

  • HTML and JSON: these control the start of rendering and data APIs.
  • Critical CSS and JavaScript: anything that blocks the first render.
  • SVG icons and fonts: helpful but secondary.

Skip or explicitly exclude:

  • Images (JPEG/PNG/WebP/AVIF)
  • Videos
  • Archives (ZIP, GZ, RAR, etc.)

2. Choose safe compression levels

Our default starting values when we provision new VPS or dedicated servers:

  • Gzip: level 4 for dynamic content; 6–9 for precompressed static files generated at build time.
  • Brotli: level 4 for dynamic; 9–11 for precompressed static assets.

Then we monitor:

  • CPU usage under peak traffic.
  • Average TTFB from monitoring tools.
  • Error rates (e.g. timeouts if compression is too heavy for the hardware).

If CPU is underutilized, you can gently raise levels. If CPU saturates during spikes, reduce them.

3. Align compression with caching and CDN strategy

Compression is much more powerful when combined with correct caching headers and a CDN. For detailed header rules, see our guide to HTTP Cache-Control, ETag and CDN rules, and for the CDN concept itself, the article What is a CDN and when do you really need one.

Key alignment points:

  • Cache at the edge: When responses are both compressed and cached by the CDN, your origin server does almost no compression work for cache hits.
  • Vary header: Ensure Vary: Accept-Encoding is present so the CDN can store separate variants for Brotli and Gzip when needed.
  • Warm cache intelligently: For very large catalogs or SPAs, consider warm-up scripts that hit key pages to populate compressed and cached versions before big campaigns.

4. Sync with TLS and HTTP protocol tuning

Brotli is most beneficial over HTTPS (where browsers enable it). If you are still on older TLS settings or only HTTP/1.1, you are leaving performance on the table. A modern setup typically includes:

  • TLS 1.2 and TLS 1.3 with strong cipher suites.
  • HTTP/2 enabled at minimum; consider HTTP/3 for mobile performance.
  • OCSP stapling and session resumption.

We covered these in depth in our article on TLS 1.3, OCSP stapling and modern HTTPS on Nginx and Apache. Compression, TLS and modern protocols together create a visible improvement in Core Web Vitals.

5. Measure impact on Core Web Vitals, not just transfer size

After enabling or tuning compression, measure:

  • LCP: particularly on mobile connections and from key geographies where your users are.
  • TTFB: ensure it does not regress due to CPU overhead.
  • Total bytes transferred for HTML/CSS/JS.

Tools like PageSpeed Insights, Search Console Core Web Vitals reports, and RUM (real user monitoring) scripts give you a complete picture. A 20–30% reduction in transfer size that yields a clear drop in LCP is a success; a small size gain that increases CPU and TTFB is not.

Choosing the Right Hosting Base for Brotli and Gzip

Compression is mostly a configuration issue, but hardware and hosting architecture still matter. On very weak or oversold servers, high compression levels can push CPU to 100% during traffic spikes and actually harm performance.

On our side at dchost.com, when we design hosting plans for dynamic sites (WordPress, WooCommerce, Laravel, Node.js), we consider:

  • vCPU capacity: enough headroom for PHP/Node plus Brotli/Gzip work.
  • Fast NVMe storage: to serve precompressed static assets quickly from disk.
  • Network throughput: so you can benefit fully from reduced payloads.

If your site is growing, it may be time to move from basic shared hosting to a VPS or even a dedicated server, where you have full control over Nginx/Apache/LiteSpeed and can implement all of the settings in this article. For a deeper dive into planning resources for modern PHP apps, see our guides on server-side optimization for WordPress and on NVMe VPS hosting and where the speed really comes from.

Putting It All Together

Well-tuned Brotli and Gzip compression settings are one of the simplest server-side optimizations you can make for better Core Web Vitals. The key is to avoid extremes: do not leave compression disabled, but also do not push levels so high that your CPU becomes the new bottleneck.

On Nginx, Apache and LiteSpeed alike, the winning pattern looks like this:

  • Enable both Brotli and Gzip, with Brotli prioritized for modern browsers and Gzip as a fallback.
  • Compress HTML, CSS, JS and JSON, skip already compressed binaries.
  • Use moderate compression levels (3–6) for dynamic responses and heavy levels for precompressed build-time assets.
  • Combine compression with proper caching headers, a CDN and modern TLS/HTTP to unlock the full benefit.
  • Measure impact on LCP and TTFB, not just on transfer size numbers.

At dchost.com we apply these principles when we prepare new servers, migrate busy sites or audit Core Web Vitals for customers. If you are planning a move to a VPS, dedicated server or colocation and want an environment where Brotli, HTTP/3, TLS 1.3 and modern caching strategies are first-class citizens, building that stack on a solid hosting base matters as much as the config snippets themselves.

Take this article as a checklist: start by enabling safe compression, then iterate on levels, caching and CDN. Combined with the other tuning guides we have shared, you can bring your site into the green zone for Core Web Vitals with changes that are fully under your control on the server side.

Frequently Asked Questions

Brotli usually achieves better compression ratios than Gzip for text-based assets like HTML, CSS and JavaScript, so in many cases it reduces transfer size more. However, it is not always a simple “Brotli is better” answer. Brotli’s higher levels can be CPU intensive, which may increase TTFB on weaker servers or under heavy load. Also, Brotli is typically only used over HTTPS, and older browsers still rely on Gzip. In practice, the best strategy is to enable Brotli at a moderate level for modern clients and keep Gzip as a fallback, then monitor CPU usage and Core Web Vitals to ensure you are gaining speed without overloading the server.

For dynamic content on Nginx, a safe starting point is gzip_comp_level 4 and brotli_comp_level 3–4. These levels give a strong reduction in response size without significantly increasing CPU time per request on typical VPS or dedicated servers. If monitoring shows that CPU usage remains low and your site handles large responses, you can experiment with level 5–6 for both. Use much higher levels (Gzip 8–9, Brotli 9–11) only for precompressed static assets generated at build or deploy time, combined with gzip_static on and brotli_static on, so that users are served those files directly from disk.

You should generally enable both. Modern browsers over HTTPS will prefer Brotli when you advertise it, gaining smaller payloads and better performance. Older browsers and some tools still only support Gzip, so disabling Gzip entirely can break compatibility or degrade experience for a part of your audience. The usual pattern is to configure Brotli first with a moderate quality level, keep Gzip active as a fallback, and ensure you send a Vary: Accept-Encoding header so caches and CDNs handle both variants correctly. This dual setup provides the best mix of performance, compatibility and Core Web Vitals gains.

You can verify compression in several ways. On the command line, use curl with the Accept-Encoding header, for example: curl -I -H 'Accept-Encoding: br' https://example.com/ and curl -I -H 'Accept-Encoding: gzip' https://example.com/. In the response headers, look for Content-Encoding: br or Content-Encoding: gzip, and a Vary: Accept-Encoding header. In the browser, open DevTools, go to the Network tab, reload the page, and inspect an HTML, CSS or JS file. Check the Response Headers and Size columns to confirm that compression is applied and that the transferred size is significantly smaller than the original resource size.