HTTP/2 and Brotli on NGINX: A Comprehensive Guide to Maximum Speed

Table of Contents
Big thanks to our contributors those make our blogs possible.

Our growing community of contributors bring their unique insights from around the world to power our blog. 

Introduction

Page speed is no longer a “nice to have”—it’s a business imperative. Slow-loading pages frustrate users, increase bounce rates, and hurt SEO rankings. Two of the most powerful techniques in your performance toolkit are HTTP/2 and Brotli compression. HTTP/2 revolutionizes how browsers and servers communicate by introducing multiplexing, header compression, and server push. Brotli, Google’s modern compression algorithm, consistently outperforms Gzip, reducing text asset sizes by up to 25% more. When combined on NGINX, these technologies can deliver dramatic improvements in Time to First Byte (TTFB), Largest Contentful Paint (LCP), and overall bandwidth consumption. In this in-depth guide, we’ll cover:

  • HTTP/2 fundamentals and benefits
  • Brotli vs. Gzip: why choose Brotli
  • Installing and enabling the Brotli module
  • Configuring NGINX for HTTP/2, Brotli, and Gzip fallback
  • Pre-compressing assets in your build pipeline
  • Leveraging HTTP/2 Server Push responsibly
  • Testing, monitoring, and troubleshooting

By the end, you’ll have everything you need to transform your NGINX server into a high-performance asset delivery machine.

1. Deep Dive into HTTP/2

Why HTTP/1.1 Falls Short

  • Head-of-Line Blocking: One slow request stalls the entire TCP connection.
  • Multiple Connections: Browsers open several parallel connections per domain, incurring TCP/TLS handshakes and resource contention.
  • Redundant Headers: Repeated header fields waste bandwidth.

HTTP/2 Key Features

  1. Multiplexing:
    • Multiple streams (requests/responses) share a single connection.
    • Eliminates head-of-line blocking at the application layer.
  2. Binary Framing & Header Compression (HPACK):
    • Frames are compact and fast to parse.
    • HPACK compresses headers, reducing overhead for repeat requests.
  3. Stream Prioritization:
    • Clients assign weights to streams, guiding server on which assets matter most.
  4. Server Push:
    • Servers can send critical resources (e.g., CSS/JS) proactively before the client requests them.

Analogy: HTTP/1.1 is like a narrow one-lane road; HTTP/2 is a multilane highway with on-ramps and traffic priority lanes.

2. Brotli Compression: The Superior Codec

Brotli vs. Gzip

FeatureGzipBrotli
Compression RatioBaseline15–25% smaller
Levels of Compression1–91–11
CPU OverheadModerateHigher at top levels
Browser SupportUniversalModern browsers (Chrome, Firefox, Edge, Safari 14+)
Decompression PerformanceFastComparable (native C++)

When to Use Brotli

  • Text Assets: HTML, CSS, JavaScript, JSON, SVG.
  • High-Value Pages: Landing pages, critical JS bundles.
  • CDN Edge: Offload compression cost to build or CDN edge rather than origin server.

3. Prerequisites and Environment

  1. NGINX ≥ 1.9.5 (built-in HTTP/2 support)
  2. Linux environment (Ubuntu/Debian/CentOS)
  3. SSL/TLS certificate (Let’s Encrypt or commercial)
  4. Root or sudo privileges

Ensure your server’s OpenSSL and zlib are up to date to support the latest protocols and ciphers.

4. Installing the Brotli Module

Using Your Distro’s Package (Ubuntu/Debian)

bashCopyEditsudo apt-get update
sudo apt-get install -y nginx libnginx-mod-http-brotli
# Enable the module
sudo ln -s /usr/share/nginx/modules-available/mod-http-brotli.conf \
         /etc/nginx/modules-enabled/50-mod-http-brotli.conf
sudo nginx -t && sudo systemctl reload nginx

Compiling as Dynamic Module

bashCopyEdit# Install build tools
sudo apt-get install -y build-essential libpcre3-dev zlib1g-dev libssl-dev git

# Download NGINX and Brotli
cd /usr/local/src
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar zxvf nginx-1.24.0.tar.gz
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli && git submodule update --init

# Compile module
cd ../nginx-1.24.0
./configure --with-compat --add-dynamic-module=../ngx_brotli
make modules

# Install modules
sudo cp objs/ngx_http_brotli_filter_module.so /etc/nginx/modules
sudo cp objs/ngx_http_brotli_static_module.so /etc/nginx/modules
echo "load_module modules/ngx_http_brotli_filter_module.so;" | sudo tee /etc/nginx/modules-enabled/50-brotli.conf
echo "load_module modules/ngx_http_brotli_static_module.so;" | sudo tee -a /etc/nginx/modules-enabled/50-brotli.conf

