Font Converter

Font Caching Strategies

Implement browser caching best practices for fonts. Configure Cache-Control headers, immutable caching, CDN strategies, and service worker caching for optimal repeat visit performance.

Key Takeaways

  • • Set max-age=31536000 (1 year) for font files
  • • Use immutable directive to prevent revalidation
  • • Version fonts in filename for cache busting
  • • CDN caching provides global edge distribution

Why Font Caching Matters

Font files rarely change, making them ideal candidates for aggressive caching. Properly cached fonts load instantly on repeat visits, eliminating font-related performance issues entirely. Caching works best when combined with early discovery; the preload and preconnect resource hints guide covers how to start font downloads at the earliest possible point in the page load sequence.

Without Caching

  • • Font re-downloaded every visit
  • • 200-500ms added to each page load
  • • Wasted bandwidth for users
  • • Higher server costs

With Proper Caching

  • • Instant font load from cache
  • • Zero network requests
  • • Works offline (service worker)
  • • Reduced server load

Cache-Control Headers

The Cache-Control header tells browsers how to cache resources. For fonts, use aggressive caching with long expiration.

# Optimal font caching headers
Cache-Control: public, max-age=31536000, immutable

# Breakdown:
# public     - Can be cached by CDNs and browsers
# max-age    - Cache for 1 year (31536000 seconds)
# immutable  - Never revalidate, file won't change

Server Configuration Examples

Nginx

location ~* \.(woff2?|ttf|otf|eot)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    add_header Access-Control-Allow-Origin "*";
}

Apache (.htaccess)

<FilesMatch "\.(woff2?|ttf|otf|eot)$">
    Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>

Vercel (vercel.json)

{
  "headers": [
    {
      "source": "/fonts/(.*)",
      "headers": [
        { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
      ]
    }
  ]
}

Cache Busting with Versioned Filenames

When using long cache times, you need a way to force users to download updated fonts. Version the filename instead of using query strings. Serving fonts in WOFF2 format also means smaller files to cache and re-download when you do push updates, keeping the cost of cache busting low.

/* Good: Version in filename */
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom-v2.woff2') format('woff2');
}

/* Bad: Query string (ignored by some CDNs) */
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.woff2?v=2') format('woff2');
}

/* Also Good: Content hash */
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.a1b2c3d4.woff2') format('woff2');
}

CDN Caching

CDNs cache fonts at edge locations worldwide, reducing latency for global users. Most CDNs respect Cache-Control headers. If you are deciding between self-hosting and a third-party CDN, the self-hosted vs CDN font comparison breaks down the performance, privacy, and cost trade-offs of each approach.

Cloudflare

Automatically caches based on Cache-Control. Enable "Cache Everything" page rule for fonts if needed.

# Cloudflare Page Rule
URL: *example.com/fonts/*
Cache Level: Cache Everything
Edge Cache TTL: 1 month

AWS CloudFront

# CloudFront Cache Behavior
Path Pattern: /fonts/*
TTL Settings:
  Minimum: 86400
  Maximum: 31536000
  Default: 31536000

CORS Headers

When serving fonts from a CDN on a different domain, ensure Access-Control-Allow-Origin headers are set, or fonts will be blocked.

Service Worker Caching

Service workers provide the most reliable caching, enabling offline font access and instant loads. For a step-by-step walkthrough of configuring headers and cache rules on popular CDN providers, see the CDN font setup workflow guide.

// service-worker.js
const FONT_CACHE = 'fonts-v1';
const FONTS = [
  '/fonts/main.woff2',
  '/fonts/heading.woff2',
];

// Cache fonts on install
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(FONT_CACHE).then((cache) => cache.addAll(FONTS))
  );
});

// Serve fonts from cache, fallback to network
self.addEventListener('fetch', (event) => {
  if (event.request.url.includes('/fonts/')) {
    event.respondWith(
      caches.match(event.request).then((response) => {
        return response || fetch(event.request).then((fetchResponse) => {
          // Cache new fonts
          const clone = fetchResponse.clone();
          caches.open(FONT_CACHE).then((cache) => cache.put(event.request, clone));
          return fetchResponse;
        });
      })
    );
  }
});

Verifying Cache Behavior

Chrome DevTools

Network tab → Font request → Headers tab. Look for:

  • Cache-Control: public, max-age=31536000, immutable
  • Size column shows "(disk cache)" on repeat visits
  • Time column shows 0ms for cached fonts

curl Command

curl -I https://example.com/fonts/main.woff2

# Look for:
# Cache-Control: public, max-age=31536000, immutable
# Access-Control-Allow-Origin: *

Additional Resources

Optimize Your Fonts

Smaller fonts cache faster and use less storage. Convert and subset your fonts.

Subset Fonts Now
Sarah Mitchell

Written & Verified by

Sarah Mitchell

Typography expert specializing in font design, web typography, and accessibility

Font Caching FAQs

Common questions about browser caching and CDN strategies