Live data from Hacker News

Cloudflare outage on November 18, 2025 post mortem

blog.cloudflare.com

931–940 of 953 posts

Re: Cloudflare outage on November 18, 2025 post mortem

#931

Earlier quoted context omitted.

> `slice[i]` is just sugar for `slice.get(i).unwrap()`. And whether it's a "local" invariant or not is orthogonal. And `unwrap()` does not "require lying about invariants across your API surface." It's not orthogonal. `Result` isn't a local invariant, and yes, `.unwrap()` does require lying. If your code depends on an API that can fail, and you cannot handle that failure locally (`.unwrap()` is not handling it), then…

> No, it's a principled position. Correct code doesn't `.unwrap()`, but code that hides failure cases -- or foists invariant enforcement onto programmers remembering not to screw up -- does. I don't think you understand what an internal runtime invariant is. Either way, I don't know of any widespread libraries (in any language) that follow this "principled" position. That makes it de facto extreme. > I've built and w…

> You use `unwrap()` when you know the failure cannot happen.

That’s an invariant meant to be expressed by your type system — and it is.

You’ve failed to model your invariants in your API — and thus the type system — if you ever reach a point where an engineer has to manually assess and assert whether “cannot” applies.

You will get it wrong. That is bad code.

Re: Cloudflare outage on November 18, 2025 post mortem

#932
post #897

Earlier quoted context omitted.

> maybe briefly booting up another 100k isn’t going to be the end of the world Cloudflare doesn’t run in AWS. They are a cloud provider themselves and mostly run on bare metal. Where would these extra 100k physical servers come from?

From their desire to representatively test before they deploy to production? Doing stuff at scale doesn’t suddenly mean you skip testing. And just because they host stuff themselves doesn’t mean they couldn’t run on the cloud if they needed to.

Cloudflare infra costs are probably 300 mil+ usd. Their gaap profit is negative, their non gaap income is less than their infra expenses. Can you imagine how much they would have to charge more or spend more if they had to duplicate or simulate their production environment in staging and for each of the 100s deployments they probably do a day?

Their main cost of revenue is these infra costs.

Re: Cloudflare outage on November 18, 2025 post mortem

#933
post #906

Earlier quoted context omitted.

In the early 2000s when Google explained how they achieved their (already back then) awesome reliability, ie assuming that any software and hardware will eventually fail, and that they designed everything with the idea that everything was faulty, there were some people who couldn't get it, who would still bring the argument that "yeah but today with modern raid..." People here chatting about unwrap remind me of them…

Assuming software and people will fail is exactly what not using unwrap is about. If you depend on engineers not fucking up, you will fail. Using unwrap is assuming humans won’t get human-enforced invariants wrong. They will. They did here. As someone that works in formal verification of crypto systems, watching people like yourself advocate for hope-and-prayer development methodology is astonishing. However, I under…

I do not understand what gave you the impression that I was advocating for "hope and prayers". I'm advocating for not relying on one level of abstraction to be flawless so we can build a perfect logic on top of it. I'm advocating for not handling everything in a single layer. That FL2 program at cloudflare encountered an error condition and it bailed out and that's fine. What is not fine is that the supervisor did not fail open.

The oposing views here are not "hope and prayers" vs "good engineering", it's assuming things will fail at every stage vs assuming one can build a layer of abstraction that is flawless, on top of which we can build.

Resilient systems trump "correct" systems, and I would pick a system designed under the assumption that fake errors will be injected regularly, that process will be killed at random, that entire rack of machines will be unplugged at random at any time, that whole datacenters will be put off grid for fun, over a system that's been "proven correct", any day. I though it was common knowledge.

Of coursre I'm not arguing against proving that a software is correct. I would actually argue that some formal methods would come handy to model these kind of systemic failures and reveal the worste cases with largest blast radius.

But considering the case at hand, the code for that FL2 bot had an assertion regarding the size of received data and that was a valid assertion, and the process decided to panic, and that was the right decision. What was not right was the lack of instrumentation that should have made these failures obvious, and the fact that the user queries failed when that non-essential bot failed, instead of bypassing that bot.

Re: Cloudflare outage on November 18, 2025 post mortem

#934

Earlier quoted context omitted.

panic is the exceptional event. It so happens that rust doesn't print a stacktrace in release unless configured to do so. Similarly, capturing a stack trace in a error type (within a Result for example) is perfectly possible. But this is a choice left to the programmer, because capturing a trace is not cheap.