sudo nginx -t && sudo systemctl reload nginx

5. Configuring NGINX

Edit your server block (e.g., /etc/nginx/sites-available/example.com.conf):

nginxCopyEditserver {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # --- SSL/TLS Settings ---
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    # --- Brotli & Gzip ---
    brotli              on;
    brotli_comp_level   6;
    brotli_types        text/plain text/css application/javascript application/json image/svg+xml;

    gzip                on;
    gzip_comp_level     5;
    gzip_static         on;
    gzip_types          text/plain text/css application/javascript application/json image/svg+xml;

    # --- HTTP/2 Server Push (use sparingly) ---
    location = /index.html {
        http2_push /css/styles.css;
        http2_push /js/main.js;
        try_files $uri =404;
    }

    # --- Content Serving ---
    root   /var/www/example.com/html;
    index  index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Directive Breakdown

  • listen 443 ssl http2;: Enables HTTP/2 over TLS.
  • brotli on; brotli_comp_level 6;: Activates Brotli at level 6—sweet spot for ratio vs. CPU.
  • gzip_static on;: Serves pre-compressed .gz files if available.
  • http2_push: Pushes critical assets; limit to top 2–3 to avoid wasted bandwidth.

6. Pre-Compressing Static Assets

Offload compression from runtime by generating .br and .gz during your CI/CD build:

bashCopyEdit# In your build script:
find ./public -type f \( -name '*.js' -o -name '*.css' -o -name '*.html' \) | while read file; do
  brotli --quality=6 --keep "$file"
  gzip -k -5 "$file"
done
  • Place generated file.js.br and file.js.gz alongside originals.
  • NGINX serves pre-compressed assets with brotli_static and gzip_static.

7. Leveraging HTTP/2 Server Push Responsibly

When to Push

  • Hero CSS & JS: Critical-path rendering resources.
  • Fonts: Preload and push if above-the-fold text uses web fonts.

Example HTML Hints

htmlCopyEdit<link rel="preload" href="/css/styles.css" as="style">
<link rel="preload" href="/fonts/Inter.woff2" as="font" type="font/woff2" crossorigin>

Pair <link rel="preload"> with server push to reinforce critical resources.

Avoiding Over-Push

  • Monitor Network waterfall—avoid pushing large images or scripts users may never need.
  • Use analytics to identify truly critical assets.

8. Testing and Verification

Command-Line Checks

bashCopyEdit# HTTP/2 check
curl -I --http2 https://example.com | grep HTTP

# Brotli check
curl -H "Accept-Encoding: br" -I https://example.com/css/styles.css | grep content-encoding

Browser DevTools

  • Network → Protocol: Look for “h2”.
  • Headers → Response: Confirm content-encoding: br or gzip.
  • Lighthouse Audit: “Enable text compression” and “Avoid chaining critical requests”.

Real User Monitoring (RUM)

  • Tools like SpeedCurve, Lighthouse CI, New Relic Browser track LCP, TTI, FCP before/after changes.

9. Monitoring, Logging, and Troubleshooting

NGINX Logs

  • Access logs: Include $upstream_http2_stream_id and compression headers.
  • Error logs: Look for module load failures or misconfigurations.

Common Pitfalls

  • Missing as in preload: Browser may ignore server push without corresponding hints.
  • Over-compression: Don’t Brotli binary assets (images, video).
  • CORS with fonts: Include crossorigin on <link> and ssl_prefer_server_ciphers on;.

Rollback Strategy

  • Comment out http2 or brotli directives and reload NGINX.
  • Use Canary testing (subset of servers) to mitigate widespread issues.

Conclusion

Implementing HTTP/2 and Brotli compression on NGINX delivers substantial performance gains: fewer connections, faster delivery, and smaller payloads. By following this guide—installing the Brotli module, configuring NGINX for secure HTTP/2, pre-compressing assets in your build pipeline, and leveraging server push responsibly—you’ll slash TTFB, improve LCP, and enhance user satisfaction. Remember to rigorously test with both lab tools and RUM, monitor logs for anomalies, and keep compression levels balanced for CPU efficiency. Start optimizing today, and your pages will load faster, rank higher, and convert better.

Let's connect on TikTok

Join our newsletter to stay updated

Sydney Based Software Solutions Professional who is crafting exceptional systems and applications to solve a diverse range of problems for the past 10 years.

Share the Post

Related Posts