HTTP Compression (gzip/Brotli) on WordPress: Why It's Mandatory and How to Enable It Right

gzip or Brotli compression shrinks HTML/CSS/JS by 60-80% and slashes load times, especially on mobile. Here's how to enable it correctly.

HTTP compression is the mechanism where your server sends HTML, CSS, and JavaScript in compressed form and the browser decompresses it before parsing. For text content, gzip easily strips 60-80% of bytes, and Brotli (the more modern standard) saves another 15-20% on top of gzip. This is one of the few performance optimizations that must be enabled on every production site - it takes five minutes to turn on and the impact on load time is unmistakable.

Why this matters

A typical homepage HTML weighs 80-200KB uncompressed. gzip pulls that down to 15-40KB; Brotli to 12-32KB. The same applies to CSS (a heavy theme stylesheet drops from 300KB to 40KB) and to JavaScript (a page builder bundle from 500KB to 100KB). On a realistic mobile 4G connection at 5Mbps, saving 200KB equates to roughly 300ms less download time - exactly the slack you need to keep LCP under the 2.5-second Core Web Vitals threshold.

The biggest impact lands on weak mobile networks. A user on rural 1Mbps downloading 80KB of compressed HTML instead of 400KB sees three seconds shaved off the page. Without compression, that visit ends in abandonment; with compression the site feels acceptable.

How to detect

Ask the server directly with curl:

curl -H "Accept-Encoding: gzip, br" -I https://YOUR-SITE/

Look for Content-Encoding: gzip or Content-Encoding: br in the response. Neither header means compression is off. Browser-friendly alternatives: giftofspeed.com/gzip-test and tools.keycdn.com/brotli-test do the check without a terminal.

In Chrome DevTools: F12 > Network > reload > click the HTML document > Headers panel. Under Response Headers look for Content-Encoding. The Size column shows compressed bytes followed by the uncompressed size in parentheses.

How to fix

For Apache with .htaccess:

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

For Nginx, edit your config and add inside the http block:

gzip on;
gzip_vary on;
gzip_min_length 256;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/javascript
           application/json image/svg+xml text/xml;

If your stack supports Brotli (LiteSpeed, OpenLiteSpeed, Nginx built with ngx_brotli), enable it instead of or alongside gzip - it is more efficient. On cPanel hosts the toggle usually lives in "Optimize Website" or via support ticket. Behind Cloudflare or any CDN, Brotli is on by default; just confirm "Brotli" stays enabled under Speed > Optimization.

Flush page cache (WP Rocket, LiteSpeed Cache, W3 Total Cache) after the change. Already-cached pages were stored uncompressed and keep going out that way until the cache rotates.

Common mistakes

Do not compress images (JPG, PNG, WebP) - they are already compressed internally and another gzip pass burns CPU for nothing. Do not push gzip_comp_level above 6; levels 7-9 cost a lot of CPU and save almost nothing extra. Avoid PHP-side ob_gzhandler: it is slower than server-level compression and breaks streaming AJAX endpoints. And if there is a reverse proxy or CDN in front of your origin, make sure it forwards Accept-Encoding; otherwise the origin will keep sending uncompressed responses.

Verifying the fix

Repeat the curl check and confirm Content-Encoding appears. PageSpeed Insights should drop the "Enable text compression" warning, and the "Network payloads" category should show a 50-70% reduction in transferred bytes. In WebPageTest, compare the Visual Progress graph before and after - Speed Index typically improves by 20-40%.

Tip: Brotli always beats gzip, but every browser requires HTTPS for it. If your config refuses to take effect, verify the certificate is valid and that no part of the page falls back to plain HTTP.