Analysis10 min read

The Hidden Cost of Free CDNs — What I Found Auditing 100 Cloudflare Sites

Free Cloudflare is the default for indie developers in 2026. After auditing 100 sites running it, three patterns kept emerging — and the fixes are mostly free if you spot them.

Enis Getmez avatarBy Enis GetmezFounder & Lead Engineer

Why "free Cloudflare" deserves an honest audit

Cloudflare's free tier is the most common piece of web infrastructure on the indie internet in 2026. It is genuinely good — global anycast network, free SSL, basic DDoS protection, unlimited bandwidth. Most sites benefit from turning it on.

But "free" is not "configured well". Across 100 small-to-mid market sites I audited over the past month — all running Cloudflare's free tier — three patterns kept appearing. None are Cloudflare's fault. All cost the site owner real performance or real money downstream.

This is the field report. Cloudflare is still my default recommendation. The defaults are not.

Krawly CDN Detector — surfaces the CDN provider and edge behaviour from public signals
Krawly CDN Detector — surfaces the CDN provider and edge behaviour from public signals

How I built the sample

100 production sites running Cloudflare free. Mix of WordPress (40), Next.js / static (25), Shopify storefronts via custom domains (15), and custom backends (20). Sites were drawn from clients, agency partners, and a random sample I confirmed were on the free plan via CDN Detector (which reads response headers like `cf-ray`, `server: cloudflare`, and the `__cf_bm` cookie that only appears on free plans during challenge issuance).

For each site I checked:

  • Cache hit ratio (visible via response headers and time-to-first-byte distribution)
  • HTTPS configuration (Full vs Full Strict)
  • DNS setup (proxied "orange cloud" vs DNS-only "grey cloud")
  • Page Rules / Cache Rules in use (visible indirectly via cache behaviour)
  • Bot Management headers (free tier has limited but real signals)
  • Pattern 1: 60% of sites had cache hit ratio under 50%

    The single most common issue. Most owners think "I'm on Cloudflare" means content is cached at edge. It doesn't, by default. Cloudflare's free tier caches static assets (images, CSS, JS) but not HTML by default.

    For most sites, that's fine. But for sites whose HTML is mostly static (blog posts, marketing pages, anything that doesn't change per visitor), the default leaves performance on the table. Every request for the same blog post hits the origin server.

    The check: load any blog post on the site, then check the response headers for `cf-cache-status`. Common values:

  • `MISS` — origin fetched, didn't cache HTML (common on free)
  • `DYNAMIC` — Cloudflare actively decided not to cache (cookies present, query string, etc.)
  • `HIT` — what you want for static HTML
  • `EXPIRED` — was cached, just expired, refetching
  • If you're seeing `MISS` on the same blog post URL twice in a row, your HTML is not being cached at edge even though it could be.

    The fix on the free tier: Cloudflare's "Cache Everything" page rule (the free tier gets 3 page rules). One rule that matches `example.com/blog/*` with "Cache Level: Cache Everything" and "Edge Cache TTL: 1 month" turns a 100ms origin fetch into a 5ms edge hit globally. For most blogs, the cache invalidates fast enough through manual purges or webhook integration.

    Pattern 2: 40% of sites running "Full" SSL instead of "Full (Strict)"

    Cloudflare's SSL options:

  • Off — no HTTPS to visitor (avoid)
  • Flexible — HTTPS to visitor, plain HTTP origin-side (very insecure, never use)
  • Full — HTTPS both legs, but Cloudflare does not validate origin certificate (still vulnerable to MITM between Cloudflare and origin)
  • Full (Strict) — HTTPS both legs with origin cert validation (the secure default)
  • A staggering 40% of my sample was running "Full" not "Full Strict". Most owners set "Full" once during initial migration when their origin had a self-signed cert, then never re-tightened after switching to a real cert.

    Why it matters: an attacker with network access between Cloudflare's edge and your origin (cloud provider misconfigurations happen) can intercept traffic on "Full". On "Full Strict" they cannot.

    The fix: SSL/TLS → Overview → set to "Full (strict)". Free, instant, and only breaks if your origin really doesn't have a valid cert (in which case fix that first — Let's Encrypt is free).

    Pattern 3: DNS records exposed beyond the proxy

    15% of sites had DNS records (A records, sometimes the apex) set to "DNS only" mode (the grey cloud) instead of "Proxied" (the orange cloud). Owners had set them up like this either accidentally or because they didn't realise the implications.

    When a record is "DNS only", Cloudflare resolves the name but does not proxy traffic. That means:

  • Your origin IP is publicly resolvable. Anyone can run `dig +short example.com` and find your real server.
  • All DDoS protection is bypassed for that hostname.
  • All caching, image optimization, and other edge features are bypassed.
  • When you set up Cloudflare, the dashboard makes both options look similar. The orange/grey cloud icon is the only difference, and beginners often don't notice it.

    Krawly DNS Record Checker — quickly verify which records point at Cloudflare vs the origin
    Krawly DNS Record Checker — quickly verify which records point at Cloudflare vs the origin

    I use DNS Record Checker to verify which records are proxied. Proxied records resolve to Cloudflare's edge IPs (104.16.x.x, 172.67.x.x, etc.). DNS-only records resolve to your origin's real IP.

    For every public hostname, ask: does this hostname need to be proxied? If yes, orange cloud. If no (a mail subdomain, an internal admin record), grey is fine but consider whether the subdomain should even exist publicly.

    Smaller issues that show up

    `Brotli` compression is off

    15% of sites had `Speed → Brotli` set to off (the default for some older accounts). Brotli compresses HTML better than gzip by about 15-20% on average. Free to enable, no downside.

    `Auto Minify` is on (turn it off)

    Conversely, 35% had Auto Minify enabled — Cloudflare strips whitespace and comments from HTML/JS/CSS at the edge. This was a popular optimization in 2018. In 2026 it breaks more than it helps:

  • Modern build pipelines already minify their JS/CSS
  • Stripping HTML whitespace can mangle inline JS, especially template literals
  • Some critical comments (Cloudflare's own browser-check token, browser feature detection) get stripped
  • Disable Auto Minify. Let your build pipeline handle it. The "performance" gains are negligible on modern, build-pipeline-minified code.

    "Rocket Loader" is on

    The most aggressive Cloudflare default. Rocket Loader rewrites all your JS to defer and load asynchronously. In 2024 it broke 1 in 4 sites I audited; in 2026 it's better but still breaks site-specific event handlers about 1 in 12 sites.

    Recommendation: leave it OFF unless you have explicit reason to enable it. Modern `async`/`defer` on `