Back to Blog
CDNPerformanceCachingInfrastructure

CDN Configuration: Optimizing Content Delivery

Configure CDNs for optimal performance. Learn caching strategies, edge functions, and global content distribution.

B
Bootspring Team
Engineering
February 26, 2026
2 min read

CDNs serve content from locations close to users. This guide covers configuring CDNs for optimal performance.

How CDNs Work#

User (Tokyo) ─────┐ │ User (NYC) ───────┼──> Edge Server ──> Origin Server │ (Cached) User (London) ────┘

Cloudflare Configuration#

Cache Rules#

1// cloudflare worker for custom caching 2export default { 3 async fetch(request) { 4 const url = new URL(request.url); 5 6 // Static assets - long cache 7 if (url.pathname.match(/\.(js|css|png|jpg|webp|woff2)$/)) { 8 const response = await fetch(request); 9 const newResponse = new Response(response.body, response); 10 newResponse.headers.set('Cache-Control', 'public, max-age=31536000, immutable'); 11 return newResponse; 12 } 13 14 // API responses - short cache 15 if (url.pathname.startsWith('/api/')) { 16 const response = await fetch(request); 17 const newResponse = new Response(response.body, response); 18 newResponse.headers.set('Cache-Control', 's-maxage=60, stale-while-revalidate=300'); 19 return newResponse; 20 } 21 22 return fetch(request); 23 }, 24};

Page Rules#

1# Static assets 2Pattern: *.example.com/*.(css|js|png|jpg|webp|woff2) 3Cache Level: Cache Everything 4Edge Cache TTL: 1 month 5Browser Cache TTL: 1 year 6 7# HTML pages 8Pattern: *.example.com/*.html 9Cache Level: Cache Everything 10Edge Cache TTL: 1 hour 11 12# API endpoints 13Pattern: api.example.com/* 14Cache Level: Bypass

Cache Headers#

1// Next.js API route caching 2export async function GET() { 3 const data = await fetchData(); 4 5 return Response.json(data, { 6 headers: { 7 // Cache at CDN for 1 hour 8 'CDN-Cache-Control': 'max-age=3600', 9 // Cache in browser for 1 minute 10 'Cache-Control': 'public, max-age=60, stale-while-revalidate=300', 11 // Vary by accept-encoding 12 'Vary': 'Accept-Encoding', 13 }, 14 }); 15}

Cache Invalidation#

1// Cloudflare purge API 2async function purgeCache(urls: string[]) { 3 await fetch(`https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache`, { 4 method: 'POST', 5 headers: { 6 'Authorization': `Bearer ${CF_TOKEN}`, 7 'Content-Type': 'application/json', 8 }, 9 body: JSON.stringify({ files: urls }), 10 }); 11} 12 13// Purge by tag 14async function purgeByTag(tags: string[]) { 15 await fetch(`https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/purge_cache`, { 16 method: 'POST', 17 headers: { 18 'Authorization': `Bearer ${CF_TOKEN}`, 19 'Content-Type': 'application/json', 20 }, 21 body: JSON.stringify({ tags }), 22 }); 23}

Cache Tags#

1// Add cache tags for granular purging 2export async function GET() { 3 const product = await getProduct(id); 4 5 return Response.json(product, { 6 headers: { 7 'Cache-Tag': `product-${id}, category-${product.categoryId}`, 8 'Cache-Control': 's-maxage=3600', 9 }, 10 }); 11}

Performance Tips#

  1. Use immutable for versioned assets: max-age=31536000, immutable
  2. Enable Brotli compression: Smaller file sizes
  3. Use stale-while-revalidate: Better perceived performance
  4. Cache API responses: Even short TTLs help
  5. Monitor cache hit ratio: Target >90% for static content

Configure appropriate TTLs, implement cache invalidation, and monitor cache performance.

Share this article

Help spread the word about Bootspring