|$ curl https://forge-ai.dev/api/markdown?path=docs/performance/cdn
$cat docs/cdn-strategies.md
updated Recently·28 min read·published
CDN Strategies
Introduction
A Content Delivery Network (CDN) caches and serves your static assets from edge servers closest to your users. This dramatically reduces latency (TTFB), offloads your origin server, and improves reliability through geographic distribution.
CDN Providers
| Provider | Free Tier | Edge Locations | Best For |
|---|---|---|---|
| Cloudflare | Unlimited | 300+ | All-in-one (CDN + security) |
| AWS CloudFront | 1TB/month | 600+ | AWS ecosystem |
| Fastly | Free trial | 90+ | Real-time purging, edge compute |
| Vercel Edge | 100GB | 90+ | Next.js / frontend |
Edge Caching Configuration
edge-caching.ts
TypeScript
| 1 | // Next.js — Cache-Control headers for CDN |
| 2 | // app/api/products/route.ts |
| 3 | import { NextResponse } from "next/server"; |
| 4 | |
| 5 | export async function GET() { |
| 6 | const products = await fetchProducts(); |
| 7 | |
| 8 | const response = NextResponse.json(products); |
| 9 | |
| 10 | // Cache at CDN edge for 1 hour, stale-while-revalidate for 24h |
| 11 | response.headers.set( |
| 12 | "Cache-Control", |
| 13 | "public, s-maxage=3600, stale-while-revalidate=86400" |
| 14 | ); |
| 15 | |
| 16 | return response; |
| 17 | } |
| 18 | |
| 19 | // Static assets — immutable caching |
| 20 | // next.config.js: |
| 21 | // async headers() { |
| 22 | // return [{ |
| 23 | // source: "/_next/static/:path*", |
| 24 | // headers: [{ key: "Cache-Control", value: "public, max-age=31536000, immutable" }], |
| 25 | // }]; |
| 26 | // } |
| 27 | |
| 28 | // CloudFront configuration (AWS CDK) |
| 29 | import * as cloudfront from "aws-cdk-lib/aws-cloudfront"; |
| 30 | |
| 31 | const distribution = new cloudfront.Distribution(this, "Distribution", { |
| 32 | defaultBehavior: { |
| 33 | origin: new origins.S3Origin(bucket), |
| 34 | cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED, |
| 35 | viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS, |
| 36 | }, |
| 37 | }); |
Cache Invalidation
cache-invalidation.ts
TypeScript
| 1 | // CloudFront invalidation |
| 2 | import { CloudFrontClient, CreateInvalidationCommand } from "@aws-sdk/client-cloudfront"; |
| 3 | |
| 4 | const client = new CloudFrontClient({ region: "us-east-1" }); |
| 5 | |
| 6 | // Invalidate specific paths |
| 7 | await client.send(new CreateInvalidationCommand({ |
| 8 | DistributionId: "E1234567890", |
| 9 | InvalidationBatch: { |
| 10 | CallerReference: Date.now().toString(), |
| 11 | Paths: { |
| 12 | Quantity: 3, |
| 13 | Items: ["/index.html", "/products/*", "/images/logo.*"], |
| 14 | }, |
| 15 | }, |
| 16 | })); |
| 17 | |
| 18 | // Cloudflare: instant purge (no propagation delay) |
| 19 | // API call or dashboard → Purge Everything / Purge by URL |
| 20 | |
| 21 | // Versioned filenames avoid invalidation entirely |
| 22 | // bundle.js → bundle.a1b2c3.js (content hash in filename) |
| 23 | // Set long Cache-Control headers, the hash changes on deploy |
CDN Image Optimization
image-optimization.ts
TypeScript
| 1 | // Cloudflare Image Resizing |
| 2 | // https://example.com/cdn-cgi/image/width=800,format=auto/path/to/image.jpg |
| 3 | |
| 4 | // Next.js Image component (uses built-in optimization) |
| 5 | import Image from "next/image"; |
| 6 | |
| 7 | <Image |
| 8 | src="/photos/hero.jpg" |
| 9 | width={1200} |
| 10 | height={600} |
| 11 | alt="Hero image" |
| 12 | priority // Preload for LCP |
| 13 | sizes="(max-width: 768px) 100vw, 50vw" |
| 14 | /> |
| 15 | |
| 16 | // Cloudinary URL transformations |
| 17 | // https://res.cloudinary.com/demo/image/upload/w_800,f_auto,q_auto/sample.jpg |
| 18 | // w_800: width 800px |
| 19 | // f_auto: auto format (WebP/AVIF) |
| 20 | // q_auto: auto quality |
| 21 | |
| 22 | // CloudFront + Lambda@Edge for on-the-fly optimization |
| 23 | // Lambda@Edge function transforms images based on query params |
| 24 | // ?w=800&f=webp → resizes and converts before caching |
ℹ
info
Use format=auto (Cloudinary) or Accept header-based format negotiation to serve WebP/AVIF to browsers that support them, falling back to JPEG/PNG.
Font Serving
fonts.css
CSS
| 1 | /* Self-host fonts via CDN for best performance */ |
| 2 | @font-face { |
| 3 | font-family: 'Inter'; |
| 4 | src: url('https://cdn.example.com/fonts/inter-var.woff2') format('woff2'); |
| 5 | font-display: swap; |
| 6 | font-weight: 100 900; |
| 7 | } |
| 8 | |
| 9 | /* Preload critical fonts */ |
| 10 | /* <link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin /> */ |
| 11 | |
| 12 | /* Use font-display: swap to avoid FOIT (Flash of Invisible Text) */ |
| 13 | /* swap: show fallback immediately, swap when loaded */ |
| 14 | /* optional: don't show fallback, use only if loaded quickly */ |
| 15 | /* fallback: brief FOIT, then fallback */ |
$Blueprint — Engineering Documentation·Section ID: PERF-CDN-01·Revision: 1.0