Page speed has been a constant obsession of mine ever since a client’s Core Web Vitals scores tanked their search rankings a couple of years back. One of the simplest, highest-impact changes I made that day was enabling compression on the server. Smaller responses mean faster page loads, less bandwidth usage, and happier visitors (and search engines).
Historically, that meant mod_gzip. These days, if you’re running a modern version of Apache, you’ll actually want mod_deflate instead — I’ll explain why, and cover both, so you understand the full picture and know exactly what to use.
What Is mod_gzip (and Why mod_deflate Replaced It)
mod_gzip was a third-party Apache module used with Apache 1.3 to compress HTTP responses using gzip before sending them to the client. It was widely used in the early-to-mid 2000s.
Since Apache 2.0, the built-in mod_deflate module has effectively replaced mod_gzip. It does the same job — gzip-compressing responses — but it’s maintained as part of core Apache, better integrated, and doesn’t require a separate third-party build. If you’re on Apache 2.x (which is almost certainly the case today), mod_deflate is what you actually want, even though a lot of people still refer to “enabling gzip” out of habit.
I’ll walk through both, but I strongly recommend mod_deflate for any current setup.
Prerequisites
- Apache 2.x installed (check with
apache2 -vorhttpd -v) - Root or sudo access
- Basic familiarity with editing Apache config files
Enabling mod_deflate (Recommended for Apache 2.x)
Step 1: Enable the Module
On Debian/Ubuntu:
sudo a2enmod deflate
sudo systemctl restart apache2
On CentOS/RHEL, mod_deflate is typically built in and just needs to be loaded in your config:
LoadModule deflate_module modules/mod_deflate.so
Step 2: Configure Compression
Create or edit a config file for compression settings. On Debian/Ubuntu, I put this in /etc/apache2/mods-available/deflate.conf:
<IfModule mod_deflate.c>
# Compress common text-based file types
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE image/svg+xml
# Don't compress already-compressed formats
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|zip|gz|bz2|rar|mp4|mp3)$ no-gzip dont-vary
# Handle proxies correctly
Header append Vary User-Agent env=!dont-vary
</IfModule>
Step 3: Test and Reload
sudo apachectl configtest
sudo systemctl reload apache2 # Debian/Ubuntu
sudo systemctl reload httpd # CentOS/RHEL
Setting the Compression Level
mod_deflate lets you tune how aggressively it compresses versus how much CPU it uses:
DeflateCompressionLevel 6
The scale runs from 1 (fastest, least compression) to 9 (slowest, best compression). I almost always leave this at the default (6) — it’s a solid balance. Going to 9 rarely saves much more bandwidth but noticeably increases CPU load on busy servers.
Verifying Compression Is Working
The easiest check is with curl:
curl -H "Accept-Encoding: gzip" -I https://example.com
Look for Content-Encoding: gzip in the response headers. You can also check actual size savings:
curl -s -H "Accept-Encoding: gzip" https://example.com -o /tmp/compressed.html
curl -s https://example.com -o /tmp/uncompressed.html
ls -la /tmp/compressed.html /tmp/uncompressed.html
I also regularly use browser dev tools (Network tab) to confirm the Content-Encoding header on real page loads, and tools like GTmetrix or Google PageSpeed Insights to see the measured impact.
Legacy mod_gzip Setup (Apache 1.3, Historical Reference)
If you’re maintaining a genuinely legacy Apache 1.3 system (increasingly rare, but I’ve encountered a few), here’s the old-school config for reference:
LoadModule gzip_module modules/mod_gzip.so
<IfModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file \.html$
mod_gzip_item_include file \.css$
mod_gzip_item_include file \.js$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/javascript$
mod_gzip_item_exclude mime ^image/.*
</IfModule>
Realistically, if you’re seeing this on a live server today, I’d strongly recommend planning a migration to a current Apache version and switching to mod_deflate (or even better, mod_brotli alongside it — more on that below).
Bonus: Brotli Compression
Since I’m on the topic, it’s worth mentioning mod_brotli, which offers better compression ratios than gzip in many cases and is supported by all modern browsers. If your Apache build includes it:
sudo a2enmod brotli
<IfModule mod_brotli.c>
AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript application/json
</IfModule>
I usually configure both mod_deflate and mod_brotli together — Apache will serve Brotli to clients that support it and fall back to gzip otherwise.
Compression at the Origin vs. at a CDN
If you’re running a CDN in front of Apache, it’s worth understanding where compression actually happens. Some CDNs re-compress content at the edge regardless of what the origin sends, while others simply pass through whatever Content-Encoding the origin already applied. I always check my CDN’s specific behavior rather than assuming — enabling mod_deflate at the origin is still worthwhile even behind a CDN, since it reduces the size of the origin-to-edge transfer and protects you if the CDN is ever bypassed (health checks, direct-to-origin debugging, cache misses, etc.).
I’ve also run into cases where a CDN’s own compression conflicted with an already-compressed response from Apache, causing subtly broken behavior for certain older clients. If you notice this, it’s usually safer to let one layer (typically the CDN) own compression and disable it at the other.
Real-World Use Cases
- Text-heavy sites (blogs, documentation, news): HTML/CSS/JS compress extremely well, often 60–80% smaller.
- JSON APIs: Compressing API responses meaningfully reduces payload size for mobile clients on slower connections.
- SVG-heavy sites: SVGs are XML-based text and compress very well, unlike raster images.
- Sites targeting Core Web Vitals / SEO: Faster Time to First Byte and smaller payloads directly help page speed scores.
Measuring the Real-World Impact
After enabling compression on any site, I like to quantify the actual improvement rather than just assuming it helped. A quick before/after comparison using curl‘s timing output gives a rough sense of transfer time differences:
curl -w "Time: %{time_total}s | Size: %{size_download} bytes\n" -o /dev/null -s -H "Accept-Encoding: gzip" https://example.com
curl -w "Time: %{time_total}s | Size: %{size_download} bytes\n" -o /dev/null -s https://example.com
For a more complete picture, I run the page through Google PageSpeed Insights or WebPageTest before and after, paying attention to metrics like Time to First Byte and total transferred bytes. On text-heavy pages, it’s common to see a 60–70% reduction in transferred size once compression is properly enabled — a meaningful win for very little setup effort.
Troubleshooting Tips
- If compression doesn’t seem to be applying, confirm the module is actually loaded:
apachectl -M | grep deflate. - If images or already-compressed files are being (uselessly) re-compressed, check your
SetEnvIfNoCaseexclusion rules. - If a reverse proxy or CDN sits in front of Apache, make sure it isn’t stripping the
Accept-Encodingheader before it reaches Apache. - If you see garbled content in the browser, it’s almost always a double-compression issue — check that a CDN or another layer isn’t also compressing an already-compressed response.
Common Mistakes to Avoid
- Compressing already-compressed file types (images, videos, zip files) — wastes CPU for zero benefit.
- Setting compression level to 9 by default — rarely worth the CPU cost.
- Forgetting the
Vary: Accept-Encodingheader, which can cause caching proxies to serve the wrong (compressed/uncompressed) version to the wrong clients. - Using deprecated
mod_gzipon a modern Apache 2.x install whenmod_deflateis built in and better supported. - Not testing actual byte savings — assuming compression is working without verifying it.
Security Best Practices
- Be aware of the BREACH attack, which can exploit compression combined with reflected secrets in responses (e.g., CSRF tokens in compressed HTML alongside user input). Mitigate by not reflecting sensitive tokens into compressible response bodies alongside attacker-controlled input, or by disabling compression selectively on sensitive endpoints.
- Keep Apache and
mod_deflate/mod_brotliupdated as part of your regular patching cycle.
Performance Optimization
- Combine compression with proper caching headers (see my mod_expires post) for maximum speed benefit.
- Compress text-based assets only — binary/media files should rely on proper encoding at creation time (e.g., WebP for images) rather than HTTP-level compression.
- Monitor CPU usage after enabling compression on high-traffic servers; if CPU becomes a bottleneck, consider offloading compression to a CDN or reverse proxy layer instead.
Frequently Asked Questions
Q: Should I use mod_gzip or mod_deflate? A: Use mod_deflate — it’s the modern, built-in replacement for mod_gzip in Apache 2.x.
Q: Does compression slow down my server? A: It adds a small CPU cost per request, but for text-based content the bandwidth and load-time savings almost always outweigh it.
Q: How do I verify compression is actually working? A: Use curl -H "Accept-Encoding: gzip" -I https://yoursite.com and check for Content-Encoding: gzip in the response.
Q: What compression level should I use? A: Level 6 is a good default — it balances compression ratio and CPU usage well for most sites.
Q: Can I compress images with mod_deflate? A: No, don’t bother — image formats like JPEG and PNG are already compressed, and re-compressing them wastes CPU without meaningful size savings.
Summary and Key Takeaways
Enabling compression is one of the fastest, cheapest performance wins available for any Apache server. To recap:
- Use
mod_deflateon modern Apache 2.x installs —mod_gzipis legacy and Apache 1.3-specific. - Compress text-based content only (HTML, CSS, JS, JSON, SVG, XML).
- Set a reasonable compression level (6 is a solid default).
- Verify compression is actually applied with
curlor browser dev tools. - Consider adding Brotli alongside gzip for even better compression ratios.
It’s a fifteen-minute setup that pays off on every single page load from then on.