Skip to content
Performance

Caching Strategies Guide

Implement effective caching with HTTP headers, service workers, and CDN configuration.

stellae.design

8 min read

Introduction

Caching is the most effective performance optimization available. A cached resource loads instantly — zero network requests, zero server processing, zero latency.

Web caching operates at multiple layers: browser cache, service workers, CDN edge cache, and server-side cache. Getting them right means near-instant repeat visits.

This guide covers caching at every layer with practical configurations you can apply immediately.


Key Concepts

HTTP Cache Headers

plain
# Immutable assets (hashed filenames)
Cache-Control: public, max-age=31536000, immutable

# HTML pages (always revalidate)
Cache-Control: no-cache

# API responses
Cache-Control: public, max-age=60, stale-while-revalidate=300

# Never cache
Cache-Control: no-store

Stale-While-Revalidate

SWR serves cached content immediately while fetching a fresh version in the background. Users get instant responses while the cache stays fresh.


Practical Examples

1. Next.js Caching Headers

javascript
module.exports = {
  async headers() {
    return [
      {
        source: '/:all*(svg|jpg|png|webp|avif)',
        headers: [{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }],
      },
      {
        source: '/api/:path*',
        headers: [{ key: 'Cache-Control', value: 'public, s-maxage=60, stale-while-revalidate=300' }],
      },
    ];
  },
};

2. Service Worker Cache Strategy

javascript
self.addEventListener('fetch', (event) => {
  const { request } = event;
  if (request.url.includes('/api/')) {
    event.respondWith(
      fetch(request).then(resp => {
        caches.open('v1').then(c => c.put(request, resp.clone()));
        return resp;
      }).catch(() => caches.match(request))
    );
  } else {
    event.respondWith(caches.match(request).then(c => c || fetch(request)));
  }
});

3. Nginx Configuration

plain
location ~* \.(js|css|png|jpg|svg|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}
location ~* \.html$ {
    add_header Cache-Control "no-cache";
}

Best Practices

  • ✅ Use content hashes in filenames for long-term caching
  • ✅ Set immutable on hashed assets
  • ✅ Use stale-while-revalidate for API data
  • ✅ Always revalidate HTML with no-cache
  • ✅ Version your service worker caches
  • ❌ Don't set long max-age on URLs that can change
  • ❌ Don't confuse no-cache with no-store

Common Pitfalls

  • 🚫 Caching HTML with max-age — users get stale pages
  • 🚫 Forgetting s-maxage for CDNs
  • 🚫 Not busting cache on deployment
  • 🚫 Over-caching user-specific data — use private, not public

Performanceperformance

Was this article helpful?