Practice & Reference · Case Study · Real company

Cloudflare's Public Postmortem Culture

This page sticks to what Cloudflare has said about itself, in public, on its own engineering blog — mainly the postmortem for the July 2, 2019 outage, a 27-minute global disruption traced to a single bad regular expression in a Web Application Firewall (WAF) rule. That incident is worth a whole case study on its own: a textbook example of catastrophic regex backtracking turning into a worldwide CPU-exhaustion event. But the more interesting fact isn't the bug — it's that Cloudflare wrote up exactly how it happened, named the offending rule, quoted the actual regex, and published it within hours, for anyone on the internet to read. This page covers the incident itself, and then the harder question: what changes about a postmortem's rigor and an organization's accountability when the intended reader isn't just the team that broke it, but every customer, competitor, and security researcher who can read a blog post.

☺ Explain it like I'm 10

Imagine two kids who both spill juice on the carpet. One quietly wipes it up and never mentions it to anyone. The other walks into the living room and announces to the whole family exactly what happened, exactly which cup it was, exactly how long the stain took to clean, and promises out loud to use a lid next time. The second kid has to be far more honest and precise — everyone in the room can check the story against the carpet. Cloudflare is the second kid, but for outages that affect a meaningful slice of the internet: it doesn't just fix the problem quietly, it tells everyone exactly what broke, in enough detail that outside engineers can verify every claim — which is a much harder, much more accountable thing to do than fixing it and staying quiet.

🦊Your host for this topic: Foxy — the same root-cause detective who runs the five whys in postmortems & blameless culture, now looking at what happens when the finished document goes out the front door instead of staying on an internal wiki.

July 2, 2019: twenty-seven minutes, one regex, the whole edge network

☺ Like you're 10: A brand-new security rule went out to every Cloudflare location on Earth at once, and it had one bad line in it that made every computer choke trying to read it.

On July 2, 2019, Cloudflare deployed a new WAF managed rule intended to detect cross-site scripting (XSS) attacks. Cloudflare's WAF rules at the time deployed differently from its normal software — a routine code change was staged out gradually, but a WAF rule update, because it might need to respond to an active attack within minutes, deployed globally and near-instantly to every machine in Cloudflare's edge network. That distinction is the whole story: a bug in an ordinary staged deploy would have shown up in one region first, giving engineers a chance to catch it before it reached everyone. This bug reached everyone at once.

The timeline, minute by minute

Cloudflare's own postmortem, published the same day, laid out a timeline precise to the minute — the level of precision this page is trying to model, not just describe:

Time (UTC)Event
13:42The new WAF rule deploys globally, instantly, to every edge location.
13:45The first PagerDuty alert fires from synthetic monitoring — three minutes after deploy.
13:45–14:00Widespread HTTP 502 errors are reported from points of presence worldwide; on-call engineers trace the pattern to CPU exhaustion across the edge fleet.
14:00The new WAF rule is identified as the cause.
14:07Engineers trigger a global kill switch, disabling the WAF ruleset worldwide.
14:09Service is restored — 27 minutes of customer-facing impact, start to finish.
14:52The offending rule is removed, the fix validated, and the WAF is re-enabled globally.

Notice what the timeline actually shows: detection was fast (three minutes, via synthetic monitoring and PagerDuty — see alert design & alert fatigue for what makes an alert that fast possible) and mitigation was fast once the cause was found (seven minutes from root cause to global kill). The bulk of the 27 minutes — from 13:45 to 14:00 — was spent figuring out what was on fire, not putting it out. That's the normal shape of an incident: paging is nearly instant, diagnosis is where the clock actually runs.

What actually blew up the CPUs

The rule's regular expression contained a nested pattern that a backtracking regex engine — the kind most engines use by default, with no guaranteed upper bound on matching time — can turn into an exponential-time search on certain inputs. The specific fragment Cloudflare's postmortem singled out as the culprit is short enough to show in full:

.*(?:.*=.*)

/* Two unbounded ".*" wildcards, one nested inside a group that
   also contains an unbounded wildcard on each side of "=". For
   many inputs, there are an enormous number of ways to split the
   string across those wildcards and still fail to match — and a
   backtracking engine tries a huge fraction of them before giving
   up. Cloudflare's own numbers: a 20-character input could take
   the engine more than 555 steps to reject. Longer, adversarial-
   looking inputs made that number explode further, pinning a CPU
   core at 100% per request. */

This class of bug has a name — catastrophic backtracking — and it's a known hazard of any regex containing nested or adjacent unbounded quantifiers over overlapping character classes. It's not exotic; it's one of the most common ways for a regex to go from "correct" to "correct, but computationally explosive" without changing what it matches. What made this instance a global outage rather than a slow request on one server is the deployment mechanism described above: the rule reached every edge machine within the same few minutes, so every machine started burning CPU on the same pathological pattern at once. Cloudflare's postmortem also disclosed a second, compounding fact: a safeguard that limited how much CPU a single WAF rule was allowed to consume had been inadvertently removed in an earlier, unrelated change, sometime before this incident — so nothing caught the runaway regex before it took the CPU to 100%. A single bug plus a silently-missing safety net is a very common shape for a bad-enough outage; see distributed systems reliability fundamentals for why single points of failure so rarely act alone.