There's clearly a big gap in how things are done in practice. You wouldn't see anyone call System.exit in a managed language if a data file was bigger than expected. You'd always get an exception. I used to be an SRE at Google. Back then we also had big outages caused by bad data files pushed to prod. It's a common enough issue so I really sympathize with Cloudflare, it's not nice to be on call for issues like that.…

A panic in Rust is the same as an exception in C++. You can catch it all the same.

https://doc.rust-lang.org/std/panic/index.html

An uncaught exception in C++ or an uncaught panic in Rust terminates the program. The unwinding is the same mechanism. I think the implementation is what comes with LLVM, but I haven't checked.

I was also a Google SRE, and I liked the stacktrace facilities so much that I got permission to open source a library inspired from it: https://github.com/bombela/backward-cpp (I know I am not doing a great job maintaining it)

At Uber I implemented a similar stackrace introspection for RPC tasks via HTTP for Go services.

You can also catch a Go panic. Which we did in our RPC library at Uber.

It would be great for all of that to somehow come ready made though. A sort of flag "this program is a service, turn on all the good diagnostics, here is my main loop".

Re: Cloudflare outage on November 18, 2025 post mortem

#935
post #178

Earlier quoted context omitted.

How so? An exception is a value that's given the closest, conceptually appropriate, point that was decided to handle the value, allowing you to keep your "happy path" as clean code, and your "exceptional circumstances" path at the level of abstraction that makes sense. It's way less book-keeping with exceptions, since you, intentionally, don't have to write code for that exceptional behavior, except where it makes se…

> don't have to write code for that exceptional behavior, except where it makes sense to. The great Raymond Chen wrote an excellent blog post on how this isn't really true, and how exceptions can lure programmers into mistakenly thinking they can just forget about failure cases. Cleaner, more elegant, and harder to recognize https://devblogs.microsoft.com/oldnewthing/20050114-00/?p=36... (ctrl-f for taskbar to skip t…

I mean his post seems obviously wrong or ill chosen to support his point. Surely you can see that an inner implementation of the icon class requiring a special hidden order on which properties to set first can happen in any language and also really isn't related at all to whether you use try-catch handling or error values as return codes.

What he seems to be saying is that "obviously in C I would be checking the icon handle for being non-null so clearly error value handling is superior" but this is only obvious to someone knowing the API and checking values for validity has to be done in exception based code too. It's just that exception based code doesn't pretend that it cannot panic somewhere where you don't know. The default, better assumption for programming is that you don't know what this code is doing but it should just work. Unchecked exception handling is the best way to fit that paradigm, you should not have to care about every single line and what it does and constantly sort of almost obsessively check error values of all the APIs you ever use to have this false hope that it cannot panic because you did your duty. No, it can still panic and all this error checking is not helping you program better or more clearly or faster. It swamps the code with so many extra lines that it's practically double the size. All this makes it less clear and that is also what his post shows.

Re: Cloudflare outage on November 18, 2025 post mortem

#936
post #170

Earlier quoted context omitted.

right and if the language designers named it UNWRAP_OR_PANIC() then people would rightfully be asking why on earth we can't just use a try-catch around code and have an easier life

...and you can? try-catch is usually less ergonomic than the various ways you can inspect a Result. try { data = some_sketchy_function(); } catch (e) { handle the error; } vs result = some_sketchy_function(); if let Err(e) = result { handle the error; } Or better yet, compare the problematic cases where the error isn't handled: data = some_sketchy_function(); vs data = some_sketchy_function().UNWRAP_OR_PANIC(); In th…

it's practically always the case that you use a try-catch for more than just one source / line of code. I mean except for database/network calls I don't think I even remember a single case where I ever used a try-catch just for a single line of code. The subtle problems come from errors handling via values. You check but do you check perfectly? What happens when APIs change and the underlying functions add more error cases, then you constantly have more work to do. Nonstop constant error checking that you don't care about. This is exactly where humans are terrible: Really important work that is drudgery and where if you ever mess up once, you fail in very painful ways. Exception handling solves all of this, it fits how humans should be working and it fits the underlying hardware reality as well: We are big picture, we should not be designing languages for describing logic that force us to do drudgery work constantly and care about implementation details of every single thing we call.

Re: Cloudflare outage on November 18, 2025 post mortem

#937
Attempt to reproduce the Cloudflare 2025-11-18 outage.

