Technote

Performance optimization Practical

Series Korean web typography Part 4 of 8

Self-hosting webfonts: what you gain by dropping the CDN

The biggest advantage of a public font CDN — a cache already warmed by another site — disappeared when browsers partitioned their caches. What remains is a question of round trips and control.

The easiest way to add a webfont is to paste one link from a public CDN, and for a long time that was a perfectly sensible choice. One of the arguments holding it up, however, has disappeared on the browser side.

The shared cache is already gone

The strongest case for a public font CDN used to be: “your visitor has already downloaded this font on some other site, so it renders instantly here.” That no longer holds. Major browsers now partition the HTTP cache by top-level site as an anti-tracking measure, which means the identical file at the identical URL is fetched again on a different site.

So a public CDN today cannot promise you a warm cache. If the file has to be fetched either way, the question becomes a straightforward comparison of cost.

It is not one round trip

Fetching a font from another origin requires a DNS lookup, a TCP connection and a TLS handshake before anything else happens. Your own server already has a connection; the new domain does not.

Worse, most CDN links are two-stage: a stylesheet is fetched first, and the font file is only requested from inside it. The font your first screen needs does not even begin downloading until two round trips have completed.

The CDN path — self-hosting removes the middle box

preconnect can start the handshake earlier, but that reduces the cost rather than removing it. Serving the font from your own origin removes the step entirely.

Control, and your visitors’ details

Two more considerations sit beside speed.

Your visitor’s IP address goes to a third party. A font request is an HTTP request like any other, so connection details land on that server. In Europe this has been treated as a genuine legal question, so for a business that takes data handling seriously, self-hosting is simply easier to explain.

The version stays in your hands. When a remote service updates a font file, glyph widths can shift very slightly, and the line breaks and layout you tuned shift with them. Self-hosted, nothing happens until you swap the file yourself — the state in which what you tested is what you shipped.

Same typeface — where it comes from decides first paint and control

How to move

The work itself is simple. You need woff2 only — every current browser supports it, so there is no reason to ship woff, ttf and eot alongside. Keeping the files inside the theme, at something like assets/fonts/ in a child theme, makes deployment and version control easier.

@font-face {
  font-family: 'Pretendard Variable';
  src: url('../fonts/PretendardVariable.woff2') format('woff2');
  font-weight: 100 900;        /* the variable weight axis range */
  font-style: normal;
  font-display: swap;
}

body { font-family: 'Pretendard Variable', system-ui, sans-serif; }

On the server, give font files a long cache lifetime. If the filename carries a version or a hash, you can use Cache-Control: public, max-age=31536000, immutable with confidence, because a change in content is also a change in name.

Finally, check that nothing is re-adding the fonts behind your back. If a remote font domain still appears in the network panel after you have moved, a theme option or another plugin is usually loading its own copy. Skip that check and you end up with the worst arrangement of all: downloading both sets.

Asset loading and caching policy in general live in the Performance archive, and sorting out fonts, caching and server configuration in one pass is part of our optimization program.

Next part

Once the files are yours, their size becomes impossible to ignore — a Korean font is in another weight class entirely. The next part is about splitting that file so browsers fetch only the pieces they need.

More on this topic

All technotes

Performance optimization Practical

Who pays for the milliseconds a tag adds?

A tracking script does not stop at downloading. While it is parsed and executed the main thread is busy, and a busy page ignores fingers. That cost is…

Marketers 5 min read

Performance optimization Practical

The object cache: what Redis actually removes

Repeated identical lookups disappear. One slow query does not. Miss that distinction and you will wire up Redis and then ask why nothing got faster.

Developers 7 min read

Performance optimization Practical

This is how a landing page gets heavy

Nobody decides to make a landing page heavy. It accumulates: one addition per campaign, and nothing ever removed when the campaign ends.

Marketers 6 min read

₩270,000 · Join the program