I want to share a small, useful tip that I learned when optimising the data transfer cost for a website hosted on Nginx in AWS. Simply by applying the built-in Gzip module in Nginx, I was able to compress HTTP responses before they’re sent to users’ browsers. This significantly reduced the size of the data transmitted over the network, helping to lower bandwidth usage (reducing data transfer cost) and improve load times.
Despite its usefulness, it’s not enabled by default in Nginx on Ubuntu 24.04. It might be enabled on other previous versions, I’m not really sure. Anyways, no matter what version you’re in, when you enable gzip in Nginx, by default it applies only with MIME type text/html, if we have any other MIME types on our website, we have to configure it ourselves.
My use case
I was actually having this gzip configuration enabled for my Nginx web server. I’ve also specified gzip_types for MIME types that the web server is serving. However, I missed including one MIME type, which the site doesn’t use very often, but in rare cases, I have a job to make a request to content that contains this MIME type. It revealed that the data transfer cost increased suddenly higher than normal, which caught my attention. I would have never thought gzip was something related to data transfer in AWS (it’s a shortage of my domain knowledge I acknowledge). That’s when I realized that the gzip module from Nginx not only improves performance in normal cases but also matters in data transfer, and data transfer refers to cost.
I’ll demonstrate a small example of before and after we configure gzip compression in Nginx to explain more clearly.
Prerequisite
- A simple Ubuntu 24.04 server with Nginx installed. You could test with other Linux distros, but the location of Nginx configuration files might be a bit different. However, the core syntax and gzip directive of Nginx can still be used no matter what distro you’re using.
Before configuring gzip compression
After you installed Nginx and started nginx service. You will have a file /etc/nginx/conf.d/default.conf like mine, see below
server {
listen 80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# Other configurations...
}We will then have index.html file in /usr/share/nginx/html directory. The file has .html extension indicating that it’s a html page, if we have gzip enabled, it will be compressed by default because it’s the MIME type text/html, currently I haven’t enabled it yet. In here, simply run:
curl -H "Accept-Encoding: gzip" -I http://localhost/index.html
Output

It will show Accept-Ranges: bytes header in the output with size is 615 bytes, and there is no Content-Encoding: gzip header appear there. It means the file is served without any compression.
We continue creating two more files with specified size at in /usr/share/nginx/html directory to test. Simply run:
sudo truncate -s 2k /usr/share/nginx/html/example.js
sudo truncate -s 2k /usr/share/nginx/html/example.png
truncate command allows to create files with specified size. In here, we have two files with size of 2048 bytes each.
Testing application/js type for file example.js:
curl -H "Accept-Encoding: gzip" -I http://localhost/example.js
Output:

You see that we have example.js file that has a size of 2048 bytes with content type is application/js, and it’s not compressed yet.
Testing image/png type for file example.png:
curl -H "Accept-Encoding: gzip" -I http://localhost/example.png
Output:

Similar what we have done for js file, the content of example.png is again not compressed yet.
Imagine your website serves thousands of files in various formats and sizes, some as large as 200KB, 1000KB, or more. Without using Nginx’s gzip module to compress these files, users’ browsers will have to download them in full, which consumes more bandwidth and slows down page loading. This is where gzip comes into play, it compresses responses on the fly, significantly reducing data size and improving load times for users.
Configure the Gzip compression with Nginx
In your default /etc/nginx/nginx.conf file, we have something like:
user www-data;
# Other configurations...
http {
# Other configurations...
...
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}The default file includes all *.conf files in /etc/nginx/conf.d/. We just need to create gzip.conf in this directory.
Simply run sudo nano /etc/nginx/conf.d/gzip.conf and add the following content:
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/vnd.ms-fontobject
application/wasm
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/bmp
image/png
image/svg+xml
image/vnd.microsoft.icon
image/x-icon
text/cache-manifest
text/calendar
text/css
text/javascript
text/markdown
text/plain
text/xml
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy;Press Ctrl + O and press Enter to save the content. Then press Ctrl + X to exit.
Where:
gzip_on: enable Gzip modulegzip_comp_level: level of compression that we want to specify.gzip_min_length: avoid compressing files smaller than this size to prevent a gzip file being larger than the original.gzip_proxied: compress data even for clients that are connecting to us via proxies (required for Cloud Front)gzip_vary: It tells Nginx to include theVary: Accept-EncodingHTTP header in its response when gzip compression is used.gzip_types: specifiy MIME types should be compressed.
In the configuration file, I’m listing all MIME types suggested by Nginx Server Configs (please view it for more details) plus image/png for testing purposes. The link is a collection of Nginx config files that the community recommends to improve the website’s performance and security. I found they have a few other configuration templates that might benefit you in the same way they benefit me.
If you want to check for more MIME types, please consult the docs here.
Also, I would recommend you should be careful while configuring the
gzip_typesdirective, and you should only set the MIME/gzip types that you’re really going to serve.
Now, we just need to restart nginx service to make new configuration take effect, we run:
sudo systemctl restart nginx.service
Testing after configuration gzip
We run the curl commands at the beginning again to see how it looks after enabling gzip.
For content type: text/html of index.html file

We now see that it has Content-Encoding: gzip header appear the bottom, which means the file is served with compression.
Check the downloadable file size of index.html. Run:
curl -s -H "Accept-Encoding: gzip" -o /dev/null -w '%{size_download}\n' http://localhost/index.html
Output

The file size of index.html is 394 bytes (after compression) compared to 615 bytes (before compression).
Similar to application/js type for the example.js file:

Check the downloadable file size of example.js file. Run:
curl -s -H "Accept-Encoding: gzip" -o /dev/null -w '%{size_download}\n' http://localhost/example.js
Output

The file size now is just 35 bytes (after compression) compared to 2048 bytes (before compression).
And for image/png type for the example.png file:

Check the downloadable file size of of example.png file. Run:
curl -s -H "Accept-Encoding: gzip" -o /dev/null -w '%{size_download}\n' http://localhost/example.png
Output:

The file size now is again, just 35 bytes (after compression) compared to 2048 bytes (before compression).
We now can see how useful gzip module is when we use it properly. Hope you can get some benefits from reading this blog. Thank you.
Discover more from Turn DevOps Easier
Subscribe to get the latest posts sent to your email.
