CDN Configuration: Beyond Just Caching Static Assets

Philip Rehberger Apr 4, 2026 8 min read

Most teams configure their CDN to serve static files and call it done. A properly configured CDN does far more — handling security, routing, performance optimization, and origin protection.

CDN Configuration: Beyond Just Caching Static Assets

Most teams add a CDN to their application for one reason: serve static assets faster. This is correct but undersells what a CDN actually does. Modern CDNs are programmable, globally-distributed compute platforms capable of handling routing, security, transformation, and edge logic.

If you're only using your CDN to cache CSS and JavaScript files, you're using 20% of what you're paying for.

Understanding How CDNs Work

A CDN operates a network of Points of Presence (PoPs) globally. When a user makes a request:

User (Frankfurt) → CDN PoP (Frankfurt)
    → Is the response cached at this PoP?
        YES → Return cached response (latency: 5-20ms)
        NO  → Forward to origin, cache response, return to user

The key insight: CDN caching benefits only materialize when the cache hit rate is high. A 20% hit rate means 80% of requests still go to origin — you're adding latency (the CDN hop) for almost no benefit.

Understanding Cache Hit Ratio

Most CDN dashboards show you global hit ratio. The more useful metric is hit ratio per resource type:

Static assets (JS/CSS/images): should be 95-99%
API responses (public):         should be 70-90%
HTML pages:                     depends on caching strategy
User-specific content:          should be 0% (never cache)

If your static asset hit ratio is below 90%, investigate why. Common causes:

  • Cache keys include unnecessary query parameters
  • Cache-Control headers are too short or missing
  • Assets don't have content-hash filenames (requests for /app.js bypass cache if the CDN sees different hosts)

Cache Key Configuration

By default, CDNs use the full URL as the cache key. This works but leaves performance on the table.

Normalize Query Parameters

Malicious or innocent variance in query parameters creates cache misses:

/api/products?page=1&sort=price        → cached
/api/products?sort=price&page=1        → cache MISS (different key!)
/api/products?page=1&sort=price&fbclid=abc123  → cache MISS (analytics param)

Configure your CDN to ignore irrelevant parameters:

Cloudflare: Cache Rules → Cache Key → Query String
  → Ignore specific parameters: fbclid, utm_source, utm_medium, utm_campaign, gclid

AWS CloudFront: Cache Policy → Query Strings
  → Forward: None (for static)
  → Forward: Selected (whitelist: page, sort, per_page)

Vary Header Handling

The Vary header tells the CDN to store separate cache entries based on request headers. Use it correctly:

# For content that varies by Accept-Encoding (compression)
Vary: Accept-Encoding

# For content that varies by Accept (API versioning)
Vary: Accept, Accept-Encoding

# DANGER: Vary: Cookie caches a version per cookie value
# This creates exponential cache key explosion
# Don't do this for public content

CloudFront and Cloudflare both have controls to collapse variations and avoid the Vary explosion problem.

Origin Protection

The CDN should protect your origin from traffic it doesn't need to handle.

Origin Shield

AWS CloudFront's Origin Shield adds a centralized caching layer between regional edge locations and your origin. Instead of 300 edge locations independently fetching cache misses from your origin, they all go through one centralized location:

Without Origin Shield:
  300 edge locations × miss rate × traffic volume = many origin requests

With Origin Shield (us-east-1 shield):
  All misses → us-east-1 shield → origin (only if shield misses too)
  Shield hit rate: typically 60-80% of what would have been origin requests

This significantly reduces origin load, especially for content with moderate popularity.

IP Allowlisting at Origin

If your CDN is handling all traffic, your origin should only accept requests from CDN IPs:

# Cloudflare: only allow Cloudflare IPs to reach origin
# Cloudflare publishes its IP ranges at https://www.cloudflare.com/ips/

# Nginx: restrict access
allow 103.21.244.0/22;
allow 103.22.200.0/22;
allow 103.31.4.0/22;
allow 104.16.0.0/13;
# ... (all Cloudflare ranges)
deny all;

This prevents attackers from bypassing your CDN (and its WAF, DDoS protection, etc.) by hitting your origin IP directly.

Cloudflare Authenticated Origin Pulls

For stronger verification that requests come from Cloudflare:

# nginx.conf: require Cloudflare client certificate
ssl_client_certificate /etc/nginx/certs/cloudflare.crt;
ssl_verify_client on;

location / {
    # Cloudflare will present this certificate
    # Your origin rejects requests without it
    proxy_pass http://backend;
}

Cloudflare presents a TLS client certificate with every request to your origin. Your origin rejects any request that doesn't have this certificate — even if the attacker somehow finds your origin IP.

Dynamic Content Acceleration

CDNs accelerate dynamic (uncacheable) content through network optimizations:

Cloudflare Argo Smart Routing

Argo routes requests through Cloudflare's optimized backbone network instead of the public internet. The public internet is unpredictable — packets take indirect paths, experience congestion, and have variable latency. Cloudflare's backbone is optimized:

Public internet path (typical):
User → ISP → multiple BGP hops → ... → your origin
Latency: 180ms (highly variable)

Argo path:
User → nearest CF PoP → CF backbone (optimized routing) → your origin
Latency: 120ms (consistent)

Argo typically improves time-to-first-byte for dynamic content by 30-60%. This matters for authenticated APIs, checkout flows, and any content that can't be cached.

TCP Optimizations

Modern CDNs maintain persistent, pre-warmed TCP connections to origins. Establishing a TCP connection requires a handshake (3 round trips). For HTTPS, add TLS negotiation (2 more round trips). CDNs amortize this overhead:

