On November 18th, I was mid-deploy on an unrelated feature when our on-call channel lit up. Checkout was throwing 522s, the marketing site wouldn't load, and our status page (hosted on a completely different provider, thankfully) started getting hit with "is this us?" messages from customers before we'd even confirmed anything. My first assumption was that we'd shipped something bad. We hadn't.

What we were looking at was a wall of Cloudflare error pages, and once I checked Twitter it was obvious this wasn't our bug. Half the internet was down at the same time, including sites that have nothing to do with us and nothing in common with our stack except one thing: the same company sitting in front of all of them. It took about six hours for things to fully settle.

Once the fire was out, I did something I probably should have done a long time before that afternoon: I actually went and checked, domain by domain, which CDN sits in front of each of our production properties. I assumed I already knew the answer. I was only half right, and what I found afterward, in a data writeup by CipherCue on CDN concentration across European companies, made the whole afternoon make a lot more sense.

If you can't answer, right now, which CDN vendor fronts each of your production domains, you also can't answer whether one provider's bad day is capable of taking your entire company offline at once.

What November 18th actually looked like from inside a frontend team

The thing that made this outage confusing at first is that it didn't look like a normal outage. Our origin servers were healthy the whole time. Our database was fine. Deploys were still succeeding. What broke was the layer in front of all of that: TLS termination, edge routing, and the WAF, all handled by Cloudflare before a request ever reaches our servers. When that layer falls over, your app being perfectly healthy doesn't matter, because nothing gets to it.

According to Cloudflare's own postmortem, the root cause was a database permissions change that caused an internal Bot Management feature file to fill with duplicate entries, doubling in size past a limit their proxy enforced, which crashed core CDN and security serving globally. It wasn't an attack, and it wasn't anything customers did wrong on their end.

"not caused, directly or indirectly, by a cyber attack or malicious activity of any kind" — Cloudflare's incident writeup, November 18, 2025

Cloudflare used almost identical wording again after a separate incident on February 20th, when a cleanup automation task misread a buggy API response as an instruction to withdraw BYOIP prefixes, pulling about a quarter of them off the internet via BGP for just over six hours. Two different bugs, two different subsystems, same underlying pattern: routine internal engineering work reaching all the way out to the edge and taking a lot of unrelated companies down with it on the same afternoon.

Checking your own front door

The audit I ran after the outage was embarrassingly simple, which is exactly why I should have run it sooner. You don't need dashboard access to any of these vendors to figure out who's in front of a given domain. The response headers usually give it away, because CDNs stamp their own routing metadata onto every response that passes through their edge.

I went through our production domains one at a time and grepped for the tells: a cf-ray header or a server value of cloudflare for Cloudflare, an x-served-by pointing at a Fastly cache node for Fastly, and an x-amz-cf-id for CloudFront.

curl -sI https://app.ourcompany.example \
  | grep -iE 'server|cf-ray|x-served-by|x-amz-cf-id'

Running that across every subdomain we own turned up two properties I genuinely didn't know were behind Cloudflare, both set up by a contractor two years earlier and never documented anywhere. If a domain returns none of those headers and the server value names your own web server or origin host directly, that's usually a sign there's no CDN in front of it at all, which carries its own risk profile in the opposite direction.

The numbers behind that gut feeling

After the audit, I wanted to know whether our setup was unusual or just how the industry looks right now. CipherCue's Chris McCabe published an analysis pulling exactly this apart across European companies, and the headline number is blunt: of 44,143 European companies where CipherCue detected a CDN at all, 39,547 of them, 89.6%, sit behind Cloudflare. For a rough sanity check, W3Techs separately put Cloudflare at 84.1% of sites where a reverse proxy could be identified, measured the same way, as a share of the identified set rather than of the entire web.

The methodology matters here. This isn't "Cloudflare vs. the whole internet" — companies serving straight from their own origin aren't counted at all. It's a measure of who the CDN-using companies actually chose. Amazon came in second through CloudFront detections, but with a real caveat: some of that is companies who deliberately picked CloudFront, and some is just companies whose origin happens to sit on AWS. Fastly, described in the piece as the cleanest comparison because it's an unambiguous pure CDN, came in a distant third.

Breaking it out by country shows the concentration isn't uniform, but it's never small:

CountryCompanies with a CDNBehind CloudflareCloudflare share
Netherlands7,9397,58795.6%
United Kingdom17,00715,84693.2%
Poland2,8962,68292.6%
France4,0083,45686.2%
Italy3,6613,12685.4%
Germany5,7154,65081.4%
Spain2,0011,57678.8%
Ireland79262478.8%

Germany has the lowest share among the bigger markets, and it's still four out of every five CDN-using companies on one vendor. The UK has the largest raw count behind Cloudflare of any market in the dataset, nearly 16,000 companies. Read the table as a floor, not a ceiling, given the cohort skews toward small and mid-sized companies where Cloudflare's free tier is strongest.

Why everyone ends up behind Cloudflare anyway

None of this surprised me once I thought about why we picked Cloudflare in the first place, three years ago, as a five-person engineering team. It was free, it was a five-minute DNS change, and it bundled DDoS mitigation, a WAF, and a CDN into one dashboard we didn't have to think about again. For a small team with no dedicated infra person, that's not a lazy choice, it's the correct one under the constraints we actually had.

