Do You Need a CDN? What Changed on My Sites

cf-cache-status: DYNAMIC. That is what one of my own sites, a small business site I keep on Cloudflare Pages, sent back when I checked its headers on 20 September 2026, and I had been expecting the smug little confirmation that everything was being served from the edge. Not HIT. Not even MISS. DYNAMIC, which in Cloudflare’s vocabulary means the response did not come from its cache at all.

That site still had the fastest first byte of everything I measured that afternoon. Which is the short version of what I want to argue here: most of what a content delivery network does for a small site is not what the explainers say it is, and the part that does help is measurable in about a minute if you know which two numbers to look at.

I have three arrangements running on sites I pay for, which is the only reason I am willing to publish numbers about them: two WordPress blogs sitting directly on Hostinger shared hosting with no CDN in front, one business site of mine on the same hosting account but served through the host’s own CDN layer, and one static site on Cloudflare Pages.

Forget the first byte for a moment. Look at the handshake

Every comparison of CDN and no CDN I have read jumps straight to time to first byte, which on four different sites with four different amounts of HTML is close to meaningless. The columns that actually describe the network are the ones before it: how long the TCP connection took, and when the TLS handshake finished.

SiteDNSTCP connectTLS completeFirst byte
This blog (no CDN)0.006 s0.067 s0.236 s0.455 s
My second blog (no CDN)0.005 s0.070 s0.206 s0.568 s
My agency site (host CDN)0.007 s0.066 s0.188 s0.294 s
My static site (Cloudflare Pages)0.005 s0.042 s0.148 s0.275 s
Medians of five requests per site, all in the same run on 20 September 2026 from home fibre in Valencia, Spain. Values are cumulative, so each column includes the ones before it. Four different sites with different payloads: this is not a race, and the last column is not the point.

Connecting to the Cloudflare edge took 42 ms against 66 to 70 ms for the origin, and the TLS handshake completed at 148 ms against 188 to 236 ms. That gap is the one thing an edge network is structurally guaranteed to deliver: the TCP and TLS round trips end at a machine near the visitor rather than at your server. When a handshake costs a fifth of a second, taking 60 to 90 ms out of it is a real improvement, and unlike cache hit ratios it does not depend on configuration, plugins or luck.

The response header on that fastest site also carried CF-RAY: ...-MAD, meaning the request terminated at Cloudflare’s Madrid location, about as close to my desk as this gets. That is the mechanism in plain sight: it was not faster because the page was cached, it was faster because the conversation happened nearby. Remember that the same response said DYNAMIC.

The question I promised to come back to

When I found out that neither of my WordPress blogs was serving any page cache, the third row of that table jumped out at me: same hosting account, but 0.16 s quicker to first byte, and answering with Server: hcdn instead of Server: LiteSpeed. I said at the time I would not attribute that gap to the CDN without looking properly. I have now looked properly, and the answer is that I still cannot attribute it.

Two reasons. The first is that it is a completely different page: 56,325 bytes of very repetitive HTML that Brotli crushes to 2,482 bytes, against 100,574 bytes of WordPress output compressing to 26,886. Different application, different work, different everything. The second is more interesting: that CDN returns no cache-status header at all. Cloudflare labels every response HIT, MISS, DYNAMIC or BYPASS. My host’s CDN tells me only that it exists.

So for a toggle in a control panel it may well be doing useful work, and I have no way to confirm any individual request hit its cache. That is not a scandal, but it is worth saying out loud, because “our CDN is enabled” is a claim you cannot verify from outside on that platform. The background on the account and what else it includes is in my review of the Hostinger account these sites run on.

An edge in front of uncached PHP moves nothing important

Here is the order-of-operations mistake that looks like a fix. My blogs are slow to first byte because every request is assembled by PHP 8.3.33 on the fly, with no page cache anywhere in the chain. The obvious-looking fix is to put a network in front of them.

It would not work, because HTML is not cached at the edge by default anywhere. Static assets are: images, stylesheets, scripts, fonts. The HTML document, the thing whose generation is costing me 0.455 seconds, still gets built by PHP on every request and then relayed. I would be paying for a faster handshake while leaving the expensive part exactly where it was. Caching at the origin comes first, and that experiment is running now, documented in the post on discovering my blog was never cached.

Once the origin caches, an edge network becomes a multiplier on something that is already fast. Before that, it is decoration with a DNS change attached.

Two checks that tell you whether an edge is doing anything for you

The first is the cache status line in the response headers:

curl -sI https://example.com/ | grep -i -E 'server|cf-cache-status|x-cache|age'

What you want is a named status. HIT means the edge served it. MISS means it fetched it once and should hit next time, so run the command again and watch it change. DYNAMIC or BYPASS means this response is not being cached at the edge at all, which for HTML is normal and for an image is a misconfiguration. No header at all means you are guessing, which is where I am with my host’s CDN.

The second is the handshake timing that produced the table above:

curl -s -o /dev/null -w "connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer}\n" https://example.com/

Run it five or six times rather than once. If you are behind an edge network, the connect and TLS figures should be low and, more importantly, stable, because they no longer depend on the distance to your origin. If those two numbers are both high and jumpy, no amount of caching further down will rescue the experience.

The caveats on all of my numbers are the same as in every measurement on this site, and they are not small: five requests each, one route from Spain, homepage HTML only, no stylesheets or images, and nothing about Core Web Vitals. I lay out the method and its limits in full in the caching post, and what any of it does and does not imply for the user-experience metrics is in the post on Core Web Vitals on a cheap shared plan.

When the CDN is the hosting, and what that costs

My static site does not have a CDN attached to it. It lives on one, which is a different proposition entirely, and the reason I keep bringing it up here is that it reframes the question. You are not deciding whether to buy a delivery network; you are deciding whether your site is the kind of thing that can be served as files from many places at once. If it is, the network is where it should live, and on Cloudflare Pages that costs nothing: the published Free plan caps builds rather than bandwidth (Cloudflare Pages limits, checked 20 September 2026). I go through those limits, and Netlify’s newer credit-based pricing, in the post on free hosting that is actually worth using.

If it is not, because it is a WordPress site building pages out of a database on every request, then no amount of edge network changes the nature of the thing. You are shortening the trip to a machine that still has to phone home for the interesting part.

So do you need one?

  • Static site: you are probably already on one, or should be. The edge is the hosting, the certificate is included, and the bill is zero until you are doing something unusual.
  • WordPress on shared hosting with no page cache: not yet. Fix the origin, measure again, then decide. Adding a second layer to hide a first-layer problem is how people end up with two caches arguing.
  • Readers on another continent: yes, and this is the case my own data cannot speak to. The 60 to 90 ms I saved on a handshake from Spain to a European edge is the smallest version of that benefit, not the biggest. Measure from where your readers are.
  • Images, video or big downloads: yes, because that is the traffic the edge actually keeps, as opposed to HTML, which it usually does not.

And one thing I would not do: move DNS to an edge provider purely for a speed number, without checking what else moves with it. Nameservers, mail records and any verification records all live in the same place, and that change deserves its own quiet afternoon rather than a five-minute experiment. The safe sequence is in the guide to pointing a domain at your host without downtime.

The version of this page that used to sit at this URL told you that every site should sit behind a free CDN because the price of admission is one nameserver change. It is not terrible advice. It is just advice that would never have found the actual problem with the site it was published on, which was a cache that did not exist, on an origin nobody was looking at.