Amblem
Furkan Baytekin

Brotli vs Gzip: Modern HTTP Compression Done Right (with Flask Examples)

Brotli vs Gzip compression guide with Flask examples

Brotli vs Gzip: Modern HTTP Compression Done Right (with Flask Examples)
110
3 minutes

Fast websites win. Compression is one of the cheapest performance gains you can get, and today the real choice is Brotli vs Gzip.

Short version:

Let’s break it down and implement it properly.


What Is HTTP Compression?

HTTP compression reduces response size before sending it over the network.

Flow:

  1. Browser sends Accept-Encoding
  2. Server picks the best supported algorithm
  3. Response is compressed and sent with Content-Encoding

Smaller payload = faster load = better Core Web Vitals.


Brotli vs Gzip (Quick Comparison)

Feature Brotli Gzip
Compression ratio ✅ Better ❌ Lower
CPU cost Slightly higher Lower
Static assets Excellent Good
Browser support Modern browsers Universal
Default in HTTP/2/3 Common Common

Rule of thumb:


Browser Support (Client Side)

Modern browsers send this header automatically:

http
Accept-Encoding: br, gzip, deflate

Brotli Supported By

Gzip Supported By

If br is present → use Brotli. If not → use Gzip. If neither → send uncompressed.


Required Response Headers

Compressed Response

http
Content-Encoding: br Vary: Accept-Encoding

Why Vary Matters

Without it, CDNs and proxies may cache the wrong version and serve garbage.

Always include:

http
Vary: Accept-Encoding

Flask Implementation: Brotli + Gzip + Fallback

Install Dependencies

bash
pip install brotli

Basic Flask Compression Middleware

python
from flask import Flask, request, Response import gzip import brotli app = Flask(__name__) def compress_response(data: bytes, encoding: str): if encoding == "br": return brotli.compress(data), "br" if encoding == "gzip": return gzip.compress(data), "gzip" return data, None @app.after_request def apply_compression(response: Response): if response.direct_passthrough: return response accept_encoding = request.headers.get("Accept-Encoding", "") data = response.get_data() encoding = None if "br" in accept_encoding: encoding = "br" elif "gzip" in accept_encoding: encoding = "gzip" compressed, used = compress_response(data, encoding) if used: response.set_data(compressed) response.headers["Content-Encoding"] = used response.headers["Content-Length"] = len(compressed) response.headers["Vary"] = "Accept-Encoding" return response

Serving Compressionless Responses (Opt-Out)

Some endpoints should not be compressed:

Example:

python
@app.route("/health") def health(): response = Response("OK") response.direct_passthrough = True return response

Or explicitly disable compression via header:

python
response.headers["Content-Encoding"] = "identity"

Static Files: Best Practice

For production:

But for local or internal tools, middleware is fine.


SEO Impact

Compression helps SEO indirectly:

Google doesn’t care which compression you use — only that your site is fast.


Final Recommendation

Best setup today:

  1. Brotli for modern browsers
  2. Gzip fallback
  3. Plain response as last resort
  4. Always set Vary: Accept-Encoding
  5. Avoid compressing already-compressed data

If you’re using a CDN later, keep this logic consistent so behavior doesn’t change.

That’s it. Simple, correct, future-proof.


Album of the blog:

Suggested Blog Posts