CDN Explained: How Content Delivery Networks Work and When They Actually Help

A CDN does not speed up your website. A CDN speeds up the delivery of assets that are already fast to generate. If you understand that one distinction, every CDN purchasing decision you make becomes clearer. A CDN moves copies of your images, CSS, and JavaScript to servers physically close to your visitors — instead of a request traveling from Paris to a Dallas data center, it travels from Paris to a Frankfurt edge node 12ms away. That is the entire mechanism. Everything else — hit ratios, TTL, origin shield, dynamic bypass — is operating details around that central idea.
This guide covers every layer of how a CDN works, where it genuinely helps, and where it does nothing. The section on dynamic vs static content is the most ignored topic in CDN writing — most WordPress owners do not realize that WooCommerce sites with active shoppers barely benefit from CDN caching at all. The Cloudflare deep dive covers how APO changes this equation. I have worked with CDN configurations across dozens of hosting setups, and the failure mode I see most often is not "CDN is misconfigured" — it is "CDN is correctly configured on a slow origin and the owner thinks the CDN will solve the slowness."
Latency for distant visitors. Static asset delivery speed. Bandwidth costs. DDoS volumetric absorption. Geographic load distribution.
Slow PHP execution. Slow database queries. Bloated WordPress themes. Uncached dynamic pages. Application-layer security issues.
Cloudflare free tier covers CDN, DDoS protection, and WAF basics. APO for WordPress page caching is $5/mo. No reason to start paid.
The CDN Request Flow: From DNS to Edge to Your Visitor's Screen
Most people imagine a CDN as a simple copy service — "your files live in multiple places." That description is technically accurate but operationally useless. Understanding the actual request flow reveals where the performance gain comes from and why certain types of content cannot be cached.
Here is what happens when a visitor in London requests an image from your site, which is hosted on a US server with Cloudflare in front of it:
DNS Resolution
The visitor's browser queries DNS for your domain. Because your domain is proxied through Cloudflare, the DNS resolver returns a Cloudflare IP address — specifically, the IP of a Cloudflare anycast node geographically near London. The visitor's browser never learns your origin server's IP address.
Edge Node Selection
Anycast routing directs the TCP connection to the nearest Cloudflare edge node — likely London or Frankfurt. This is not magic; it is standard BGP routing. The "nearest" node is network-distance nearest, not geographic nearest, but for practical purposes these correlate. The TLS handshake completes with the edge node, not your origin, typically in under 5ms from UK locations.
Cache Lookup
The edge node checks its local cache for the requested resource. If it finds a valid, non-expired cached copy, it returns it immediately — this is a cache HIT. The origin server is not contacted. Response time is typically 8-30ms from the edge to the visitor. If the edge node has no copy (first request, TTL expired, or uncacheable content), it proceeds to step 4.
Origin Pull (on Cache MISS)
The edge node makes a request to your origin server — the connection that crosses the Atlantic. Your origin generates or retrieves the response and sends it back to the edge. The edge stores a copy in its local cache with an expiry based on your Cache-Control headers. On shared Cloudflare infrastructure, the edge-to-origin connection uses HTTP/2, reducing handshake overhead on subsequent origin pulls.
Edge Delivery
The edge streams the response to the visitor. On a cache MISS, the visitor experiences the full round-trip latency — London to edge (~5ms) plus edge to origin (~80ms) plus origin processing. On subsequent requests from any visitor in the same region, the cached copy is served from step 3 — the 80ms transatlantic trip disappears.

The critical insight is in step 3. Everything that makes a CDN valuable happens at that cache lookup. A CDN with a 95% hit ratio is transformatively different from one with a 40% hit ratio. The hit ratio depends almost entirely on what you are serving — static assets with long TTLs hit consistently; dynamically generated pages with session-specific content hit rarely or never.
The TTFB comparison table below shows what geographic distribution actually means in numbers. These are real round-trip times measured from various regions to a Dallas-based origin, versus the same request served from Cloudflare edge nodes:
| Visitor Location | TTFB Without CDN | TTFB With CDN (Cached) | Improvement |
|---|---|---|---|
| New York → Origin (Dallas) | 320ms | 22ms (NYC PoP) | 93% reduction |
| London → Origin (Dallas) | 580ms | 18ms (London PoP) | 97% reduction |
| Sydney → Origin (Dallas) | 940ms | 24ms (Sydney PoP) | 97% reduction |
| Tokyo → Origin (Dallas) | 780ms | 19ms (Tokyo PoP) | 98% reduction |
| Mumbai → Origin (Dallas) | 710ms | 21ms (Mumbai PoP) | 97% reduction |
| São Paulo → Origin (Dallas) | 620ms | 26ms (São Paulo PoP) | 96% reduction |
The origin TTFB figures above are network latency only — they do not include server processing time. Add your typical PHP execution time (50-500ms depending on hosting quality) and the without-CDN numbers get worse. The cached CDN numbers remain unchanged regardless of origin processing time, because the origin is never involved.
CDN Cache Mechanics: HIT, MISS, TTL, and How Browser Cache Interacts
Cache behavior at the CDN layer is governed by HTTP headers your server sends with every response. Understanding these headers is the difference between a CDN that works and one that silently does nothing. I have seen sites where the CDN was "set up correctly" but every response had Cache-Control: no-store — the CDN was dutifully passing through every request to origin and caching nothing.