Without CDN:
User → [TCP 3-way handshake] → [TLS negotiation] → [Request/Response] → Done
Total: 5-6 RTTs minimum from user to origin

With CDN:
User → [TCP to CDN PoP: 1-2 RTTs] → CDN has persistent connection to origin
Total: 1-2 RTTs from user's perspective

SSL/TLS at the CDN Layer

Full vs Full Strict SSL Mode

Flexible:    User→CDN (HTTPS)  CDN→Origin (HTTP)  ← INSECURE, never use
Full:        User→CDN (HTTPS)  CDN→Origin (HTTPS, any cert)  ← Acceptable
Full Strict: User→CDN (HTTPS)  CDN→Origin (HTTPS, valid cert) ← Best

Always use Full Strict. "Flexible" mode means your origin traffic is unencrypted — the CDN is just providing false security theater.

HTTP to HTTPS Redirect

Configure the redirect at the CDN level, not at your origin. This saves the round trip to your origin for every HTTP request:

Cloudflare: SSL/TLS → Edge Certificates → Always Use HTTPS: ON

CloudFront: Viewer Protocol Policy: Redirect HTTP to HTTPS

Performance Headers and Optimizations

HSTS Preloading

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

With HSTS, browsers remember to use HTTPS and don't even try HTTP. Submit your domain to the HSTS preload list and browsers will use HTTPS without ever making an HTTP request — eliminating even the redirect latency.

HTTP/2 and HTTP/3

Cloudflare: Speed → Optimization → Protocol Optimization → HTTP/3: Enable

HTTP/3 (QUIC) uses UDP instead of TCP, eliminating TCP handshake latency and head-of-line blocking. For users with high packet loss (mobile networks), HTTP/3 can dramatically improve performance. Browser support is excellent.

Image Optimization

Cloudflare Images and similar services transform images on-demand:

<!-- Request any size, CDN serves optimally sized image -->
<img src="/cdn-cgi/image/width=800,format=auto/images/hero.jpg">

<!-- Parameters:
  width: resize to width (height scales proportionally)
  format=auto: serve WebP to browsers that support it, JPEG otherwise
  quality: 1-100, default 85
  fit: scale-down, contain, cover, crop, pad
-->

This eliminates the need to generate multiple image sizes at build time — the CDN handles it.

Real-Time Log Analysis

CDN logs reveal cache behavior and traffic patterns:

# Cloudflare Logpush to S3, then analyze with Athena
# Key fields:
#   CacheStatus: hit, miss, expired, bypass, revalidated
#   EdgeResponseStatus: HTTP status code at CDN
#   OriginResponseStatus: HTTP status the CDN got from origin

-- Athena query: cache hit ratio by path prefix
SELECT
    split_part(clientrequestpath, '/', 2) AS path_prefix,
    COUNT(CASE WHEN cachestatus = 'hit' THEN 1 END) AS hits,
    COUNT(*) AS total,
    ROUND(100.0 * COUNT(CASE WHEN cachestatus = 'hit' THEN 1 END) / COUNT(*), 2) AS hit_rate
FROM cloudflare_logs
WHERE year='2026' AND month='03'
GROUP BY 1
ORDER BY total DESC
LIMIT 20;

Purging and Cache Invalidation

Purge by Tag

Tag-based purging is more flexible than URL-by-URL purging:

// Set cache tags on origin responses
return response()->json($product)
    ->header('Cache-Tag', "product-{$product->id} category-{$product->category_id}")
    ->header('Surrogate-Control', 'max-age=3600');

// When product is updated, purge by tag
$client->post(
    "https://api.cloudflare.com/client/v4/zones/{$zoneId}/purge_cache",
    [
        'json' => [
            'tags' => ["product-{$product->id}"]
        ]
    ]
);
// Only this product's cached responses are invalidated
// Other products are unaffected

Stale-While-Revalidate

Avoid cache purge races — serve stale content briefly while the cache updates:

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

After the 5-minute TTL expires, the CDN serves the stale response immediately while fetching a fresh version from origin in the background. Users see no latency spike during revalidation.

Configuration Checklist

For any production CDN setup, verify:

Security:
  ✓ Full Strict SSL mode enabled
  ✓ HTTP to HTTPS redirect at CDN level
  ✓ HSTS enabled (and preload list submitted)
  ✓ Origin restricted to CDN IPs only
  ✓ WAF rules enabled
  ✓ DDoS protection enabled
  ✓ Bot management configured

Performance:
  ✓ HTTP/2 and HTTP/3 enabled
  ✓ Brotli compression enabled
  ✓ Static assets: Cache-Control max-age=31536000, immutable
  ✓ Query parameter normalization configured
  ✓ Analytics parameters (utm_*, fbclid, gclid) in ignore list
  ✓ Cache hit ratio > 90% for static assets
  ✓ Cache hit ratio > 60% for public API responses

Operational:
  ✓ CDN logs streaming to S3 or similar
  ✓ Alerts on cache hit ratio drop
  ✓ Purge mechanism tested and documented
  ✓ Origin shield or equivalent enabled

A well-configured CDN is not a set-and-forget component — it's an active part of your architecture. Regular review of cache hit rates, log analysis for unusual traffic patterns, and incremental configuration improvements pay compounding dividends.

Building something that needs to scale? We help teams architect systems that grow with their business. scopeforged.com

Share this article

Related Articles

Reading Database EXPLAIN Plans: From Mystery to Mastery

Reading Database EXPLAIN Plans: From Mystery to Mastery

EXPLAIN plans tell you exactly what your database engine is doing to execute a query — whether it's using indexes, how many rows it's scanning, and what it costs. Learning to read them is essential for database performance work.

Apr 2, 2026

Need help with your project?

Let's discuss how we can help you build reliable software.