That's also exactly why the blast radius is so large when something breaks. Fastly and Akamai ship bugs too, plenty of them. They just don't take down a fifth of the sites you use in a day, because a smaller fraction of the internet is sitting behind them in the first place. The concentration isn't evidence that Cloudflare's engineering is worse than its competitors; it's evidence that being the default choice for the largest number of small and mid-sized teams comes with a side effect nobody budgets for until the day it matters.

A CDN sitting in front of your domain says nothing about where your data actually lives. It terminates TLS and serves cached edge content, but your origin server, your database, and whoever processes customer data sit behind it — that's the part a GDPR or data-residency review actually needs to look at, not the front door.

What adding a second CDN actually costs you

The instinctive fix that came up in our retro was "let's just put a second CDN in front of the critical stuff." It sounds simple in a Slack thread and gets a lot less simple the moment you try to write the DNS config.

Our original setup for the checkout subdomain was about as basic as it gets: one CNAME record pointing straight at Cloudflare's proxy, a 60 second TTL we'd set once and never revisited, and nothing resembling a fallback path if that one record stopped resolving to something useful.

resource "aws_route53_record" "checkout" {
  zone_id = var.hosted_zone_id
  name    = "checkout.ourcompany.example"
  type    = "CNAME"
  ttl     = 60
  records = ["ourcompany.cdn.cloudflare.net"]
}

Lowering the TTL to 60 seconds felt like it was buying us something, but it wasn't buying what we thought. A short TTL only helps if you're planning to manually flip the record during an incident, and it does nothing if the resolvers are still pointed at the one authoritative answer that happens to route through the provider that's down. What we actually needed was a record that could fail over on its own, based on a health check that isn't itself dependent on Cloudflare being up.

resource "aws_route53_health_check" "cloudflare_edge" {
  fqdn              = "checkout.ourcompany.example"
  port              = 443
  type              = "HTTPS"
  resource_path     = "/healthz"
  failure_threshold = 3
  request_interval  = 10
}

resource "aws_route53_record" "checkout_primary" {
  zone_id         = var.hosted_zone_id
  name            = "checkout.ourcompany.example"
  type            = "CNAME"
  ttl             = 30
  records         = ["ourcompany.cdn.cloudflare.net"]
  set_identifier  = "cloudflare-primary"
  health_check_id = aws_route53_health_check.cloudflare_edge.id
  failover_routing_policy { type = "PRIMARY" }
}

resource "aws_route53_record" "checkout_secondary" {
  zone_id        = var.hosted_zone_id
  name           = "checkout.ourcompany.example"
  type           = "CNAME"
  ttl            = 30
  records        = ["d123456abcdef.cloudfront.net"]
  set_identifier = "cloudfront-secondary"
  failover_routing_policy { type = "SECONDARY" }
}

That gets the DNS layer sorted, but it's not the whole job, and I want to be honest about the part that still bit us in testing. Cloudflare and CloudFront don't cache the same way by default, their default cache keys differ, their WAF rule sets aren't equivalent, and a rule tuned against false positives on one edge can happily block legitimate traffic on the other. Getting real parity between two CDNs means testing your cache behavior and your security rules on both, on an ongoing basis, not just wiring up a failover record and calling it done.

What I actually recommend doing this week

I'm not going to tell you to rip Cloudflare out, because for most teams that's the wrong call given the cost and effort involved versus how rarely a global outage actually happens. What I'd push back on is doing nothing simply because nobody ever sat down and looked at the actual exposure.

The fix isn't necessarily a second CDN, it's making the dependency visible enough that someone on your team can decide about it on purpose instead of finding out during an incident. In practice that turned into a short list we now revisit every quarter:

  • Run the header check above against every production subdomain you own, including the ones nobody's touched in two years.
  • Write down, in a doc your whole team can find, which vendor fronts each domain and which ones share a provider.
  • Rank those domains by what actually breaks if the CDN goes down: your marketing site going dark for six hours is annoying, checkout going dark is a different conversation with finance.
  • For anything ranked critical, at minimum get a second authoritative DNS provider in place so a Cloudflare-side DNS problem doesn't also take out your ability to route around Cloudflare.
  • Subscribe to your CDN's status page with an alert path that doesn't itself route through that CDN, because a status page hosted behind the same provider it's reporting on has an obvious blind spot.

For us, the honest outcome was that only one domain, checkout, got the full failover treatment. Everything else stayed single-provider, on purpose, because the engineering cost of dual-CDN parity wasn't worth it for a marketing page. That's a fine answer as long as it's a decision and not a default.

So is Cloudflare too big to fail

No single vendor is too big to fail, and the last fifteen months of postmortems make that pretty concrete. What changed for our team after November 18th wasn't the vendor, it was our own awareness of the blast radius we'd quietly accepted three years earlier without ever writing it down. We still use Cloudflare for almost everything. The difference is that now, if it has another bad afternoon, we know exactly which of our domains go dark, which ones don't, and that the gap between those two lists was a choice we actually made rather than one that happened to us.

If you take one thing away from this, let it be the header check, not the Terraform. It costs you five minutes and it tells you something concrete about risk you're currently carrying without knowing it. Whether you act on what it tells you is a separate, harder conversation, and it's going to look different for a two-person side project than it does for a payments team, which is exactly why nobody outside your company can answer it for you.

Sources: CipherCue — Among European Companies That Use a CDN, Nearly 9 in 10 Use Cloudflare, Cloudflare — November 18, 2025 outage postmortem, Cloudflare — February 20, 2026 outage postmortem