I run free performance audits on "roast my website" posts. Most findings are boring in a healthy way: oversized JPEGs, render-blocking scripts, a missing cache header. This week I found something I had never seen before, and I want to show you how to check your own site for it, because nothing in your normal workflow will warn you.
A site I audited transferred 5.2MB across 20 requests on a cold load. More than half of that - 2.9MB on the wire, 8.2MB after decompression - was a single SVG file. It rendered as a navigation arrow. At 24 pixels.
One arrow. Three megabytes. That's the biggest byte-per-pixel ratio I've ever measured on a production site.
How an SVG gets to 8MB
SVG is a text format, so I opened the file expecting to find an embedded raster image (the usual way SVGs get huge - a base64 PNG hiding inside). That's not what this was.
The file was one single <path> element. Its coordinate list was exported at full machine precision: 15 decimal places per value, including scientific-notation numbers like -3.16856e-06 - for a viewBox that's 37 by 36 units, rendered at 24px.
Think about what that precision means physically. A 37-unit-wide viewBox drawn at 24px means one unit is smaller than one pixel. Fifteen decimal places of a unit is roughly a millionth of a billionth of a pixel. Every one of those digits is a byte that gets shipped, decompressed, and parsed - and none of them can possibly affect the rendered output, because the output resolution ran out twelve decimal places earlier.
This is not the site owner's fault, and that's the point of writing this up. Design tools will happily serialize paths at whatever precision their internal math produced. If a curve was generated by a boolean operation or a trace, the coordinates come out looking like floating-point noise - because they are. The exporter doesn't round; the developer pastes the asset in; the icon looks perfect; nobody ever opens a .svg in a text editor.
Why nothing warned them
- It looks fine. The icon renders crisply. There is no visual symptom at all.
- The site "feels fast" to the owner. On the owner's fast connection with a warm cache, the page loaded in about 1.3 seconds. The 3MB tax is only felt by first-time visitors - which for a small business site means exactly the people the site exists to convince.
- Bundlers don't parse SVG geometry. Your build tool reports the file size if you look, but nothing flags "this asset is 3000x larger than its information content."
- Lighthouse buries it. It shows up inside a generic "reduce payload" line item, indistinguishable from a big hero photo that might be a legitimate choice.
The two-minute check
Paste this in your browser console on your own site:
const res = performance.getEntriesByType('resource');
res.map(r => ({
file: r.name.split('/').pop().split('?')[0],
transferKB: Math.round((r.transferSize || 0) / 1024),
decodedKB: Math.round((r.decodedBodySize || 0) / 1024)
})).sort((a, b) => b.transferKB - a.transferKB).slice(0, 10);
You're scanning the top-10 for two smells:
-
Any
.svgabove ~20KB. Icons should be single-digit KB. A 100KB+ SVG is either an embedded raster or precision noise. - A large decoded-to-transfer ratio on text assets. My arrow was 2.9MB transferred but 8.2MB decoded - repetitive digit soup compresses well, which is exactly why it sneaks past "the page doesn't feel that heavy" intuition while still costing real decompression and parse time on a phone.
The fix is one command
npx svgo arrow.svg --precision=1 -o arrow.min.svg
SVGO with 1-2 decimal places of precision is visually lossless for icon-sized art. For this file, the projected result was under 1KB - roughly a 3000x reduction, from more than half the page's weight to a rounding error. If you re-export from the design tool instead, set the export precision to 1 or 2 decimals; the default in several tools is "whatever the float said."
While you're at it, the same audit pass usually catches the quieter siblings of this bug: a photo shipped at 2048px into a 1300px slot (that site had one - 910KB where ~150KB would do) and a 76KB favicon (also present; ~10x the norm).
The takeaway
Vector doesn't mean small. SVG size scales with path complexity times export precision, not with rendered size, and export precision is set by a tool you probably never configured. The cheapest performance win I found all week was, literally, rounding.
I build a lot of these checks into SpeedKit, a Claude Code skill that runs a full speed audit on any site. But honestly: the console snippet above is free and takes two minutes - start there.
Top comments (0)