What actually moves the needle
Fonts are usually the biggest performance win nobody looks at. What moves the numbers is the pipeline: where the font is served from, what format it's in, how big it is, and whether the browser knows to fetch it early. Get those right and the font arrives fast enough that nothing downstream has to paper over a slow load. So that's the order I work in — heaviest lever first.
Self-host the font
My first move is always to pull the font off any third-party host and serve it from my own origin. A Google Fonts URL means a fresh DNS lookup, TLS handshake and connection to another server before the font can even start downloading — often with a render-blocking stylesheet on top. Self-hosting collapses all of that into a request to an origin the browser is already talking to.
Speed is why I do it, but it pays twice: it's one fewer external dependency and one fewer call off my server, which is a little more private and a little more robust — nothing third-party to break, change, or watch who's visiting. I'm here for the milliseconds, but I'll take the smaller surface too.
Ship it as woff2
Format is a free win. woff2 is the most compressed web-font format there is —
noticeably smaller than woff, and nowhere near raw ttf or
otf — and every browser I care about has supported it for years. I serve woff2 and
nothing else; the older formats would only add bytes for browsers I don't have.
Subset, and cut the fonts you don't need
This is the biggest lever of all. A full font file carries glyphs for scripts my site will never render, so I subset to Latin and drop the rest — that's where most of the weight disappears. Then I cut the families and weights down to the few the design truly uses; every extra weight is another file to fetch.
It compounds harder than it looks. On a site a friend and I recently reviewed, tightening the font layer alone — format, self-hosting, subsetting, fewer families, preloading the right ones — cut the font payload by roughly 10× and took the page from a PageSpeed score of 47, with FCP and LCP in the 10-second range, to 92–96 with both metrics between 2.0 and 2.7s. Same content, same design — the fonts just stopped being the bottleneck.
Preload the ones that matter
The browser only discovers a font when it parses the CSS that asks for it, which is late. A
<link rel="preload"> in the <head> tells it to start
fetching immediately, in parallel with everything else. I preload exactly the faces the first
screen uses and no more — preload everything and you're just making your fonts fight your own
critical assets for bandwidth. Here that's three weights, and it's why the font is ready before
the text needs it.
fun fact: the font-display line
The nerdy bit, for anyone who enjoys this as much as I do. font-display decides
what the browser shows while the font loads, and every guide says use swap. I did —
and watched the fallback flip to JetBrains Mono on every load. It never dented my CLS, but the
flash looked awful. Because the pipeline above gets the font painting in about 39ms (PageSpeed
Insights, mobile, 4G), I went with optional instead: its ~100ms window is a
comfortable margin over 39ms, and if the font ever overran it the browser just keeps the
fallback — no swap, no shift. On a fast pipeline the choice is almost cosmetic, which is exactly
the point.
How I'd decide next time
None of the above is a law; it's what this site needed. A few things would change my answer:
- More fonts than this — the more families and weights a design leans on, the more subsetting and cutting weights matter, and the harder it gets to preload them all without choking the critical path. Past a point the honest fix is fewer fonts, not cleverer loading.
-
Real legacy support — I ship woff2 only because everything I support speaks it. For genuinely
old browsers I'd add a
wofffallback in the@font-facesrclist, so those bytes land only where they're needed. - A font I can't make fast — if a brand face had to always render and I couldn't get it small, subset, or preloaded (a big file, or one on a host I don't control), the honest move is to change the font, not to ship a slow one.
That's the whole strategy: make the font small and serve it early. Measure your own font's arrival time first — the number tells you which of these you're in.