Content Delivery Network Guide: CDN Architecture, Edge Caching, and Cloudflare Workers
Understand CDN architecture and edge caching — how CDNs work, cache-control headers, cache invalidation, Cloudflare Workers for edge logic, and when CDNs don't
Content Delivery Network Guide: CDN Architecture, Edge Caching, and Cloudflare Workers
A CDN (Content Delivery Network) is a geographically distributed network of cache servers that serve your content from locations close to users. A request from Tokyo that would normally travel to your US origin server — 150–200ms round trip — instead hits a CDN edge node in Tokyo at 5–10ms.
But CDNs are commonly misunderstood: they cache more than static files, they require careful configuration to work correctly, and they can cause bugs (stale content, cache poisoning) if set up wrong.
How CDNs Work
User (Tokyo) → CDN Edge (Tokyo) → Origin Server (US East)
First request:
User → Tokyo edge → MISS → Origin (150ms) → Cache response → User
Subsequent requests (while cached):
User → Tokyo edge → HIT → User (5ms)
The CDN edge node caches the response. Subsequent requests for the same URL are served from cache without hitting your origin.
What gets cached:
- Static assets: JS, CSS, images, fonts (obvious)
- HTML pages: static site pages, pre-rendered pages
- API responses: if you set the right headers
- Video and audio files
- WebAssembly modules
What doesn't get cached (by default):
- Requests with cookies (treated as personalized)
- POST/PUT/DELETE requests
- Responses with
Cache-Control: privateorno-store - Responses with
Set-Cookieheaders
Cache-Control Headers
Your origin server controls CDN behavior via Cache-Control response headers.
// Fastify route with explicit cache directives
// Static assets — long-lived, immutable (fingerprinted filenames)
app.get('/assets/*', async (request, reply) => {
reply.header('Cache-Control', 'public, max-age=31536000, immutable');
// max-age=31536000: cache for 1 year
// immutable: browser won't revalidate even on refresh
});
// API data — short-lived, serve stale while revalidating
app.get('/api/posts', async (request, reply) => {
reply.header('Cache-Control', 'public, max-age=60, stale-while-revalidate=300');
// max-age=60: serve fresh for 60s
// stale-while-revalidate=300: serve stale while fetching new data (up to 5 min)
});
// User-specific data — never cache
app.get('/api/user/profile', async (request, reply) => {
reply.header('Cache-Control', 'private, no-store');
});
// Rarely changing public data — cache for 1 hour
app.get('/api/pricing', async (request, reply) => {
reply.header('Cache-Control', 'public, max-age=3600, s-maxage=86400');
// max-age: browser cache TTL
// s-maxage: CDN cache TTL (overrides max-age for shared caches)
});
Cache-Control directives reference:
| Directive | Effect |
|---|---|
public | Any cache (CDN, browser) can store |
private | Browser only — CDN must not cache |
no-store | Don't cache anywhere |
no-cache | Cache, but always revalidate before serving |
max-age=N | Cache for N seconds (browser + CDN) |
s-maxage=N | CDN cache TTL (overrides max-age for CDNs) |
stale-while-revalidate=N | Serve stale while fetching fresh |
stale-if-error=N | Serve stale if origin errors |
immutable | Don't revalidate (use only with fingerprinted assets) |
☁️ Is Your Cloud Costing Too Much?
Most teams overspend 30–40% on cloud — wrong instance types, no reserved pricing, bloated storage. We audit, right-size, and automate your infrastructure.
- AWS, GCP, Azure certified engineers
- Infrastructure as Code (Terraform, CDK)
- Docker, Kubernetes, GitHub Actions CI/CD
- Typical audit recovers $500–$3,000/month in savings
Cloudflare Configuration
Cloudflare is the most widely used CDN/edge platform. Key configuration:
Page Rules (or Ruleset) for cache behavior:
Rule: Cache static assets aggressively
URL: *yourdomain.com/assets/*
Cache Level: Cache Everything
Edge Cache TTL: 1 year
Rule: Bypass cache for API routes
URL: *yourdomain.com/api/*
Cache Level: Bypass
(unless your API explicitly sets Cache-Control: public)
Rule: Cache HTML pages
URL: *yourdomain.com/blog/*
Cache Level: Cache Everything
Edge Cache TTL: 1 hour
Browser Cache TTL: 30 minutes
Cloudflare Terraform config:
# terraform/cloudflare.tf
resource "cloudflare_ruleset" "cache_rules" {
zone_id = var.cloudflare_zone_id
name = "Cache rules"
kind = "zone"
phase = "http_request_cache_settings"
rules {
action = "set_cache_settings"
action_parameters {
cache = true
edge_ttl {
mode = "override_origin"
default = 86400 # 24 hours
}
browser_ttl {
mode = "override_origin"
default = 3600 # 1 hour
}
}
expression = "(http.request.uri.path matches \"^/blog/\")"
description = "Cache blog pages"
enabled = true
}
rules {
action = "set_cache_settings"
action_parameters {
cache = false # Bypass CDN cache for API
}
expression = "(http.request.uri.path matches \"^/api/user\")"
description = "Bypass cache for user-specific API routes"
enabled = true
}
}
Cache Invalidation
The classic engineering problem: "There are only two hard things in Computer Science: cache invalidation and naming things."
Strategies:
1. URL fingerprinting (best for assets) Include a content hash in the filename. When the file changes, the URL changes, the old URL expires naturally.
/assets/main.abc123de.js ← hash changes with file content
Next.js, Vite, and Webpack do this automatically.
2. Versioned paths
/api/v1/pricing ← Old version
/api/v2/pricing ← New version serves updated data
3. Explicit purge via API
// Purge specific URLs after content update
async function purgeCloudflareCache(urls: string[]) {
const response = await fetch(
`https://api.cloudflare.com/client/v4/zones/${process.env.CF_ZONE_ID}/purge_cache`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CF_API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ files: urls }),
}
);
if (!response.ok) {
throw new Error(`Cache purge failed: ${await response.text()}`);
}
return response.json();
}
// Call after publishing a blog post
await purgeCloudflareCache([
'https://yourdomain.com/blog/',
'https://yourdomain.com/blog/new-post-slug/',
'https://yourdomain.com/sitemap.xml',
]);
4. Short TTL + stale-while-revalidate For content that changes frequently, use a short TTL so staleness is bounded:
Cache-Control: public, max-age=60, stale-while-revalidate=300
The CDN serves stale content instantly while fetching fresh — users see fast responses, content updates within 5 minutes.
⚙️ DevOps Done Right — Zero Downtime, Full Automation
Ship faster without breaking things. We build CI/CD pipelines, monitoring stacks, and auto-scaling infrastructure that your team can actually maintain.
- Staging + production environments with feature flags
- Automated security scanning in the pipeline
- Uptime monitoring + alerting + runbook automation
- On-call support handover docs included
Cloudflare Workers: Edge Logic
Cloudflare Workers let you run JavaScript at the CDN edge — before requests hit your origin. Use cases: A/B testing, authentication, request modification, geolocation routing.
// workers/ab-test.ts — A/B test routing at the edge
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// Only A/B test the pricing page
if (url.pathname !== '/pricing') {
return fetch(request);
}
// Assign variant based on cookie or random
const cookie = request.headers.get('Cookie') || '';
const variantMatch = cookie.match(/ab_pricing=([ab])/);
let variant: 'a' | 'b';
if (variantMatch) {
variant = variantMatch[1] as 'a' | 'b';
} else {
variant = Math.random() < 0.5 ? 'a' : 'b';
}
// Route to different origin paths
const targetUrl = variant === 'b'
? new URL('/pricing-v2', url.origin).toString()
: request.url;
const response = await fetch(targetUrl, request);
// Set variant cookie
const newResponse = new Response(response.body, response);
if (!variantMatch) {
newResponse.headers.append('Set-Cookie',
`ab_pricing=${variant}; Path=/; Max-Age=86400; SameSite=Lax`
);
}
return newResponse;
},
};
// workers/geo-redirect.ts — serve region-specific content
export default {
async fetch(request: Request): Promise<Response> {
const country = request.headers.get('CF-IPCountry') || 'US';
const url = new URL(request.url);
// Redirect EU users to GDPR-compliant endpoint
const euCountries = ['DE', 'FR', 'NL', 'IT', 'ES', 'PL', 'SE', 'NO'];
if (euCountries.includes(country) && !url.hostname.startsWith('eu.')) {
return Response.redirect(
`https://eu.${url.hostname}${url.pathname}${url.search}`,
302
);
}
return fetch(request);
},
};
CDN Provider Comparison (2026)
| Provider | Free Tier | Pricing Model | Edge Locations | Best For |
|---|---|---|---|---|
| Cloudflare | Unlimited bandwidth | $0–$200/mo fixed | 320+ | Most use cases |
| AWS CloudFront | 1TB/mo free | $0.0085–0.12/GB | 450+ | AWS-native apps |
| Fastly | None | $0.12/GB | 70+ | Enterprise, VCL control |
| Vercel Edge | Included | Part of Vercel plan | Varies | Next.js apps |
| Bunny CDN | None | $0.005–0.06/GB | 120+ | High-volume, low cost |
For most startups: Cloudflare (free tier covers most traffic, Workers included, DDoS protection included). For AWS-native deployments: CloudFront + Lambda@Edge.
When CDNs Don't Help
CDNs don't fix slow APIs, dynamic content, or small user bases:
- Uncacheable dynamic content: If every response is unique (personalized dashboards), a CDN provides only DDoS protection, not caching benefit
- Small user base in one region: If all users are in one city, latency reduction is minimal — focus on origin performance
- Slow database queries: CDN caches at the HTTP layer; a 3-second database query is still 3 seconds on cache miss
- High cache invalidation rate: If content changes every minute and TTL is 60 seconds, cache hit rate is low
Working With Viprasol
We configure CDN infrastructure as part of cloud deployments — Cloudflare setup, cache-control header strategy, Workers for edge logic, and performance audits that identify what to cache vs. optimize at the origin.
→ Talk to our cloud team about CDN and performance optimization.
See Also
- Web Performance Optimization — Core Web Vitals and beyond
- Caching Strategies — application-level caching patterns
- Next.js Performance — CDN integration with Next.js
- Infrastructure as Code — Terraform for CDN configuration
- Cloud Solutions — CDN and cloud infrastructure services
About the Author
Viprasol Tech Team
Custom Software Development Specialists
The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 100+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement. Based in India, serving clients globally.
Need DevOps & Cloud Expertise?
Scale your infrastructure with confidence. AWS, GCP, Azure certified team.
Free consultation • No commitment • Response within 24 hours
Making sense of your data at scale?
Viprasol builds end-to-end big data analytics solutions — ETL pipelines, data warehouses on Snowflake or BigQuery, and self-service BI dashboards. One reliable source of truth for your entire organisation.