The fix, and the five commitments Cloudflare put in writing

☺ Like you're 10: Cloudflare didn't just say "sorry, fixed it" — it wrote down a specific list of promises, each with its own deadline, for anyone to check back on later.

The postmortem didn't stop at explaining the bug. It closed with a list of concrete engineering commitments — the same "action items with an owner and a due date" discipline covered in postmortems & blameless culture, except these owners and dates were published where any reader could later check whether they'd actually happened:

⚠ Don't copy the instant-global-deploy, copy the guardrail that replaced it

The part of this story that reads as reckless in hindsight — "one change, deployed to the entire fleet, in seconds, with no canary" — wasn't negligence; it was a real trade-off Cloudflare had made deliberately, because a WAF rule sometimes needs to block an active attack everywhere, immediately, or it isn't doing its job. The lesson isn't "never deploy fast." It's that a fast, global deployment path needs its own safety net — CPU limits, complexity-bounded regex, a kill switch that's fast in the other direction too — sized for the blast radius it's capable of, not borrowed from the safety net built for the slow, staged path next to it.

What changes when the postmortem is public, not just internal

☺ Like you're 10: Writing something down for your own team is one level of honest. Writing the same thing down for strangers who will fact-check you is a much higher level.

An internal postmortem, covered in full in postmortems & blameless culture, is already supposed to be blameless, precise, and timestamped. Publishing that document externally adds pressures an internal-only version never faces:

◆ Key idea

A postmortem written only for people who already trust you doesn't have to work very hard. A postmortem written for people deciding whether to trust you has to be specific enough, honest enough, and technically defensible enough that a skeptical outsider reading it for the first time comes away more confident, not less. That's a strictly harder writing problem than the internal version — and the discipline it forces tends to raise the internal version's quality too.

Before July 2019 New WAF rule Every edge location, worldwide, instantly no staging step — this path shipped the July 2019 bug After July 2019 Ordinary rule change Staged rollout — canary regions first same discipline as a normal software deploy Active-attack rule rare, deliberate Emergency global path — preserved on purpose now paired with the CPU-limit & regex-engine fixes

Not a one-off: the practice across six years

☺ Like you're 10: Cloudflare kept doing this for years afterward — and later used its own worst day as the yardstick for how bad a new worst day was.

A single detailed postmortem could be a one-time PR exercise. Cloudflare's blog carries a running, dated archive of these reports stretching across years, covering incidents that range from embarrassing to merely inconvenient — including ones where the honest root cause reflects poorly on Cloudflare's own redundancy design, not just an unlucky external event. A November 2023 postmortem, for instance, disclosed a multi-day control-plane and analytics outage after a core data-center failure exposed a redundant-failover path that didn't work as designed — a considerably less flattering story than "we found the bug and fixed it in 27 minutes," published with the same level of named detail.

The clearest evidence that this is a sustained practice, not a single good day, came on November 18, 2025, when a database permissions change caused a configuration file feeding Cloudflare's Bot Management system to double in size, exceed an internal limit, and take down the core proxy across the network for roughly six hours — by Cloudflare's own account, a considerably larger disruption than 2019. CEO Matthew Prince personally signed that postmortem too, and in it, measured the new incident against the one this page is built around, calling it plainly "Cloudflare's worst outage since 2019." That's a company using its own six-year-old public postmortem as the benchmark for grading itself on a bad day — a comparison that's only possible because the 2019 report was detailed, dated, and never quietly memory-holed.

Jul 2019 WAF regex CPU exhaustion, 27 min impact Nov 2023 data-center failure, failover didn't work as designed — multi-day Jun 2025 service outage — postmortem noted externally for its clarity Nov 2025 Bot Management config file doubles — ~6 hrs, "worst since 2019" The 2019 report is precise and permanent enough that Cloudflare later graded itself against it

What to steal for your own postmortem practice

☺ Like you're 10: You don't need a global network to copy the habits — write it down like a stranger will read it, even if only your own team ever does.

Honest caveats

☺ Like you're 10: Cloudflare gets to pick what goes in the report and how it's worded — so read it as a very good, very detailed story the company chose to tell, not as neutral, independently checked fact.

🦊 Foxy's stakeout · 15 min

Pull up the last postmortem your own team wrote — or, if you don't have one, imagine the last real incident you were part of. Rewrite just its timeline section as if a skeptical stranger, with no context and no reason to trust you, were going to read it tomorrow. Does every line have a UTC timestamp? Does the root-cause section name a system or a process, never a person? Would a reader who doesn't already work with you understand exactly what broke and why, without asking a single follow-up question? That gap — between what you wrote for your own team and what would survive a stranger's read — is exactly the discipline a public postmortem forces, whether or not you ever intend to publish one.