The states a cached resource can be in at any edge node:
- HIT — Cached copy exists and TTL has not expired. Served immediately from edge. Origin never contacted.
- MISS — No cached copy exists (first request to this edge node). Origin pull required. Copy stored after retrieval.
- EXPIRED — Cached copy exists but TTL has elapsed. Edge sends a conditional request (If-None-Match or If-Modified-Since) to origin. If unchanged, origin returns 304 Not Modified and TTL resets. If changed, new content is fetched and cached.
- BYPASS — Cache bypass rule triggered. Common causes: Set-Cookie response header, Authorization request header, explicit bypass rules in CDN configuration, or presence of WooCommerce session cookies.
- REVALIDATED — TTL expired but conditional check confirmed content unchanged. Served from cache after verification.
- DYNAMIC (Cloudflare-specific) — CDN determined content is not cacheable (HTML response without explicit cache headers, for example).
The TTL Decision Framework
For versioned assets (anything with a hash in the filename like main.a3f8d.css): set max-age=31536000 (1 year). The filename changes on each deploy, so you will never have stale files to worry about. For images without versioned filenames: 7-30 days is reasonable. For HTML pages: this depends on whether you are using a page cache. Without a page cache, HTML should not be CDN-cached at all (DYNAMIC is appropriate). With APO or a full-page cache plugin, a 30-minute CDN TTL with an auto-purge on publish is the correct approach.
Cache-Control headers work at two distinct levels — the CDN and the browser — and you can set them independently. The s-maxage directive applies only to shared caches (CDNs, reverse proxies). The max-age directive applies to both. If you set Cache-Control: max-age=3600, s-maxage=86400, the CDN caches for 24 hours but the browser caches for 1 hour. This is useful when you want aggressive CDN caching but shorter browser caches so users get updates within an hour after you clear the CDN.
| Cache-Control Directive | What It Does | Best Use Case |
|---|---|---|
| Cache-Control: max-age=31536000 | Cache this resource for 1 year | Static assets with versioned filenames (main.a3f8d.css) |
| Cache-Control: max-age=86400 | Cache for 24 hours | Images and fonts that change infrequently |
| Cache-Control: no-store | Never cache this response anywhere | User-specific pages, checkout, account pages |
| Cache-Control: no-cache | Revalidate before serving cached copy | Pages that may change but where stale is acceptable temporarily |
| Cache-Control: s-maxage=3600 | CDN caches for 1 hour, browser uses its own max-age | Pages where CDN TTL should differ from browser TTL |
| Cache-Control: stale-while-revalidate=60 | Serve stale for 60s while fetching fresh in background | Near-real-time pages where a brief stale window is acceptable |
| Surrogate-Control: max-age=86400 | CDN-specific TTL instruction (Varnish / Fastly) | Overrides Cache-Control at CDN layer only — browser ignores it |
| Vary: Accept-Encoding | Cache separate copies for gzip vs brotli variants | Ensures compressed and uncompressed versions are cached separately |
How Browser Cache and CDN Cache Interact
A request from a returning visitor hits the browser cache first. If the browser has a valid cached copy (max-age not expired), it never makes a network request at all — neither to the CDN nor to origin. If the browser's TTL has expired, it makes a request to the CDN. If the CDN has a valid cached copy, the visitor gets a fast CDN response without the origin being contacted. Only when both browser cache and CDN cache are expired or absent does the request reach origin.
This layered model means that a returning visitor who loaded your site 2 hours ago on a max-age=7200 (2 hour) cache will get all assets from browser cache instantly — zero network requests. A new visitor or one on a fresh browser gets assets from CDN cache in 10-30ms. An edge node that has never cached an asset gets it from origin in 100-600ms and caches it for all subsequent visitors in that region. These three tiers compound: once an asset is cached in the CDN, every visitor globally benefits without touching your origin.
The interaction between page cache layers (browser, CDN, page cache, object cache, OPcache) is explored in detail on the cache explainer page — understanding all four layers is necessary for diagnosing why TTFB is slow even after adding a CDN.
CDN Benefits vs Reality: What Changes and What Does Not
CDN marketing is relentlessly positive. "Speed up your site globally." "Cut load times by 50%." These claims are true for specific assets under specific conditions. They are misleading when applied to the site as a whole — particularly for WordPress sites with significant dynamic content. Here is an honest breakdown.
What CDN Genuinely Improves
- Latency for geographically distributed visitors. The difference between 800ms and 20ms TTFB for a visitor in Tokyo accessing a Dallas-hosted site is entirely a CDN benefit. This is real and significant.
- Static asset delivery speed. Images, CSS, JS, fonts — all delivered from the nearest edge node. Sub-30ms delivery instead of sub-500ms is transformative for LCP scores.
- Bandwidth costs. Traffic served from CDN edge does not hit your origin's bandwidth quota. For high-traffic sites on metered plans, this saves real money.
- Volumetric DDoS absorption. A 100Gbps flood against a CDN's 100Tbps+ network is trivially absorbed. The same flood against your origin's 1Gbps uplink is an outage.
- Origin server load. Fewer requests reaching origin means lower CPU and memory usage during traffic spikes. A 90% hit ratio means your origin only handles 10% of actual traffic.
- Availability during traffic spikes. A viral post that sends 100x normal traffic hits CDN edge before origin. Origin survives because it only sees the MISS fraction.
What CDN Does Not Fix
- Slow database queries. If your WordPress site takes 2 seconds to generate a page because of unindexed MySQL queries or WooCommerce product queries, the CDN delivers that 2-second wait from a nearby server. The wait is still there.
- Bloated WordPress themes. A theme loading 800KB of unminified JavaScript delivers that 800KB faster from a CDN edge — but it is still 800KB. A CDN reduces latency; it does not reduce file size.
- Uncached dynamic pages. Any page that bypasses CDN cache (logged-in users, cart, checkout, personalized content) goes to origin every time. A CDN adds zero performance benefit to these requests.
- Application-layer security holes. A CDN WAF blocks known attack patterns. It does not fix an insecure plugin, weak admin password, or outdated WordPress core.
- Broken page caching configuration. A site with no page cache serves fresh PHP on every request. A CDN passes these requests through to origin unchanged unless APO or a full-page CDN cache is configured.
- Local or regional audiences near origin. A UK-hosted site serving UK visitors already has 10-30ms latency. A CDN adds marginal benefit for this specific audience.
The Realistic Impact: A Worked Example
A WordPress blog hosted in the US with global traffic: images make up 70% of page weight. Without CDN, a UK visitor downloads all images from the US server — 500ms+ per image on high-latency connections. With CDN, the same visitor downloads from a UK edge node at 20ms per image. LCP improves dramatically. The PHP-generated HTML page — 15% of total page weight — is unaffected (unless APO is configured). The net result: significant improvement for image-heavy pages for international visitors. Near-zero improvement for local visitors or for pages dominated by PHP execution time rather than asset delivery time.
CDN Types Explained: Pull, Push, Reverse Proxy, Image CDN, Video CDN
The term "CDN" covers five distinct architectures that work differently, serve different content types, and have different operational implications. Most WordPress owners only need a pull CDN or reverse proxy CDN, but understanding all five clarifies when you would reach for each one.

