If I understand correctly it's better not to gzip small resources as they might actually get bigger while still having a performance hit on the CPU. So using the gzip_min_length directive is an obvious solution to that. However, when trying this on a server that runs a REST API I'm working on this doesn't seem to work. When I receive an empty json response, or a very small one, the Content-Encoding header is still present and reading "gzip".
HTTP Response headers
My question is why this setting is not being respected by NginX and what can I do to fix it?
The API is built on the Lumen microframework.
I have attached the Gzip setting I'm using in my nginx.conf:
# Compression
# Enable Gzip compressed.
gzip on;
# Enable compression both for HTTP/1.0 and HTTP/1.1.
gzip_http_version 1.1;
# Compression level (1-9).
# 5 is a perfect compromise between size and cpu usage, offering about
# 75% reduction for most ascii files (almost identical to level 9).
gzip_comp_level 5;
# Don't compress anything that's already small and unlikely to shrink much
# if at all (the default is 20 bytes, which is bad as that usually leads to
# larger files after gzipping).
gzip_min_length 1000;
# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
gzip_proxied any;
# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
# Avoids the issue where a non-gzip capable client (which is extremely rare
# today) would display gibberish if their proxy gave them the gzipped version.
gzip_vary on;
# Compress all output labeled with one of the following MIME-types.
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/x-component;
# text/html is always compressed by HttpGzipModule
If you take a file that is 1300 bytes and compress it to 800 bytes, it's still transmitted in that same 1500 byte packet regardless, so you've gained nothing. That being the case, you should restrict the gzip compression to files with a size greater than a single packet, 1400 bytes (1.4KB) is a safe value.
The other reason Gzip might not be working is that you have extremely large files on your site. Older version of Gzip have a file size limit of something like 2GB. Any file larger than that will not be compressed using the Gzip algorithm. That is, however, relying on the older algorithms.
You can configure Nginx to use gzip to compress the files it serves on the fly. Those files are then decompressed by the browsers that support it upon retrieval with no loss whatsoever, but with the benefit of a smaller amount of data to transfer between the web server and browser.
The data is clear that Brotli offers a better compression ratio than GZIP. That is, it compresses your website “more” than GZIP. However, remember that it's not just about the compression ratio, it's also about how long it takes to compress and decompress data.
Confirming my note above, this does seem to correspond to the note in the NGINX gzip module documentation stating "The length is determined only from the “Content-Length” response header field."
With gzip_min_length 1000;
, my JSON responses were being gzip'ed, even if they were only 100 bytes.
I changed my application to add the Content-Length: 100
header and NGINX sends the JSON response without using the gzip encoding.
If I change the configuration to gzip_min_length 80;
with the same 100-byte Content-Length, then NGINX applies the gzip encoding as expected.
Short story: you need to apply the Content-Length
header for NGINX to properly handle the gzip_min_length
check.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With