🎬 At the Reliability Watch
🦊

Foxy: Twenty-seven minutes of impact, and Cloudflare published the actual regex. The actual one. Not "a rule had an issue."

🐦

Pip the Hummingbird: Three minutes to first page, though — that part I care about. Fast detection is the difference between a bad five minutes and a bad afternoon.

🐘

Ellie the Elephant: The part that got me was the missing CPU-usage guardrail. It had been removed earlier, quietly, and nobody's telemetry flagged that a safety net had gone missing until it was needed and wasn't there.

🐢

Timmy the Turtle: Which is exactly why you verify your safety nets are still attached, not just that they existed once. "We had a CPU limit" and "we have a CPU limit right now" are different claims.

🦫

Benny the Beaver: I'll say the scary part out loud: their WAF deploy path pushed a change to every machine on Earth in the time it takes me to get coffee. No staging, no canary.

🦊

Foxy: And they said so, in writing, publicly — then fixed it. That's the whole case study. Not "nothing ever breaks here," but "when it breaks, here's exactly how, and here's the date we said we'd stop it happening that way again."

Where this connects in the course

☺ Like you're 10: This one incident touches several other lessons — read whichever one matches what you're building next.

The blameless-writing discipline this whole page assumes is covered in full in postmortems & blameless culture — read that first if you haven't. The detection-and-paging mechanics behind that three-minute first alert are monitoring & observability and, in more depth, alert design & alert fatigue. The organizational question of what it costs — and what it buys — to make reliability failures a matter of public record is organizational impact of SRE. And for a worked, fictional incident built to practice the same timeline-and-root-cause discipline without needing a real company's outage to learn from, see this course's own case study: an outage post-mortem. For other real, publicly documented incidents covered elsewhere in this course, see Meta's 2021 BGP outage, Slack's January 2021 outage, the 2017 AWS S3 outage, and — for where the blameless-postmortem idea itself came from before Cloudflare ever published one — Etsy & the origin of blameless postmortems.

🐢 Timmy's checkpoint

1. What triggered the July 2, 2019 outage, and why did it reach Cloudflare's entire edge network within minutes rather than staying contained to one region? 2. What is catastrophic backtracking, and what made this particular regex vulnerable to it? 3. Name three of the concrete commitments Cloudflare published at the end of its postmortem. 4. Give two specific things that change about a postmortem's rigor when it's written for external publication instead of an internal audience only. 5. What later incident did Cloudflare's own CEO explicitly measure against the July 2019 outage, and in what words? 6. Why should you treat every number on this page as "Cloudflare has said," not as independently audited fact?

Check your answers
  1. A newly deployed WAF managed rule for XSS detection contained a regex vulnerable to catastrophic backtracking. It reached the entire edge network within minutes because WAF rules, unlike Cloudflare's normal staged software deploys, shipped globally and instantly at the time — a deliberate design choice for responding to active attacks quickly, which became the mechanism that turned one bad rule into a global outage.
  2. Catastrophic backtracking is when a backtracking regex engine, faced with nested or adjacent unbounded quantifiers over overlapping patterns, tries an exponentially large number of ways to match or reject an input. The fragment .*(?:.*=.*) had two unbounded wildcards nested around another unbounded pattern, and Cloudflare's own numbers showed a 20-character input could take over 555 steps to reject — with worse inputs scaling far higher, consuming a full CPU core.
  3. Any three of: re-introduce the removed CPU-usage protection, manually audit all 3,868 existing WAF rules, add regex performance profiling to the test suite, move toward a regex engine with a runtime guarantee (such as RE2 or a Rust-based engine), stage WAF rollouts like ordinary software deploys while preserving an emergency global path, build a way to take the Cloudflare dashboard/API off Cloudflare's own edge, and automate status-page updates.
  4. Any two of: the timeline and technical claims have to survive scrutiny from a skeptical outside technical readership rather than just an internal team; the document becomes a permanent, dated, citable public record that can't be quietly edited or forgotten; the blameless "system, not person" discipline is tested publicly, at a scale that would genuinely harm a named individual if broken; and the report becomes a real trust signal for customers deciding whether to rely on the company.
  5. The November 18, 2025 outage, caused by a database permissions change that doubled a Bot Management configuration file and took down the core proxy for roughly six hours. Cloudflare's CEO, signing that postmortem personally, called it "Cloudflare's worst outage since 2019" — directly measuring the new incident against the one covered on this page.
  6. Because every fact on this page is drawn from Cloudflare's own blog posts, written and reviewed by Cloudflare before publication — accurate and detailed by the standards of self-reporting, but not the same as a third-party audit, and still shaped by whatever legal and communications review a company applies to any public statement about its own failures.