| CDN Type | How It Works | Best For | Examples | Key Consideration |
|---|---|---|---|---|
| Pull CDN | CDN fetches from your origin on first request, then caches | Images, CSS, JS, fonts — standard website assets | Cloudflare, KeyCDN, BunnyCDN pull zones | Zero setup — point DNS and you're done. Cache warms automatically. |
| Push CDN | You upload files directly to CDN storage | Large files, software downloads, backups, video files | BunnyCDN storage zones, AWS S3 + CloudFront | You control exactly what is on the CDN. Good for files that never change. |
| Reverse Proxy CDN | All traffic (static + dynamic) flows through CDN | Full-site acceleration, WAF, DDoS protection | Cloudflare, Fastly, Akamai | Protects origin IP, enables WAF. Dynamic pages can use edge rules. |
| Image CDN | Real-time image transformation at the edge | Sites with thousands of images needing responsive sizes | Cloudflare Images, imgix, Cloudinary | Resize, convert to WebP/AVIF, crop — all at delivery time, not build time. |
| Video CDN | Adaptive bitrate streaming from edge nodes | Video-heavy sites, course platforms, media streaming | AWS CloudFront, Akamai, Fastly | HLS/DASH delivery with buffering optimized for video player performance. |
Pull CDN: The Default for Most Sites
A pull CDN is configured by pointing your asset URLs (or your entire domain via DNS proxy) at the CDN. When a visitor requests an asset the edge has not seen before, the edge "pulls" it from your origin, caches it, and returns it. Every subsequent request for that asset from that region is served from cache. You never manually upload anything. The cache fills automatically as real visitors request real assets. The downside: cache cold-start means the first visitor to request any new asset after a deploy or purge hits origin directly. For high-traffic sites this is negligible — the cache warms within minutes. For low-traffic sites, cold starts happen more frequently.
Push CDN: Manual Control, Best for Large Static Files
A push CDN requires you to upload files to CDN storage yourself. You control exactly what is on the CDN and when it is there. There is no origin pull because there is no origin — the CDN storage is the origin. This is the correct architecture for software download sites, large media archives, or video game asset distribution where files are gigabytes in size, change infrequently, and cannot be dynamically fetched. Push CDNs are operationally more complex — you need to manage uploads and deletions explicitly — but they give complete control and avoid any origin load. BunnyCDN storage zones are a common push CDN implementation.
Reverse Proxy CDN: Full-Site Acceleration and Protection
A reverse proxy CDN (like Cloudflare in proxy mode) sits in front of your entire domain. All HTTP traffic — static and dynamic — routes through the CDN's network. This provides static asset caching, DDoS protection, WAF filtering, SSL termination, HTTP/2 and HTTP/3 delivery, and (with APO) full-page HTML caching. Your origin IP is hidden behind the CDN's anycast addresses. This is the architecture most businesses should use because the security benefits compound with the performance benefits at no additional complexity. The tradeoff: you lose direct visibility into visitor IPs (the CDN adds a Cf-Connecting-IP header containing the real visitor IP), and CDN configuration mistakes affect your entire site.
Image CDN: Real-Time Transformation
An image CDN does more than deliver images fast — it transforms them at delivery time. Request the same source image with different URL parameters and get different sizes, formats, and quality levels. A single product.jpg source file can be delivered as 400px WebP at 80% quality for mobile, 800px AVIF at 90% quality for desktop, and 200px WebP thumbnail for a grid — all from one uploaded file, all handled at the CDN edge, not at your server. Cloudflare Polish and Mirage, imgix, and Cloudinary are image CDN services. For sites with hundreds of product images or editorial photography, image CDNs eliminate the need for WordPress to generate and store multiple image sizes.
Dynamic vs Static Content: The WooCommerce Problem Most Guides Ignore
Static content is any response that is identical for every visitor. An image is the clearest example — every visitor gets the same bytes. A CDN can cache it perfectly. Dynamic content is any response generated specifically for the requesting user — a cart page showing items you added, an account dashboard, a checkout flow. A CDN cannot cache these because the response differs per visitor.

The practical breakdown for a typical WordPress site:
- Cacheable by CDN without any special configuration: Images (JPEG, WebP, PNG, GIF), CSS files, JavaScript files, web fonts (WOFF2, WOFF), PDFs, static video files, sitemap.xml, robots.txt.
- Cacheable by CDN with full-page cache enabled (APO or plugin): Blog post pages, static pages (About, Contact), product pages (WooCommerce) for unauthenticated visitors with no cart.
- Not cacheable by CDN under any configuration: Cart page, checkout page, account pages, order confirmation, any page showing session-specific content, admin area, REST API responses with authentication.
The WooCommerce Cache Bypass Reality
WooCommerce sets cookies as soon as a visitor interacts with the store. The standard session cookie (woocommerce_cart_hash, woocommerce_items_in_cart, wp_woocommerce_session) signals to CDNs that the user has session state. Most CDNs, including Cloudflare, automatically bypass cache for requests that contain these cookies. The result: a visitor who has added a product to their cart gets no CDN caching on any subsequent page load until the session cookie expires.
This has real implications for cache hit ratio calculations. A WooCommerce store with active shoppers might measure an overall 35-50% CDN hit ratio — the first visit to product pages hits cache, but return visits with cart cookies bypass cache completely. Compare this to a blog with no user state, which routinely achieves 90-97% hit ratios. The CDN still delivers static assets (images, CSS) fast for these bypass requests — the HTML response just bypasses cache and hits origin.
Cloudflare APO and WooCommerce
Cloudflare APO handles the WooCommerce bypass problem more intelligently than standard CDN rules. APO serves cached HTML versions of product and category pages even to visitors with WooCommerce cookies, while bypassing cache only for the specific URLs that must be unique per session (cart, checkout, my-account). It also updates the cached page version within 30 seconds of a price or availability change via the APO Worker. The result: active shoppers see fast cached product pages with correct pricing, and only their cart-related pages hit origin. APO is $5/month standalone or included in Cloudflare Pro — it is the most impactful single CDN feature for WooCommerce performance.
Logged-In WordPress Users
When a WordPress user is logged in, WordPress sets a wordpress_logged_in_* cookie. Standard CDN configurations bypass cache for all requests carrying this cookie. This means: your logged-in editors, administrators, and registered users never benefit from HTML page caching. For most content sites, this is acceptable because editors are a small fraction of traffic. For membership sites or course platforms where most users are logged in, CDN HTML caching provides almost no benefit. The solution is serving personalized content via JavaScript after page load (edge-side includes or client-side personalization), allowing the HTML shell to be cached while dynamic elements load asynchronously.
Cloudflare Deep Dive: Proxy Mode, DNS-Only, APO, and WAF Integration
Cloudflare dominates CDN search traffic for a reason: it is the only provider with a genuinely useful free tier that includes not just CDN but also DDoS protection, WAF, and (with APO) full-page WordPress caching. Google associates Cloudflare heavily with CDN queries because it is the de facto starting point for anyone looking to add CDN to a WordPress site without spending money. This section covers what Cloudflare actually does under the hood.

