How to gzip vs. brotli for svg files: a practical comparison
- Step 1Get the exact gzip number first — Drop your most common SVGs onto the Compression Estimator and note the gzip estimate — that line is a real deflate-raw measurement plus the 18-byte wrapper, accurate to within a few bytes of a default-level server.
- Step 2Add the brotli rule of thumb, then verify — The estimator's brotli line is gzip × 0.82 (a flat 18% off). Treat it as a lower-bound planning figure. For the assets that matter most, run a real encoder once:
brotli -q 11 icon.svgand compare the.brsize to the gzipped size. - Step 3Check what your server / CDN actually serves — Brotli needs explicit support: Nginx via the brotli module, Apache via mod_brotli, and it's automatic on Cloudflare, Fastly, AWS CloudFront, Vercel, and Netlify. Gzip is universal. Confirm the
content-encoding: brresponse header on a real SVG request in DevTools. - Step 4Pick the right brotli quality for the path — For static SVGs, pre-compress at build time with brotli q11 — maximum ratio, zero runtime cost. For dynamically generated SVG responses, use brotli q4-6, which is competitive with gzip on speed while still beating it on ratio.
- Step 5Enable both with gzip as the fallback — Keep gzip enabled as the fallback for the rare client that doesn't send
Accept-Encoding: br. The browser and server negotiate automatically; you don't choose per-request. - Step 6Re-measure after content optimisation — Compression is multiplicative with content-level cleanup. Run the SVG through the Pro-Minifier and Metadata Scrubber first, then re-estimate — both gzip and brotli operate on the smaller, cleaner input.
Gzip vs. brotli for SVG at a glance
How the two algorithms differ on SVG specifically. Brotli ratios assume quality 11; runtime/dynamic use is typically q4-6.
| Dimension | Gzip (DEFLATE) | Brotli |
|---|---|---|
| Window size | 32 KB sliding window | Up to 16 MB — captures repetition across a whole large SVG |
| Static dictionary | None | ~120 KB dictionary including common HTML/CSS/markup tokens |
| Typical SVG ratio | 70-85% reduction on icons | Usually 5-25% smaller than gzip on the same SVG |
| Encode speed (max quality) | Fast at level 6-9 | Slow at q11 — best done at build time |
| Encode speed (dynamic) | Fast | q4-6 competitive with gzip |
| Decode speed | Fast | Comparable to gzip — no client penalty |
| Browser support | Universal | All modern browsers send Accept-Encoding: br over HTTPS |
Brotli support on common hosts
Whether brotli for text responses (including image/svg+xml) is on by default or needs setup. Verify with the content-encoding response header.
| Host / server | Brotli for SVG | Notes |
|---|---|---|
| Cloudflare | Automatic | On by default for eligible text MIME types |
| Fastly | Automatic | Brotli at the edge for compressible content |
| AWS CloudFront | Automatic | Negotiated when the origin/edge supports it |
| Vercel | Automatic | Static assets pre-compressed and served with br |
| Netlify | Automatic | Brotli served for text assets |
| Nginx | Module required | Build/enable the brotli module; gzip is built-in |
| Apache | Module required | mod_brotli (2.4.26+); mod_deflate for gzip |
What the JAD estimator reports for each
Be precise about measured vs. estimated. The estimator gives you a trustworthy gzip number and a heuristic brotli number.
| Algorithm | Estimator source | Trust level |
|---|---|---|
| Gzip | Real CompressionStream("deflate-raw") output + 18-byte wrapper | Use directly for budgets |
| Brotli | gzip × 0.82 (flat 18% reduction) | Planning ballpark — verify with brotli -q 11 |
Cookbook
Side-by-side readings. The gzip column is the estimator's real measurement; the "estimator brotli" column is its 18% heuristic; the "real brotli" column is from an actual brotli -q 11 run so you can see how the heuristic compares.
Small icon — brotli barely helps
On tiny SVGs the brotli dictionary and window have little to work with, so real brotli is close to gzip — sometimes the estimator's flat 18% is too optimistic at this size.
menu-icon.svg Raw: 212 B Gzip (measured): 168 B Estimator brotli (×0.82): 138 B Real brotli -q11: 159 B <-- only 5% under gzip Lesson: the 18% heuristic overstates the win for tiny icons.
Icon set sprite — brotli pulls ahead
A sprite with many similar <symbol> paths has long-range repetition that brotli's 16 MB window captures and gzip's 32 KB window can't. Here real brotli beats the heuristic.
icons-sprite.svg Raw: 41.0 KB Gzip (measured): 9.8 KB Estimator brotli (×0.82): 8.0 KB Real brotli -q11: 7.4 KB <-- 24% under gzip Lesson: long-range repetition favours brotli > 18%.
Gradient illustration — middle of the road
Path-heavy illustrations land near the heuristic: diverse coordinates limit dictionary gains, but there's still structural repetition for brotli to exploit.
hero-illustration.svg Raw: 90.5 KB Gzip (measured): 31.9 KB Estimator brotli (×0.82): 26.2 KB Real brotli -q11: 26.8 KB <-- ~16% under gzip Lesson: heuristic is close here — within a kilobyte.
Confirming brotli is actually served
Estimating is only half the job — verify the wire. Check the response header in DevTools or curl to confirm the CDN chose brotli for your SVG.
$ curl -sI -H 'Accept-Encoding: br' https://cdn.example.com/logo.svg \
| grep -i 'content-encoding'
content-encoding: br
If you see 'gzip' or nothing, brotli isn't enabled
for image/svg+xml on that host.Build-time pre-compression beats runtime
Pre-compressing to .svg.br at build time lets the server ship the brotli-q11 file with zero per-request CPU. Estimate the gzip floor first to know the budget you're hitting.
# Build step $ brotli -q 11 -k dist/icons/*.svg # produces .svg.br alongside # Nginx serves the precompressed file when present: # brotli_static on; # Result: q11 ratio, no runtime compression cost.
Edge cases and what actually happens
Brotli not negotiated over plain HTTP
Not appliedBrowsers only advertise Accept-Encoding: br over HTTPS. On a plain-HTTP origin the client falls back to gzip even if the server supports brotli. If your SVGs aren't getting brotli, confirm the request is HTTPS before blaming the server config.
Estimator brotli overstates the win on tiny SVGs
Heuristic driftThe flat 18% reduction assumes brotli's dictionary and large window help. On sub-300-byte icons there's little to exploit, so real brotli may be only 3-6% under gzip. The estimator's brotli line is a planning floor, not a promise — verify small critical assets with a real encoder.
Estimator brotli understates the win on large sprites
Heuristic driftOn large files with long-range repetition (icon sprites, tiled patterns), brotli's 16 MB window captures matches gzip's 32 KB window misses, so real brotli can be 20-30% under gzip — better than the 18% heuristic. The estimator is conservative here.
Server uses brotli at a low quality for dynamic responses
Lower ratioDynamic compression typically runs brotli at q4-6 for speed, not q11. The served size is then larger than a build-time q11 file — closer to gzip than the heuristic suggests. Pre-compress static SVGs to capture the full q11 ratio.
CDN skips compression below a size threshold
UncompressedSome CDNs (Cloudflare ~512 bytes) don't compress responses below a threshold because the wrapper overhead isn't worth it. A tiny SVG may ship uncompressed regardless of gzip/brotli config — which matches the estimator showing near-zero savings at that size.
Double compression attempted
No gainServing an already-gzipped .svgz and then re-compressing at the server yields nothing — the data is already high-entropy. Pick one layer: serve plain .svg and let the server compress, or serve precompressed .svg.br/.svgz with the right Content-Encoding. Don't stack both.
Comparing the estimator's gzip to a different server level
Minor driftThe estimator's deflate-raw runs at the browser default level. A server at gzip level 1 (speed) or level 9 (max) differs slightly. For gzip the spread between levels on SVG is small; the estimate stays within a few percent.
Treating the brotli line as your billed transfer size
By designThe estimator never runs brotli. If you need an exact brotli Content-Length for a budget or a contract, measure the real .br file. Use the estimator's gzip figure as the dependable number and brotli as directional.
Frequently asked questions
How much smaller is brotli than gzip on SVG?
Usually 5-25% smaller at quality 11, depending on the file. Tiny icons see the smallest gain (sometimes under 6%); large sprites and tiled patterns with long-range repetition see the largest (20-30%). The JAD estimator models this as a flat 18% reduction — a reasonable middle, but verify the extremes with a real encoder.
Does the JAD estimator measure real brotli?
No. It measures real gzip via the browser's deflate-raw encoder, then estimates brotli as gzip × 0.82 (a flat 18% off). The brotli line is a planning heuristic, not an encoder run. Trust the gzip number; treat brotli as directional.
Is brotli slower to compress than gzip?
At quality 11, yes — substantially. That's why brotli q11 belongs in your build step for static assets, where the cost is paid once. For dynamically generated SVG, use brotli q4-6, which is competitive with gzip on speed while still beating it on ratio. Decode speed is comparable, so there's no client-side penalty.
Should I pre-compress SVGs at build time?
For static SVGs, yes. Generating .svg.br (and optionally .svg.gz) at build time with brotli q11 gives you the best ratio with zero per-request CPU, and servers like Nginx (brotli_static on;) serve the precompressed file automatically. Dynamic or user-generated SVGs are compressed at request time at a lower quality.
Which CDNs give me brotli for SVG without any setup?
Cloudflare, Fastly, AWS CloudFront, Vercel, and Netlify all serve brotli for eligible text MIME types automatically, including image/svg+xml. Self-managed Nginx and Apache need the brotli module enabled explicitly; gzip is built into both.
Does compressing an SVG change how the browser renders it?
No. HTTP compression is transparent: the browser decompresses the response based on the Content-Encoding header before parsing, so the rendered SVG is byte-identical to the original. Compression is purely a transfer optimisation.
Why did brotli barely beat gzip on my small icon?
Brotli's advantages — a big window and a static dictionary — need enough content to pay off. On a sub-300-byte icon there's little repetition to find and the dictionary tokens may not match, so the win shrinks to a few percent. This is exactly where the estimator's 18% heuristic overstates the benefit.
How do I confirm brotli is actually being served?
Request the SVG with Accept-Encoding: br and check the response: curl -sI -H 'Accept-Encoding: br' https://host/logo.svg | grep -i content-encoding. You want content-encoding: br. In DevTools, the Network tab's Response Headers show the same. If it says gzip or nothing, brotli isn't enabled for that MIME type.
Is there any reason to prefer gzip over brotli?
Only operational ones: universal support without a module, and lower CPU for high-throughput dynamic compression if you can't pre-compress. For static SVGs there's no downside to brotli with gzip as the negotiated fallback — enable both.
Does minifying the SVG first change the gzip-vs-brotli gap?
Slightly. Minification removes whitespace and redundant structure, leaving a denser file where both algorithms have less to exploit, narrowing the absolute gap. Both still shrink it further. Always minify with the Pro-Minifier first, then compress.
What about .svgz files?
An .svgz is a gzip-compressed SVG served with Content-Encoding: gzip. It predates widespread brotli. Today it's usually simpler to serve plain .svg and let the server/CDN compress (gzip or brotli), or to precompress to .svg.br. Don't double-compress an .svgz at the server.
Can I automate this comparison across many files?
Yes — pull the gzip figure for each file through the runner-backed API (GET /api/v1/tools/svg-compression-estimator for the schema, then the runner on localhost), and run brotli -q 11 alongside in the same script. See the batch estimation guide for the pipeline shape.
Privacy first
Every JAD SVG tool runs entirely in your browser using the DOM API and Canvas. Your SVG files never leave your device — verified by zero outbound network requests during processing.