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.
İçindekiler
- 1 How Compression Affects Core Web Vitals
- 2 Brotli vs Gzip: What You Really Need to Know
- 3 Tuning Brotli and Gzip on Nginx
- 4 Tuning Brotli and Gzip on Apache (mod_deflate, mod_brotli)
- 5 Brotli and Gzip on LiteSpeed/OpenLiteSpeed
- 6 Practical Tuning Strategy Across All Web Servers
- 7 Choosing the Right Hosting Base for Brotli and Gzip
- 8 Putting It All Together
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: gziporContent-Encoding: brVary: 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-Encodingisgziporbr. - 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-Encodingis 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.