Proxy Mode vs DNS-Only Mode
Cloudflare offers two modes for any DNS record, controlled by the orange/grey cloud toggle in the DNS dashboard:
All traffic for this DNS record routes through Cloudflare's network. Cloudflare returns its own IP addresses in DNS responses, hiding your origin's real IP. Every request passes through Cloudflare's edge: CDN caching, WAF rules, DDoS protection, SSL termination, and rate limiting all apply. This is required for CDN and security features to work.
- CDN caching active
- WAF rules enforced
- DDoS protection active
- Origin IP hidden
- SSL at edge
- Workers execute at edge
Cloudflare resolves the DNS record normally and returns your actual origin server's IP address. Traffic goes directly from visitors to your origin without passing through Cloudflare's network. No CDN, no WAF, no DDoS protection. Use for DNS records that require direct access: mail server MX records, SSH subdomains, FTP endpoints.
- No CDN caching
- No WAF
- No DDoS protection
- Origin IP exposed
- Direct connection to origin
- Faster DNS propagation for changes
SSL/TLS Encryption Modes
Cloudflare's SSL/TLS mode controls how the Cloudflare-to-origin connection is secured. Never leave this at "Flexible" in production:
- Off: No HTTPS to origin. HTTP only. Never use this.
- Flexible: HTTPS from visitor to Cloudflare; HTTP from Cloudflare to origin. Your origin does not need a certificate, but the origin connection is unencrypted. This is how phishing sites bypass the "I installed Cloudflare for free SSL" misconception. Avoid.
- Full: HTTPS end-to-end. Cloudflare validates that a certificate exists on your origin, but does not validate it is trusted. A self-signed certificate works. Use this if you cannot install a valid cert on your origin.
- Full (strict): HTTPS end-to-end. Cloudflare validates that your origin has a valid, trusted certificate — either from a public CA or from a Cloudflare Origin Certificate (free, 15-year validity). Use this always when possible.
APO: How Cloudflare Caches WordPress HTML Pages
Automatic Platform Optimization is a Cloudflare Worker that intercepts WordPress page requests and serves them from edge cache. The Worker detects WordPress via cookies and URL patterns, applies bypass rules for authenticated users and WooCommerce cart pages, and caches the HTML response at the edge with a 30-minute TTL. When you publish or update content in WordPress, a WordPress plugin (the Cloudflare plugin) triggers an immediate cache purge for that specific URL. The result: visitors get sub-50ms HTML responses from the nearest Cloudflare PoP rather than waiting for PHP to execute at your origin.
WAF Integration and How It Combines with CDN
Cloudflare's WAF runs at the edge, before traffic reaches your origin. Requests matching WAF rules (SQL injection patterns, XSS payloads, known bot signatures, vulnerability scanners) are blocked or challenged at the CDN layer. This means your origin server never processes malicious requests — they are dropped before they reach your server's network stack. On the free plan, Cloudflare provides managed rulesets from the OWASP Top 10. On Pro and above, you get the Cloudflare Managed Ruleset with thousands of signatures updated automatically. The WAF and CDN use the same edge infrastructure — adding WAF protection does not add latency because requests are already terminating at the edge for CDN purposes.
| Feature | Free | Pro ($20/mo) | Business ($200/mo) | Enterprise |
|---|---|---|---|---|
| Feature | Free | Pro ($20/mo) | Business ($200/mo) | Enterprise |
| CDN + PoPs | All 310+ PoPs | All 310+ PoPs | All 310+ PoPs | All 310+ PoPs |
| DDoS Protection | Unmetered L3/L4 | Unmetered + L7 | Advanced L7 | Enterprise SLA |
| WAF Rules | Free managed rules | 50 custom rules | 200 custom rules | Custom |
| APO (WordPress) | $5/mo add-on | Included | Included | Included |
| Cache Analytics | Basic | Full analytics | Full analytics | Full analytics |
| Image Optimization | No | Polish + Mirage | Polish + Mirage | Custom |
| Workers (edge compute) | 100k req/day free | 10M req/mo | Custom | Custom |
| Support | Community | Email/chat | 24/7 chat | Dedicated TAM |
For most WordPress sites, the free plan is sufficient. The Pro plan makes sense if you need custom WAF rules, Cloudflare image optimization (Polish + Mirage), or want APO included without paying the add-on fee. Business tier is primarily relevant for compliance-sensitive sites needing custom SSL certificates or enterprise-level support SLAs. The SSL certificates guide covers Cloudflare's origin certificate setup in detail.
CDN and SEO: How Edge Delivery Affects Core Web Vitals and Crawl Efficiency
A CDN affects SEO in three distinct ways: it directly improves Core Web Vitals metrics (which are Google ranking signals), it reduces TTFB (which is a component of LCP), and it can improve crawl efficiency by reducing origin server load during Googlebot crawls. The effect varies significantly depending on your content type and where Google's crawlers originate.