Cloudflare's incident report is written clearly and explicitly, so based on my own understanding, I’m going to try reproducing this outage. Already completed:

CK cluster Permission change triggering data doubling Cache propagation Unaffected proxy services Proxy services with bot score errors

TODO:

unwrap panic during pre-allocation of cache Full demonstration of the entire outage process

https://github.com/Laotree/reproduce_cf20251118

Re: Cloudflare outage on November 18, 2025 post mortem

#938

Earlier quoted context omitted.

How do you manage to do this?

There's a crate that prevents linking panic symbol in the final stage of the executable generation, forcing it to be undefined symbol, so while it is hard to find out where the panic is, it effectively requires me to inspect throughout the code to find out. Sometimes I have to disassemble the object file to see this

it's not the `no_panic` crate by david tolnay, is it?

Re: Cloudflare outage on November 18, 2025 post mortem

#939

Earlier quoted context omitted.

> don't have to write code for that exceptional behavior, except where it makes sense to. The great Raymond Chen wrote an excellent blog post on how this isn't really true, and how exceptions can lure programmers into mistakenly thinking they can just forget about failure cases. Cleaner, more elegant, and harder to recognize https://devblogs.microsoft.com/oldnewthing/20050114-00/?p=36... (ctrl-f for taskbar to skip t…

I mean his post seems obviously wrong or ill chosen to support his point. Surely you can see that an inner implementation of the icon class requiring a special hidden order on which properties to set first can happen in any language and also really isn't related at all to whether you use try-catch handling or error values as return codes. What he seems to be saying is that "obviously in C I would be checking the icon…

> Surely you can see that an inner implementation of the icon class requiring a special hidden order

In practice, programmers don't find it easy to keep in mind that certain functions might throw. This is a real problem with unchecked exceptions and with C-style error codes that sloppy programmers might ignore entirely.

> [...] on which properties to set first can happen in any language

A carefully designed library using a statically typed functional language, especially a pure functional language, might sometimes be able to eliminate such hidden ordering bugs.

Rust used to have a feature to help the compiler detect invalid ordering of imperative operations, called typestates. This feature has since been mostly removed, though, as it saw little use. [0]

> isn't related at all to whether you use try-catch handling or error values as return codes

I guess Chen is assuming a reasonably diligent programmer who makes a habit of never discarding status/error values returned by functions. C++'s [[nodiscard]] can help ensure this.

(Of course, outside of C++, those aren't the only options. Idiomatic Haskell and Zig code forces the programmer to explicitly handle the possibility of an error. Same goes for Java's checked exceptions.)

> What he seems to be saying is that "obviously in C I would be checking the icon handle for being non-null so clearly error value handling is superior"

I don't think he's exactly arguing for the C-style approach, he's more just criticizing exceptions, especially unchecked exceptions. I agree the C-style approach has considerable problems.

> It's just that exception based code doesn't pretend that it cannot panic somewhere where you don't know.

With checked exceptions, you know precisely which operations can throw.

> Unchecked exception handling is the best way to fit that paradigm, you should not have to care about every single line and what it does and constantly sort of almost obsessively check error values of all the APIs you ever use to have this false hope that it cannot panic because you did your duty

You do need to care about every line, or your plausible-looking code is likely to misbehave when an exception occurs, as Chen's post demonstrates. Unchecked exceptions deprive the compiler of the ability to ensure good exception-handling coverage. There is no error-handling model that allows to programmer to write good code by pretending errors won't arise.

(I presume that by panic you mean throw an unchecked exception.)

[0] https://cliffle.com/blog/rust-typestate/

Re: Cloudflare outage on November 18, 2025 post mortem

#940

Earlier quoted context omitted.

This is assuming that the process could have done anything sensible while it had the malformed feature file. It might be in this case that this was one configuration file of several and maybe the program could have been built to run with some defaults when it finds this specific configuration invalid, but in the general case, if a program expects a configuration file and can't do anything without it, panicking is a n…

I don't know too much about how the feature file distribution works but in the event of failure to read a new file, wouldn't logging the failure and sticking with the previous version of the file be preferable?

Or even truncating the features to their limit and alerting through logs that there is likely performance degradation in their Bot Management.

I'm really confused how so many people are finding it acceptable to bring down your entire reverse-proxy because the length of feature sets for the ML model in one of your components was longer than expected.

Post reply on HN