Core Web Vitals Impact
Cloudflare's global network is not just close to your visitors — it is also close to Google's web crawlers. Googlebot crawls from US-based IP addresses (primarily Mountain View, CA). For a US-hosted site, a CDN does not change Googlebot's experience much. For a European-hosted site, Cloudflare's US PoPs may serve Googlebot faster than the European origin could. But more importantly, the field data Google uses for Core Web Vitals (via Chrome User Experience Report / CrUX) reflects real user experiences — and real users are geographically distributed. If your audience is international, CDN improvements to their experience directly improve your CrUX scores.
The metric-level breakdown:
- LCP (Largest Contentful Paint): Usually the hero image or header image. CDN delivery dramatically reduces image fetch time for distant visitors. A London visitor waiting 600ms for a Dallas-hosted hero image versus 20ms from a CDN edge sees their LCP drop by ~580ms. This is where CDN has the largest SEO impact on a typical blog or product page.
- TTFB (indirect LCP component): TTFB is not directly a Core Web Vitals metric, but it is one of the LCP subparts. A CDN with full-page caching (APO) reduces TTFB from 200-600ms (PHP execution) to 20-40ms (cached HTML from edge). This compresses into a meaningfully faster LCP.
- INP (Interaction to Next Paint): CDN delivery does not affect INP. INP measures main thread responsiveness to user interaction — that is a JavaScript execution problem, not a delivery problem. Delivering your JavaScript from a CDN 20ms faster does not change how long the main thread takes to process it.
- CLS (Cumulative Layout Shift): CDN delivery does not affect CLS. CLS measures visual stability — elements shifting after load. That is a CSS, image dimension, and font loading problem, not a delivery problem.
Crawl Efficiency
Googlebot respects server-side Cache-Control headers. A response with Cache-Control: max-age=86400 tells Googlebot it may cache that resource for 24 hours without re-fetching. When Googlebot re-crawls the page, it can skip fetching already-cached resources. CDN delivery means Googlebot's resource requests (images, CSS, JS) are served from edge cache without loading your origin, which is particularly relevant if your origin is on shared hosting with CPU limits. A CDN-accelerated site under Googlebot crawl is a site that handles the crawl budget more efficiently — the crawl completes faster, and origin CPU limits are less likely to cause 429 or 503 errors that pause Googlebot's crawl.
The Practical SEO Takeaway
If your site has global traffic or is image-heavy, a CDN has genuine SEO value through LCP improvements. If your site is local or regional with an already-fast origin server near your audience, the SEO value is marginal. The most impactful SEO move related to CDN is combining a fast origin (good TTFB) with CDN-cached images (fast LCP) and a full-page cache (Cloudflare APO or WP Rocket). Each layer compounds on the others.
How to Set Up a CDN for WordPress: Cloudflare Free Setup, WP Rocket, and W3TC
WordPress CDN setup has three distinct approaches with different capability levels. The right choice depends on what you are trying to achieve and what plugins you already use.
Option 1: Cloudflare DNS Proxy (Free, Recommended Starting Point)
This covers the basics: static asset CDN, DDoS protection, basic WAF, SSL at edge. It does not cache WordPress HTML pages without APO.
- Create a free Cloudflare account and add your domain.
- Cloudflare scans your existing DNS records. Review and confirm they are correct.
- Update your domain's nameservers at your registrar to Cloudflare's nameservers (e.g.,
ada.ns.cloudflare.comandcole.ns.cloudflare.com). - Wait for nameserver propagation — typically 30 minutes, up to 24 hours.
- In Cloudflare > SSL/TLS > Overview, set encryption mode to Full (strict). If your origin has no SSL certificate, install one first (cPanel AutoSSL or Certbot on VPS).
- Enable Always Use HTTPS under SSL/TLS > Edge Certificates.
- Enable Automatic HTTPS Rewrites — this fixes mixed content warnings caused by hardcoded HTTP asset URLs.
- Under Speed > Optimization, enable Auto Minify (JS, CSS, HTML) and Brotli compression.
At this point, all static assets serve from Cloudflare edge. WordPress HTML pages bypass CDN and go to origin. TTFB is unchanged; image/CSS/JS delivery is significantly faster for distant visitors.
Option 2: Cloudflare APO (Full-Page WordPress Caching)
APO is the upgrade that makes Cloudflare genuinely transformative for WordPress. Enable it from the Cloudflare dashboard under Speed > Optimization > Automatic Platform Optimization. It requires installing the official Cloudflare WordPress plugin, which handles cache purge on publish.
# Install and configure Cloudflare plugin
wp plugin install cloudflare --activate
# Verify APO is active
wp cloudflare status
# Manually purge cache (useful after bulk updates)
wp cloudflare purge-cacheOption 3: WP Rocket + Any CDN (Pull Zone)
WP Rocket is the most reliable WordPress caching plugin and integrates with any CDN that supports pull zones (BunnyCDN, KeyCDN, Cloudflare, RocketCDN). The CDN integration works via URL rewriting: WP Rocket rewrites your static asset URLs from https://yourdomain.com/wp-content/uploads/image.jpg to https://cdn.yourdomain.com/wp-content/uploads/image.jpg. The CDN subdomain serves assets from its edge cache. WP Rocket's page cache generates static HTML files; the CDN delivers your other assets.
# Check cache status header
curl -sI https://cdn.yourdomain.com/wp-content/themes/yourtheme/style.css \
| grep -i "cf-cache-status\|x-cache\|cdn-cache"
# Expected output for Cloudflare:
# cf-cache-status: HIT
# Expected output for BunnyCDN:
# cdn-cache: HITCache Purge Verification After Deploy
After any site update, verify your CDN cache cleared correctly. The most common failure mode I have encountered is a deploy that updates JavaScript or CSS but the CDN continues serving the cached old version because the purge failed silently.
# 1. Check CSS version header (look for Last-Modified or ETag change)
curl -sI https://yourdomain.com/wp-content/themes/yourtheme/style.css
# 2. Force cache bypass to compare origin vs CDN responses
curl -sI https://yourdomain.com/page-url/ \
-H "Cache-Control: no-cache" \
-H "Pragma: no-cache"
# 3. Verify CF-Cache-Status after purge (should be MISS, then HIT on next request)
curl -sI https://yourdomain.com/wp-content/uploads/hero.webp \
| grep cf-cache-status
# First request after purge: MISS
# Second request: HITCDN Provider Comparison: Cloudflare, BunnyCDN, KeyCDN, Fastly, AWS CloudFront
The CDN market is dominated by Cloudflare for WordPress users and AWS CloudFront for enterprise workloads. Between those extremes, BunnyCDN and KeyCDN offer compelling pricing for pure asset delivery without the full reverse-proxy feature set. Here is a practical comparison based on what WordPress site operators actually care about:
| Provider | Pricing | PoP Count | Key Features | Best For |
|---|---|---|---|---|
| Cloudflare | Free / $20+/mo | 310+ | Free DDoS, WAF, APO for WordPress | Free tier is genuinely useful. APO caches WordPress pages at edge. |
| BunnyCDN | $0.005–0.01/GB | 114+ | Pay-as-you-go pricing, Bunny Optimizer | Cheapest per-GB for high-volume static assets. No free tier but very low entry cost. |
| KeyCDN | $0.04/GB | 48+ | HTTP/2, Brotli, real-time analytics | Simple pull/push zones. Good EU coverage. No monthly minimum. |
| Fastly | $0.12/GB | 80+ | Instant purge, edge computing, VCL config | Instant purge is genuinely best in class. Expensive for small sites. |
| AWS CloudFront | $0.085/GB | 600+ | Largest PoP network, Lambda@Edge | Most flexible but complex pricing. Best for AWS-native stacks. |
| Akamai | Enterprise pricing | 4,000+ | Largest network, media streaming, enterprise SLA | Overkill for WordPress sites. Built for Netflix-scale media delivery. |
Cloudflare: The Right Choice for Most WordPress Sites
Cloudflare wins on the zero-friction factor. Add your domain, change nameservers, get CDN, DDoS protection, WAF, and free SSL in one step at zero cost. No credit card. No CDN subdomain configuration. No URL rewriting in your WordPress settings. The reverse proxy architecture means every asset automatically routes through CDN without any plugin configuration. The free tier is not a stripped-down trial — it is production-quality infrastructure that handles enterprise-scale traffic. I recommend starting with Cloudflare free for any new WordPress site, then evaluating whether Pro features are worth the upgrade after seeing your analytics.
BunnyCDN: Best Value for High-Volume Static Asset Delivery
If you are running a site with thousands of product images or user-generated content where you need pure asset delivery without the full reverse-proxy overhead, BunnyCDN at $0.005-0.01/GB is the cheapest quality option. Their Bunny Optimizer applies real-time image optimization similar to Cloudflare Polish. BunnyCDN is not a reverse proxy — you use it with URL rewriting (point your CDN subdomain at a BunnyCDN pull zone). It integrates cleanly with WP Rocket and LiteSpeed Cache. For a site serving 500GB/month of images, the cost difference between Cloudflare Pro and BunnyCDN is significant.
Fastly: Instant Purge Matters for News and eCommerce
Fastly's instant purge (sub-150ms globally via surrogate keys) is genuinely best-in-class. For a news site that publishes dozens of articles per day or a WooCommerce store that updates product availability in real time, the ability to purge a specific page from every edge node in 150ms is operationally important. Fastly is expensive for small sites ($0.12/GB) and requires configuration via VCL (Varnish Configuration Language), which has a higher operational complexity than Cloudflare's UI-driven setup. It is the right choice for development teams building on top of the CDN as infrastructure.
CDN Troubleshooting: Stale Cache, Header Inspection, Cache Poisoning
CDN problems fall into four categories: stale content being served after updates, cache bypass not working when it should, cache not working when it should be caching, and cache poisoning. Here is how to diagnose each.
Diagnosing Stale Content
Symptom: you deployed an update but visitors (or you) still see old CSS or JavaScript. The CDN is serving a cached copy that TTL has not expired on yet.
# Step 1: Check the cache status header
curl -sI https://yourdomain.com/path/to/asset.js | grep -i "cf-cache\|age\|last-modified"
# 'Age: 14400' means this response has been cached for 14400 seconds (4 hours)
# 'cf-cache-status: HIT' confirms it is coming from CDN cache, not origin
# Step 2: Check what the origin is serving (bypass CDN with direct IP)
# First find your origin IP from hosting panel, then:
curl -sI --resolve "yourdomain.com:443:ORIGIN.IP.HERE" \
https://yourdomain.com/path/to/asset.js | grep "last-modified\|etag"
# If origin etag differs from CDN etag, CDN is serving stale content
# Step 3: Purge and verify
# Via Cloudflare API:
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"files":["https://yourdomain.com/path/to/asset.js"]}'Diagnosing Cache Bypass (CDN Not Caching When It Should)
Symptom: every request shows CF-Cache-Status: BYPASS or MISS even for static assets. Common causes and diagnostics:
# Check response headers for bypass reasons
curl -sI https://yourdomain.com/image.webp
# Common bypass indicators:
# Set-Cookie: [anything] — response is setting a cookie
# Cache-Control: no-store — origin is explicitly forbidding caching
# Authorization: [in request] — authenticated request bypasses cache
# CF-Cache-Status: BYPASS — Cloudflare cache rule or cookie bypass active
# Check if WooCommerce session cookies are present in your test
# browser (they cause Cloudflare to bypass cache for authenticated sessions)
curl -sI https://yourdomain.com/product/sample/ \
--cookie "woocommerce_cart_hash=ANYTHING"
# If this shows BYPASS but without the cookie shows HIT, WooCommerce bypass is working correctlyCache Poisoning: What It Is and How to Prevent It
Cache poisoning is when an attacker manipulates a CDN into caching a malicious response and serving it to all subsequent visitors. It happens when CDNs cache responses that differ based on request headers but do not vary on those headers. For example: a CDN caches GET /search?q=normal and returns it to a visitor who requested GET /search?q=, because the CDN treated both URLs as the same cache key. Prevention: ensure your origin sends Vary: Accept-Encoding for compressed content, never cache user-input-reflected responses, and configure CDN cache key rules to include any query parameters that affect page content.
CDN Myths Debunked
These are the most persistent CDN misconceptions I encounter when reviewing hosting setups:
Myth: A CDN makes my slow WordPress site fast.
False, with a specific exception.
A CDN speeds up asset delivery for geographically distant visitors. It does not change how long your WordPress installation takes to generate a page. If your PHP execution takes 1.5 seconds, visitors still wait 1.5 seconds — they just wait it out from a nearby edge instead of a distant origin. The exception: Cloudflare APO caches full WordPress pages at the edge. When APO serves a cached page, PHP execution is bypassed entirely. But APO is a page cache that happens to run on CDN infrastructure — the caching is doing the work, not the CDN delivery mechanism itself.
Myth: Having Cloudflare means I have free unlimited CDN bandwidth.
Mostly true with important caveats.
Cloudflare's free plan has no bandwidth limit for CDN purposes on proxied web traffic. This is genuinely unusual — most CDN providers charge per gigabyte. However, Cloudflare's Terms of Service prohibit using their CDN to deliver large media files (video streaming, large binary downloads) that are primarily served from Cloudflare rather than from your origin. The intent is that Cloudflare proxies website traffic, not video streaming infrastructure. For standard website assets (images, CSS, JS), there is no practical bandwidth limit on the free plan.
Myth: CDN increases my Core Web Vitals scores automatically.
Only for LCP and TTFB, and only under specific conditions.
CLS is completely unaffected by CDN — it is a layout stability issue. INP is unaffected — it is a JavaScript execution issue. LCP improves if your LCP element is an image delivered from CDN. TTFB improves if APO or full-page caching is active. If your LCP element is text (a heading or paragraph), CDN has minimal impact on LCP. The measurable improvement depends entirely on what is causing your slow scores. Diagnosing which metric is failing and why — using Chrome DevTools or PageSpeed Insights — is necessary before assuming CDN will fix it.
Myth: I should enable Cloudflare's "Development Mode" to see my changes immediately.
Development Mode is a temporary diagnostic tool, not a workflow.
Cloudflare Development Mode bypasses edge caching for 3 hours, which means your origin serves every request directly — defeating the entire purpose of having a CDN. It is useful for verifying a live change during development. It is not a production setting. A properly configured CDN with per-URL cache purge on deploy is the correct workflow. If you find yourself enabling Development Mode regularly, your cache invalidation strategy needs fixing.
Myth: Using a CDN makes my site immune to DDoS attacks.
Partially true — for volumetric attacks. Application-layer attacks still work differently.
Cloudflare's network capacity (100+ Tbps) means a volumetric DDoS flood that would saturate your origin's uplink is absorbed without reaching your server. This is real protection. However, application-layer attacks (Layer 7 — slow POST floods, credential stuffing, scraping that triggers PHP execution for every request) bypass CDN caching because they look like valid requests. These requests reach your origin and can still overwhelm it. Cloudflare's rate limiting rules and WAF help significantly with Layer 7 attacks, but they require configuration — they are not automatic.
Where to Go Next
Understanding CDN naturally leads to two adjacent topics. The caching layers guide covers how browser cache, CDN cache, page cache (WP Rocket, LiteSpeed), object cache (Redis), and PHP OPcache work together — and how to diagnose which layer is the bottleneck when performance is still slow despite a CDN. The TTFB guide explains the full request lifecycle including the server processing phases that a CDN cannot shorten for uncached dynamic requests — understanding these phases explains exactly why a CDN alone does not fix a slow origin server. For security, web hosting security threats covers what Cloudflare's WAF blocks and what it cannot help with at the application layer. If you are evaluating which managed VPS hosting option to pair with Cloudflare for the best overall performance, the managed VPS guide covers origin server quality in depth.
CDN Frequently Asked Questions
Does every website need a CDN?
No — and this is where most CDN guides mislead beginners. If your visitors are geographically close to your origin server, the latency benefit is minimal. A blog hosted in London with 90% UK traffic already has low latency to its origin. A CDN helps most when your audience is geographically spread. It also helps for DDoS absorption, regardless of geography. The clearest cases for a CDN: you have significant international traffic, your static assets are large (images, video), or you want DDoS protection and WAF functionality. The clearest case against: you have a local or regional site, your traffic is low, and your origin server is already fast.
What is a CDN cache hit ratio and why does it matter?
The cache hit ratio is the percentage of requests served from the CDN edge without contacting the origin server. A 90% hit ratio means 90 out of every 100 requests never touch your origin — they are served from a nearby edge node in milliseconds. A 40% hit ratio means the CDN is barely helping — most requests still go back to origin. The hit ratio is determined by your TTL settings, how diverse your URLs are, how much dynamic content you have, and how much traffic each cached asset receives. Dynamic WordPress sites often have poor hit ratios because most page URLs are unique or user-specific. Static sites routinely achieve 95%+ hit ratios.
What is the difference between CDN cache TTL and browser cache TTL?
CDN TTL (usually controlled by s-maxage or Surrogate-Control headers) tells the CDN how long to keep a cached copy of an asset before checking with your origin for a fresh version. Browser TTL (controlled by max-age) tells the visitor's browser how long to keep the asset in local disk cache before checking the CDN or origin again. You can set different values for each. For example: s-maxage=86400 (CDN caches for 24 hours), max-age=3600 (browser caches for 1 hour). This lets you purge the CDN on deploy while still getting moderate browser caching, without forcing every visitor to re-download everything immediately.
Can a CDN make a slow WordPress site fast?
A CDN improves static asset delivery dramatically. It will not fix a slow WordPress site. The confusion comes from conflating two different problems: delivering assets quickly to geographically distant visitors (CDN solves this), and generating pages quickly on your origin server (CDN does not solve this). If your WordPress site takes 3 seconds to generate a page because of a slow database, un-cached PHP execution, or a bloated theme, the CDN delivers that 3-second response from a nearby edge node instead of a distant one — but the 3 seconds still happens. A CDN with a properly configured page cache (Cloudflare APO, or a plugin-level cache that stores static HTML) can fix the PHP execution problem by caching full pages at the edge. But that is the page cache doing the work, not the CDN delivery mechanism itself.
What is Cloudflare APO and how does it work with WordPress?
Cloudflare APO (Automatic Platform Optimization) is an add-on that caches full WordPress HTML pages at Cloudflare's edge, not just static assets. Normally, Cloudflare only caches CSS, JS, and images — each HTML page request bypasses the CDN and hits your origin. APO changes this: it stores a cached copy of your rendered HTML pages at every Cloudflare PoP. Visitors get sub-50ms TTFB because they are served a static HTML snapshot from the nearest edge, not a dynamically generated PHP response from your origin. APO automatically bypasses cache for logged-in users and WooCommerce cart/checkout pages. It costs $5/mo on the free plan and is included in Pro and above.
How does Cloudflare proxy mode affect my website?
When Cloudflare proxy is enabled (orange cloud in DNS settings), all traffic to your domain routes through Cloudflare's network before reaching your origin server. Your origin's real IP address is hidden — visitors connect to Cloudflare's IP instead. Cloudflare applies your WAF rules, DDoS protection, CDN caching, SSL termination, and any Workers at the edge before forwarding allowed requests to your origin. In DNS-only mode (grey cloud), Cloudflare resolves DNS normally and traffic goes directly to your origin — no CDN, no WAF, your IP is exposed. The proxy mode is required for CDN and security features. DNS-only is used for subdomains that need direct access, like mail servers or SSH.
Does a CDN help with DDoS attacks?
Yes — significantly, for volumetric attacks. When you are behind a CDN like Cloudflare, incoming traffic hits the CDN's network (with hundreds of terabits of capacity) before reaching your origin. A volumetric DDoS flood that would saturate your origin's 1Gbps uplink is trivially absorbed by Cloudflare's infrastructure. The CDN also hides your origin IP, preventing attackers from bypassing the CDN to attack your server directly. However, application-layer DDoS (Layer 7 — POST floods, scraping attacks that target PHP execution) still passes through to your origin if caching is low. This is why Cloudflare's WAF rules and rate limiting matter in addition to the CDN itself.
What CDN header tells me whether a request was served from cache?
The CF-Cache-Status header (on Cloudflare) shows HIT, MISS, EXPIRED, BYPASS, DYNAMIC, or REVALIDATED for every response. You can check it with: curl -sI https://yourdomain.com/image.jpg | grep -i cf-cache-status. On BunnyCDN, the header is CDN-Cache. On generic Varnish/Nginx setups it is often X-Cache. A HIT means the CDN served it without contacting origin. MISS means it was not cached (first request, expired TTL, or uncacheable). BYPASS means a cache bypass rule was triggered (logged-in user cookie, no-store header). DYNAMIC means Cloudflare determined the content is not cacheable. Always check these headers after deploying to verify your cache configuration is working as intended.
Why does my WooCommerce site get low CDN cache hit ratios?
WooCommerce generates reasons to bypass CDN caching on almost every page. Cart pages must be unique per visitor — the cart contents are stored in a session cookie. Checkout and account pages contain user-specific data. Any page visited after adding to cart gets a WooCommerce session cookie, which most CDNs read as a reason to bypass cache entirely for that user. The practical result: new visitors with no WooCommerce cookies get CDN-cached product pages. Any visitor who has added to cart or logged in gets uncached origin responses for every subsequent page. Cloudflare APO handles this by bypassing cache only for the specific cart/checkout URLs and serving cached versions everywhere else, but even then, active shoppers see uncached responses.
What is origin shield and when do I need it?
An origin shield is an additional caching layer between the CDN edge PoPs and your origin server. Without origin shield, every CDN edge node that receives a cache MISS makes its own request to your origin — a popular asset with 100 edge nodes could trigger 100 simultaneous origin requests on the first cache cold-start or after a purge. With origin shield, all edge MISS requests are funneled through a single intermediate node (the shield), which makes one request to your origin, caches it, and serves all the other edge nodes from there. This protects origin against traffic spikes on cache purges or new deployments. Cloudflare calls this Argo Shield. BunnyCDN includes origin shielding by default. It matters most if your origin is bandwidth-limited or CPU-constrained.
Does using a CDN affect my SSL certificate?
When you use a CDN in reverse proxy mode (like Cloudflare), there are actually two SSL connections: visitor to CDN edge, and CDN edge to your origin server. Cloudflare provisions its own edge certificate for visitor connections automatically. Your origin server needs its own certificate for the CDN-to-origin connection. Under Cloudflare's Full (strict) mode, the origin certificate must be valid and trusted — Cloudflare validates it. Under Full mode (not strict), Cloudflare encrypts the connection to origin but does not validate the cert. You should always use Full (strict). Cloudflare offers free 15-year origin certificates specifically for this purpose. Your visitors never see your origin certificate — they interact only with the Cloudflare edge certificate.
How do I purge CDN cache after updating my website?
Each CDN has its own purge mechanism. On Cloudflare: go to Caching > Configuration > Purge Cache, or use the API: curl -X POST 'https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache' with a JSON body of {'purge_everything': true}. On BunnyCDN: use the API or the Purge URL button in the storage zone. On Fastly: their instant purge via API is one of their strongest features — surrogate keys let you tag content and purge all tagged items in under 150ms globally. Most WordPress CDN plugins (WP Rocket, W3 Total Cache, LiteSpeed Cache) integrate CDN purge into their cache clearing workflow. On deploy, always purge CSS and JS files. On content update, purge the specific page URL. Never leave stale CDN cache without a purge plan.
