Rewriting Bun in Rust
106 points by mitsuhiko
106 points by mitsuhiko
I actually don't have any personal criticisms of Jarred.
I would hate to read a post where Kelley had some personal criticisms.
I don’t get why people write something like this and then tack on a sentence like that at the end as if it changes something.
Does anyone think if Jarred reads this he’s going to say “yeah, I feel fine, this isn’t personal, you didn’t say anything insulting about me, or my motives, or my writing?”
Sometimes, you insult people. I try not do it too much, but it happens. And when it does, I either apologize or I own it. Owning it means saying “yeah, I implied you’re a liar, and I stand by it.”
Like our great poet said:
now let me say I'm the biggest hater I hate the way that you walk, the way that you talk, I hate the way that you dress
P.S. I’m not saying Kelley shouldn’t criticize Jarred. Maybe he deserves it. It’s the half-walking it back bit that I think is a mistake. An understandable mistake: it feels nice to say “it isn’t personal”, I understand why someone would want to say it. It just doesn’t make a lot of sense.
Yeah, that part threw me for a loop. I guess technically you can criticize someone’s coding, management style, ideological dependence on VC money, and quality of relationships without it being personal, but come on.
Somebody who works 90 hours a week probably doesn't have that much personal other than these work related qualities.
I didn't find it especially insulting?
I see it as quite a healthy attitude, particularly for young people and students. This is the best way to level up and learn new things...
But having graduated from the Thiel Fellowship school of thought rather than university, he was essentially groomed from a young age into uncritically embracing the Silicon Valley mindset, and he took venture capital.
It sounded to me like Kelley saying "he was set up for failure from the start". It's easy to blame people for their actions, but it's a lot harder and a lot more interesting to try to understand why they choose those actions. Usually people choose to do something because it seems like the best option they have. This is why perspective and experience are important for making good decisions on the large scale, it gives you a broad set of choices and a deep understanding of how they will turn out. From the sound of it, Jarred never got the opportunity to develop that, and was probably actively told not to.
People with a lot less insight to the inner workings of Bun have been saying it would turn out the way that it has for years, because of the choices Jarred made.
IMO: I don't think it's polite to publicly psychoanalyze someone in this way. Calling someone "groomed" because they moved away from your programming language is wildly inappropriate.
"Groomed" in this context reads like "groomed for success" or "groomed for politics", which is what the Thiel Fellowship literally does. It takes a small subset of university aged young people and tells them that they don't need a traditional education, they just need some startup capital, some advice, and success will flow from there. This is Thiel's world view and political position, he is trying to essentially make and appoint industry leaders who have favourable views of him and his politics.
I don't think it reads like that at all.
But having graduated from the Thiel Fellowship school of thought rather than university, he was essentially groomed from a young age into uncritically embracing the Silicon Valley mindset, and he took venture capital.
Fair, modulo a whole sub-argument we could have about intent but I'm not really feeling it rn, but I'm not sure what the alternative is. Don't talk about it at all, even though it obviously has affected Zig a lot and people are asking about it? Issue a dry-as-dust statement from The Zig Foundation to The Subsidiary Of Anthropic Formerly Known As Bun saying how happy they are for their new corporate overlords?
There is no reading of “groomed” and “uncritically embracing” that isn’t emotionally charged. The post would have been better without these kinds of side-swipes; they make it much easier to dismiss the writing as reactive rather than carefully considered.
I honestly do appreciate and respect that Zig-as-an-entity is not beholden to dry corpo-speak due to their structure, and I don't want to tone-police, but I think you can communicate "we appreciated his support, our values were not aligned, we wish him the best" without the condescension in "he was manipulated into his beliefs."
I think it is reductive to peg this response to Bun "moving away from [Zig]". I don't mean to imply the response is perfect, but your framing here essentially implies that any critique of what happened is doomed from the start ("they're just upset that they got dumped, lmao" sort of vibes IMO).
I also don't think politeness has to be everyone's goal. The PR-managed blog post from Anthropic may be infinitely more "polite", but that doesn't really mean anything. It wasn't written to "be polite", it simply had to be polite to have the intended effect. It is a cover, a smokescreen.
If all of that is true, would we expect Bun's UAF & leak rate to stay the same post-rewrite? Was Jarred setup for failure by "Silicon Valley VC Culture", or by the programming language he decided to start this project in?
What failure are we even talking about, writing systems code w/o blowing your foot off? Jarred practically succeeded in every goal he had.
This is one of the most interesting moves in software in years, and more words are spent on VCs than on Rust here.
Moreover, it's hard for me to reconcile "as the Internet stops arguing" with the Zig Evangelism Strike Force. But, I guess there's no such thing as bad publicity.
I have to admit I never found Zig very interesting on its technical merits - I'm thoroughly memory safety pilled and I've found Rust a very comfortable and productive language for nearly 10 years now. So I never really paid that much attention to what was happening in Zig.
But as time has marched on I find myself quite a bit more interested in Zig on the social merits, and let down by Rust in that respect too. So kudos to Andrew for consistently coming across as a decent and thoughtful leader. I might just have to find some project to take Zig for a spin with now and spend some time getting familiar with its ideas.
I never found Zig very interesting on its technical merits
This is surprising to read! From the language design perspective, Zig is well worth studying in detail. While we had comptime in D before, Zig's novelty is demonstrating that you don't need other features, (in particular, that you don't need to abstract over syntax).
Of course, interesting != practical, whether you should use Zig is an entirely different question from it being worthy of a study!
in particular, that you don't need to abstract over syntax
What do you mean by this? One potential interpretation of this makes it sound like DSLs are possible in Zig, but they aren't in the same way as in other languages with macros, and you're super familiar with macros, so I'm guessing that's not what you meant.
I don't understand this as thoroughly as I'd like, so I am not good at explaining this yet, my current best attempt is at https://matklad.github.io/2025/04/19/things-zig-comptime-wont-do.html
Perhaps it's better to give litmus test examples.
In Rust, when you slap #[derive(MetaFn)] on a struct, the MetaFn gets access to the syntax of the struct. It sees a difference between Vec and std::vec::Vec field types. In Zig, an fn MetaFn(T: type) would get access to the resolved type. It doesn't see a syntactic expression that resolved to a type, it sees the actual type.
Conversely, derive in Rust works by essentially injecting new source code into compilation, you manufacture syntax of expressions. In contrast, in Zig you can't do that. You can't even inject new declarations into compilation. All you can do is to write a function which can get comptime-specialized/partially evaluated.
While comptime is powerful, it doesn't allow to read or write "syntax", only the stuff that syntax evaluates to. Zig doesn't have anything similar to https://tour.dlang.org/tour/en/gems/string-mixins. Likewise, Zig doesn't have a way to invent custom syntax, like macro-by-example in Rust.
It is useful to contrast with Lisp. Lisp is all powerful, because lisp programs can reflect on their own source code, and transform it into different source code. A Lisp program is a compiler from Program Specific Language to core forms. So you could do literally anything in Lisp. But then it's kinda cognitively hard, as each program is its own language. You start Lisp programming with defining your grammar.
Zig is much more restricted than that, the grammar is fixed, you can'd do your own if or some such. Surprisingly, the power that Zig has is exactly enough for any tasks you want to do, excepting literal embedded DSLs. Even there, you actually can do something like fn eval_python(comptime text: []const u8, runtime_arguments: anytype), it's just that your eval would be written as an interpreter, and then partially applied to text
What are your thoughts on the error handling of comptime? Rust macros are famously hard to get good error messages out of, and comptime seems like it might be even worse.
I only work with Zig code I am very familiar with, so I don't much valuable experience here. The error messages feel clear enough to me, they are basically stack traces through imperative comptime code. I think I like them more than, e.g., Rust trait solving "traces" through prolog-ish comptime code, and more than macro stack traces through code I didn't write. Though, this is apples to oranges, and I might be wrong as well as right, fairly uncertain here. But, e.g., for const fn, I am fairly certain that just trying to call it and bailing with stack trace would work better, in terms of error messages, than stuffing const-ability into the trait system (https://github.com/rust-lang/rfcs/pull/3762#discussion_r2293116910).
But the happy path here is more consequential than the sad path. It is impossible to say, at a glance, what interface is required of comptime parameters. Again, this doesn't affect me in our closed-world low abstraction code base, but I imagine this to get trickier if people try to string together highly abstract libraries.
I'll add a +1 to matklad's comment. Most of the time a comptime error looks exactly like the runtime error you would get if comptime didn't exist. You can even throw some comptime printlns in there to help debug. I find it worlds easier than rust macros or even trait resolution errors. I dread having to write rust macros, but for the same tasks I reach for comptime without hesitation.
Also the vast majority of the uses of comptime I encounter fall either into:
fn sort(comptime T: type, items: []T, less_than: fn(T, T) bool) so the interface is clearly specified.I actually suspect that you could make a language with a slightly more restricted comptime that allowed generic checking for both of those classes. I've been noodling on it from time to time for https://github.com/jamii/zest.
that you don't need to abstract over syntax
You don't need a lot of stuff in programming. You technically don't need a programming language. That doesn't nullify the value of abstraction. Abstraction is a fundamental concept in computing.
Zig's novelty is definitely not "you don't need other features" - LISP, Forth, and many many other demonstrate the same. Far from novel.
While we had comptime in D before, Zig's novelty is demonstrating that you don't need other features, (in particular, that you don't need to abstract over syntax).
Can you elaborate on how it's being demonstrated? I think comptime is very interesting. But, from afar, it doesn't feel like it gets as much development/attention as I would hope. The news I generally see coming out of Zig seems to be about mechanical stuff.
I had thought of comptime as an alternative to adding first-class constructs in the language (classes, traits, interfaces, macros, etc...). So, it seems to me, the most interesting part is leaning into that and seeing how things really work out in practice. Like, how does the programmer and tooling and whatever work if those constructs are not part of the language? Can you really reason about comptime code very well? Does a refactoring tool have to throw up its hands when it encounters some comptime magic? Do people build libraries of comptime code that effectively recreate these common language constructs? Does a programmer have to learn a new way to do the same thing for every project they work on? And, so on...
Perhaps I am just not thinking about comptime in the right way...
The way I think about comptime, which is obviously the correct way ;) , is coming from the other direction.
You start out with a dynamic programming language where every value has a concrete type, and types are themselves values. Like Julia. You can do arbitrarily fun metaprogramming stuff - arbitrary reflection, create types on the fly, etc.
Then you figure out which subset of the language you can compile efficiently. It's a pretty small crappy subset. Every expression has to always produce a value of a single concrete type, and types can't be used a values, and you can't reflect on types. But it is easy to compile.
Then you begin to realize that if you compile a separate version of each function for each combination of parameter types, a lot of the metaprogramming only depended on the types and you can evaluate that away at compile-time, leaving you with just the easy-to-compile subset with some embedded values.
This is basically what Julia does too - Julia and Zig actually are quite similar languages. The big divide is just that Zig always wants to be able to compile away the dynamic part of the language, whereas Julia is happy to regularly bail back to the dynamic side if it can't compile everything away.
Can you elaborate on how it's being demonstrated?
Zig is very minimal and very expressive.
Minimal: no type reference syntax, no type declaration syntax, no pattern syntax, no static item syntax, no generics, no templates, no literal suffixes, no keyword arguments, no default arguments. No cfg flags, no defines, no traits, no macros, no constructors, no mixins, no closures, no RTTI
Expressive: xshell and xflags are significantly easier to implement and use in Zig than in Rust, the "recursively walk the type and do something" code is trivial, and trivially upgradable to runtime. So far, I haven't seen anything which I can't express in Zig directly, without translating what I want to do to language-specific idioms.
Expressive: it is a DSL for machine code. With ad hoc type specialization, comptime control flow partial evaluation (inline for), and pretty direct access to the underlying ISA, its similarly possible to rather directly convince the compiler to emit code you need.
Same here as well ironically, I like the safety features of Rust so much more and I don't have anything I'd use Zig for, but just the baller moves of ZSF are interesting enough for me to learn and use Zig.
"Memory-safety-pilled" is a great way to describe me as well, but Zig is a fascinating programming language that takes some wild design ideas and seems to actually make them work well in practice.
I wonder how much of the Zig vs Rust leadership delta is due intent or idology, and how much of it is just "a good, small team lead by a benevolent dictator(?)" vs "growing way too fast and operating by committee".
I'm thoroughly memory safety pilled
A lot of people using Zig and interacting with the Zig community seem to become engineering pilled. That's a way more potent pill.
I have always found that zig was pretty interesting to me, but I really does not like some of its syntax so I never really wrote that much of it. On the other hand I have heard loads of people saying the same about Rust so maybe I should just get started at some point.
I like Zig as a language, and I respect a lot of things about Andrew Kelley, but this post felt really mean-spirited and immature.
I read the Bun post, and it didn't read to me as an attack on Zig at all. It felt like Sumner admitted places where Bun used Zig poorly, and he said that Bun as a project has unusual requirements. I didn't see any attacks on Zig or even subtle digs, though I admit that I haven't followed the Bun drama closely, so maybe there were subtle digs I can't perceive.
Kelley's post, though, was just gloves-off attacking Sumner on a personal level. Even the "nice" things were backhanded compliments:
I described [Sumner] as someone who had strong "beginner energy". That is, he moved fast and tried a lot of different stuff, jumping head first into problems that he was not yet equipped to solve, leading to mediocre outcomes in terms of engineering, but learning a whole heck of a lot in the process.
[Sumner] was essentially groomed from a young age into uncritically embracing the Silicon Valley mindset, and he took venture capital.
The grapevine was large and healthy and full of juicy grapes, and all those grapes contained the juice of the same message: Jarred was a stinky manager. Poor communication, unrealistic expectations, low empathy, no experience. Just a total shit show, from an employment perspective.
We became increasingly horrified at the programming practices we saw in Bun's codebase. Hacks on top of hacks. Abuse of assertions. Most of all, recklessly speeding past feature after feature with very little time taken for reflection and elimination of bugs and technical debt. Jarred was already writing slop well before he had access to LLMs.
It makes it all the more absurd that Kelley's post ends with:
I actually don't have any personal criticisms of Jarred.
I can understand airing dirty laundry when the other side gets ugly, but this seems entirely one-sided. I don't see Sumner attacking Zig at all, much less Kelley personally.
I also think mudslinging like this erodes trust in the people that remain in the Zig community. As a manager, I've had to fire developers who wrote sloppy code, but I don't turn around to other developers on my team and say, "I fired that person because they're a total moron." I keep it professional and respectful because I want my current teammates to know that if our relationship ends, I'm going to talk respectfully about them as well.
Even the "nice" things were backhanded compliments
The first part about Jarred learning systems programming when he was a Zig beginner is not backhanded. It's how everybody starts, and it's genuinely cool to see people get their bearings and start climbing the competence scale to do things they were never able to do before. I went through this same exact experience myself throughout my involvement in the Zig community.
It's less cool to see somebody interrupt their journey too early to get VC money and a ton of responsibilities they are not yet well equipped to handle, especially when failing to do so has the side effect of hurting other people (as mentioned in my other comment).
"I fired that person because they're a total moron." I keep it professional and respectful because I want my current teammates to know that if our relationship ends, I'm going to talk respectfully about them as well.
That's a perfectly fine perspective, but it's not the relationship we had with Bun. We didn't employ Jarred, we were (and are) peers in an ecosystem, we had misaligned incentives, and we hoped that Bun would not trample the flowers in the Zig ecosystem in order to storm towards the money bag, especially considering that there was already a very well marked road towards it that required no trampling whatsoever.
If you feel that US-style 'professionalism' should take precedence over telling the story (as biased our perspective might be), then IMO you're cheering for more of the rot that makes our industry pump out more and more user hostile software. This stuff should be in the sun in my opinion.
Even the "nice" things were backhanded compliments
The first part about Jarred learning systems programming when he was a Zig beginner is not backhanded. It's how everybody starts, and it's genuinely cool to see people get their bearings and start climbing the competence scale to do things they were never able to do before. I went through this same exact experience myself throughout my involvement in the Zig community.
If it's how everyone starts, why is it worth mentioning? Why call out "leading to mediocre outcomes in terms of engineering?"
When I talk about enthusiastic beginners, I talk about how rapidly they learn and not how crappy their early work is.
If you feel that US-style 'professionalism' should take precedence over telling the story (as biased our perspective might be), then IMO you're cheering for more of the rot that makes our industry pump out more and more user hostile software. This stuff should be in the sun in my opinion.
Can you clarify how personal attacks on Sumner are good for the industry?
I could understand if Sumner was going around abusing people and you saw it as your duty to alert people, but I'm not seeing that anywhere. He's a demanding manager, and I wouldn't want to work for him, but he also seems open about that fact in hiring.
The main beef seems to be that the Zig team thinks Sumner is subpar technically, and it's suddenly important to let everyone know now, but it wasn't important to disclose publicly when Sumner was paying the Zig team $60k/year.
Can you clarify how personal attacks on Sumner are good for the industry?
The people subject to life-changing poor management had no recourse so it's only healthy if some stuff is called out by somebody who has a platform.
I could understand if Sumner was going around abusing people and you saw it as your duty to alert people, but I'm not seeing that anywhere. He's a demanding manager, and I wouldn't want to work for him, but he also seems open about that fact in hiring.
Only focusing on this framing, and not the contents of your argument: I don't agree.
If someone is abusive, extractive, and exploitative it doesn't really enter into it whether they are honest about it or not. It is still abusive, extractive, and exploitative.
As an analogy, it seems like record labels often exploits artists who are just starting out: they praise you and float you huge advances while technically being up-front about the fact that you're essentially selling your soul to them in the event that you actually find success. Young artists looking for validation sign on anyway. Successful, slightly-older artists (Prince, Taylor Swift, Smashing Pumpkins, etc.) then try to course-correct and spend years litigating it.
I am not saying anything about this instance wrt. Bun, only that this part of your argument doesn't seem sound to me.
I think it comes down to whether you think it's inherently abusive to ask someone to work 90 hours/week. I think it can be, but it is not strictly abusive.
If someone can't get a job anywhere and you say you're going to hire them to scrub toilets, but they have to do it for 90 hours a week, yes that's abusive.
If someone has their choice of coasting at a FAANG job for $200k/yr and you tell them you'll give them 3% equity in Bun and maybe that 2% will be worth $5M in a year or two, but they have to work 90-hour weeks until exit, I don't think that's abusive. If you can get a job at Bun/Oven, you can probably get a job elsewhere, and you're choosing the longer hours in exchange for higher expected comp.
If someone has their choice of coasting at a FAANG job for $200k/yr and you tell them you'll give them 3% equity in Bun and maybe that 2% will be worth $5M in a year or two, but they have to work 90-hour weeks until exit, I don't think that's abusive. If you can get a job at Bun/Oven, you can probably get a job elsewhere, and you're choosing the longer hours in exchange for higher expected comp.
I genuinely get where you're coming from. I used to feel this way. then I burned a decade and got nowhere. I regret basically all of it. I should have coasted and focused on more meaningful parts of my life, like time with my family I can never get back.
this trade is basically "sacrifice your humanity for this lottery ticket", and it preys on youthful ambition. time is the great equalizer, and the house always wins.
I don't think I can say this better myself, so I'll just upvote and reply here (see above, @mtlynch)
To add my 2c on top though (I can't resist, I guess): I don't buy the argument that "abuse is OK if the abused already enjoy enough privilege."
It may not be the most pressing abuses to address in the system, but the argument is not any stronger because of it.
Edit: and again, I tried and want to continue to avoid judgement on the specifics in this case. I am explicitly not commenting on whether Sumner is "abusive" in this instance, only that "I could understand if Sumner was going around abusing people and you saw it as your duty to alert people" is not so simple to walk back.
It's less cool to see somebody interrupt their journey too early to get VC money and a ton of responsibilities they are not yet well equipped to handle, especially when failing to do so has the side effect of hurting other people
What does this has to do with Bun being re-written in Rust? I have no idea of Jarred's background and relation with money, maybe him taking money off the table now from VCs is perfectly valid move. Heck, Mitchell did it as well.
So he chose money now over "enlightenment" later. So what? It's not like he burned down an orphanage.
The other thing I don't quite get is why was this any of Zig's problem? ZFS famously states that donations do not buy you a seat at the table. Why Bun is so special?
It would've been great to read another technical breakdown by Matthew Lugg instead of this personal attack.
If you feel that US-style 'professionalism' should take precedence over telling the story (as biased our perspective might be), then IMO you're cheering for more of the rot that makes our industry pump out more and more user hostile software. This stuff should be in the sun in my opinion.
You can criticize someone and/or their actions without going for personal attacks. This isn't some "touchy feely Americans" thing, it's basic decency. Going for the low blows makes you look worse.
I described [Sumner] as someone who had strong "beginner energy". That is, he moved fast and tried a lot of different stuff, jumping head first into problems that he was not yet equipped to solve, leading to mediocre outcomes in terms of engineering, but learning a whole heck of a lot in the process.
Funny to call the guy that considering I'm pretty sure that's the story of Zig itself.
I like Zig as a language, and I respect a lot of things about Andrew Kelley, but this post felt really mean-spirited and immature.
I didn't read it that way, no one emerges like Athena fully competent and Andrew Kelley gave what seemed like a pretty even personal take. This might be generational but it didn't seem nearly as harsh as some of the criticism I've witnessed (and received) at workplaces over the years. Was it necessary? Maybe not. Andrew has a higher profile than a random blogger so the perception of slighting someone carries more impact than if most of us did it.
This might be generational but it didn't seem nearly as harsh as some of the criticism I've witnessed (and received) at workplaces over the years.
Was that criticism in private? In a group setting? In front of the whole company? On the open internet?
Meta comment: Merging these two stories is absolutely horrible. Is this the itention of merging stories to to take two commentary and mix all the comments and feedback together?
Agreed. I came back to read these and initially thought the post from Andrew's blog had been deleted or something.
This mostly matches the outsider perspective I had of the Bun project for the past few years, and I'm sorry to say that it heavily affected how I regarded Zig. Ghostty's reliability and performance managed to repair most of that reputational damage for me, and while I still prefer the safety rails of Rust, this blog post along with prior actions by Andrew make me reasonably confident in Zig's future. Thank you for taking the time.
C++ instead of Zig would be a reasonable choice for Bun. We would get constructors & destructors. We could delete lots of extern "C" wrapper code. But, we would still be reliant on style guides enforced through code review, and even with ASAN, memory corruption and memory leaks would still happen.
Funnily enough Node.js works perfectly fine in C++.
I never took Bun as a serious project. And now it's just a test bench for Anthropic marketing department. I will continue to stay away from it.
Funnily enough Node.js works perfectly fine in C++.
I mean, Node has definitely had memory safety CVEs that stem from stuff in their own library code, I found multiple results from literally just googling "nodejs memory cves".
But Node doesn't have anything like the instability issues that Bun has. The problem Bun was facing wasn't "there are CVEs", it was the quantity and regularity of crashes and CVEs.
Node uses a similar language, but doesn't have the same issues with stability. It is reasonable, then, to try and understand what causes these differences. I don't think the language alone is enough to explain the difference in scale between the kinds of issues facing both runtimes.
(In fairness, the blog post also mentions the small size of the Bun team and the ambitious scope of the project, being more than just a runtime like Node.)
But is it less stable than node in 2016? We need to keep in mind that node had 14 years headstart over bun when comparing them like that. (Or longer, depending on how you count)
I'm not sure, but my feeling is that it was. At that point I remember using it in production and not really running into any issues with the runtime at all. NPM still had plenty of issues, but they were less because NPM was unstable, and more because the ideas behind it had issues. And the package repository was a mess but that was more due to the load and iirc poor architecture.
Whereas what I've heard from people who've tried Bun out is generally not great stuff - it's cool that everything is included in a single package, but using it in anger typically leads to stumbling into these sorts of stability issues.
Though this is pure feeling and memory, and I'm not trying to cite hard evidence here. I would be interested if someone has gone through and actually looked at the stability issues over time for the different runtimes.
(Although fwiw, Deno was released in 2018, was written in Rust, and stability issues/memory safety were not mentioned at all as a reason for Deno in Rust over NodeJS in C++. It's not a completely comparable situation, because Deno was deliberately trying to do a lot of things differently from NodeJS, and the choice of host language was just part of that, but I think it demonstrates that NodeJS's major flaws, at least in the eyes of its creator, did not include instability, which is a stark contrast to Bun.)
I don't think Zig is that similar to C++ for these purposes. Node makes heavy use of C++'s tools like unique_ptr and destructors, for example. I think that explains most of the difference.
That's a fair point. I'd be interested to see how a seasoned Zig developer would architect something like Bun, particularly in terms of memory safety. Is this something that can be got around by changing how allocations happens (@matklad has already mentioned the approach of doing all allocation up front, although I assume that wouldn't be practical for a JS runtime integrating with a pre-existing engine), or is this just one of those things where Zig just doesn't do much to help?
Funnily enough Node.js works perfectly fine in C++
Only in the same way Bun was perfectly fine with Zig. Node just has more attention and users to flag the problems earlier, but they're in exactly the same situation of "it works perfectly if we're very careful and nobody makes a mistake". (Spoiler: they aren't and they do)
I'm glad Andrew made a statement here. Zig resisted AI slop and so Anthropic made an example out of them, similar to what OpenAI did to Studio Ghibli's art style. Some are calling out Andrew's "unprofessional" language as if Anthropic/Bun's slop rewrite and subsequent marketing blog post were purely technical endeavors free from politics. Some very rich people took a shot at Zig for marketing purposes and I think it's okay to punch up at that.
Zig resisted AI slop and so Anthropic made an example out of them
I don't think there is any reason at all to believe this and it has been explicitly denied. I wish people would stop repeating this as if it's true, especially after Jarred's long post which was very complimentary of Zig and which laid out in detail the reasons that he pursued the rewrite and gave concrete reasons that the result was an improvement.
To add more context around lifetime errors and TigerBeetle's particular style guide:
Many projects opt to answer these kinds of questions through a style guide. TigerBeetle's TigerStyle is an example in Zig and Google's 31,000 word C++ style guide is another. The challenge with style guides is enforcement.
TigerStyle is a bit more than just a style guide. The key rule for this discussion, uplifted straight from of NASA, is static memory allocation: all memory is allocated in the startup phase, and there's absolutely zero allocs afterwrads . This plus crash only design means that we never call free.
This rule is self-enforcing and compositional, in Zig. There's no global memory allocator, so the code after startup simply hasn't the API to allocate. You can't circumvent this by accident. Of course, if the programmer is byzantine, they can stuff allocator in the global, or just directly mmap and unmap pages of memory, but, at our scale, we don't have problems with that. This is a similar in kind (not degree) to Rust, where untrusted code generally can circumvent safety guarantees, even without literally spelling unsafe.
And, naturally, never freeing goes a long way towards solving many memory errors by construction. Empirically, they just haven't been a problem for TigerBeetle. It's hard to untangle contribution of static allocation in particular from everything else we are doing, but it would make sense for it to play a leading role.
(As a footnote, we aren't actually do static allocation to avoid memory errors, we use it as a linter to check that every quantity has a known logical static limit, the main property we care about)
There's no global memory allocator, so the code after startup simply hasn't the API to allocate.
I don't know Zig at all, but can't you call std.heap.page_allocator anywhere you'd like?
Yes, this is "just directly mmap and unmap pages of memory" part.
How is that not a global memory allocator? Presumably you can pass it to your function calls as well? There's also std.heap.c_allocator which seems to be just malloc in disguise.
He's making the distinction that in Zig you can't just my_vec.append(thing) and expect an ambient, global allocator to silently give you the memory.
You're saying "but there's an allocator API, so therefore there's a global allocator," which is not correct. Passing around an allocator to functions is exactly what you do in Zig, and is exactly what makes it not global. You can pass different allocators to different functions, which by definition makes them local!
I am preemptively agreeing that my phrasing isn't water tight :) I stand by the meaning: Zig can't guarantee that no runtime allocation happens behind your back, but the API works such that you code won't be able to allocate, unless you design for it, or deliberately circumvent your own checks. The rule is in the function signatures checked by compiler, not in the style guide checked by reviewers.
How is that not a global memory allocator? Presumably you can pass it to your function calls as well?
The "pass it to your function calls" is the key part. You could also have effectively global allocator by creating it in fn main, and then passing it down the stack. The salient part is not the number of instances, but the explicitness of access.
All APIs in Zig work such that a function that needs to allocate, requires you to pass the allocator down. So, eg, HashMap's grow function would take an allocator, but a function to do lookup or insertion into a free slot won't:
pub fn ensureTotalCapacity(
self: *Self, allocator: Allocator, new_size: Size
) Allocator.Error!void
pub fn put(
self: *Self, allocator: Allocator, key: K, value: V
) Allocator.Error!void
pub fn putAssumeCapacity(
self: *Self, key: K, value: V
) void
This is purely API-design question. You could do the same thing in C, but then you'll need to replace standard library with your code, and you'll have to proactively ensure that nothing uses libc, as innocuous-looking things like strdup will allocate behind your back (the Zig analogue takes the allocator as a parameter).
The beauty of the API is that it allows to separate allocation temporarily, not spatially. It's not "module A allocates, module B doesn't", it's "everything allocates, but only at startup".
Being API, nothing prevents you from ignoring it and just building your own worse version which relies on a globally-accessible allocator itself, so the non-byzantine assumption is important here. Another easy way to circumvent this is to use libc, as Zig makes it equally easy to use or not use libc (we don't, c_allocator is @complieError in tigerbeetle).
Thank you (and your siblings) for your comment. Perhaps a different way to phrase it is:
In Zig, assuming that the function I'm calling to is well-behaved (e.g. it doesn't call
std.heap.c_allocout from under you), I can control where stuff is allocated by passing an allocator to it.
Would you agree with that way of saying it? And then "well-behaved" here is doing a lot of heavy lifting, since this is purely by convention, correct? In a way, this sounds similar to the way that in Rust, consumers of libraries generally assume that the libraries are "well-behaved" in their uses of unsafe.
Is there anything preventing anyone from designing such an API in e.g. Rust?
Sounds like the benefits of Zig has a lot to do with the way that the standard library is designed, more than with how the language is designed (modulo comptime) and what the community standards and conventions are. Would you say that's a fair characterization?
Would you agree with that way of saying it?
Very much so! The "unsafe culture" analogy is something I considered writing, and skipped in the interest of brevity.
Is there anything preventing anyone from designing such an API in e.g. Rust?
I'd love to see more experiments in this area, but I am skeptical, for three reasons:
Box is an escape hatch for the borrow checker, but, if your allocator isn't global, that option goes away, which might push code complexity too farThough, maybe something similar just for static allocation works? You still have a global allocator, but you explicitly type-state all types for pre/post alloc, and use a ZST lifetime-less token as an allocation capability?
Sounds like the benefits of Zig has a lot to do with the way that the standard library is designed
For the static allocation, yes! Although, again, that Zig doesn't have a borrow checker is also important, as that allows to design the most natural API without much thinking. But there's more to Zig than static allocation. Bounds checks, checked arithmetic, strongly-typed alignment, strongly-typed error codes, tagged unions, explicit undefined are some rather important language features. If Zig didn't exist, TigerBeetle would probably have been written in C, and the safety gap between C and Zig is just gigantic. And safety is one aspect of the language, Zig has a lot of going on for it elsewhere!
the safety gap between C and Zig is just gigantic
An often under-appreciated and misunderstood fact!
"No global memory allocator" means the allocation doesn't happen automatically, without those explicit initializations / calls as you mentioned. You can certainly use it as a global allocator as you wish, but this would be explicit and visible in the call stack, and not very idiomatic in the general case.
There's also std.heap.c_allocator which seems to be just malloc in disguise
it's hardly a disguise; it's plainly obvious from literally all available context clues.
Zig made Bun possible. I would never have been able to build this much in 1 year if it wasn't for Zig.
With 1 engineer using Fable & closely monitoring Claude Code, we went from start to 100% of the test suite passing on all platforms in 11 days. One engineer can do a lot more today than a year ago.
One of the most interesting things to me about Bun is that it's a story of (basically) one engineer doing way more than we would estimate or expect. Jarred attributes this first to Zig, then to Claude, but you could just as easily attribute it to Jarred himself or his work ethic. Or the power of a small team, or the fact that he's rewriting and implementing things that already exist.
In the "Bun is joining Anthropic" announcement Jarred said they were hiring additional engineers to work on Bun. ("Being part of Anthropic gives Bun: More firepower. We’re hiring engineers.") But just going off of GitHub, the Bun team seems to have shrunk. I don't know what the take away from that is, other than, "Bun is a small team."
Meta: Combining the comments section for these two articles has made the discussion incredibly confusing and hard to follow.
I think there are legitimate technical discussions to have on the Bun port. I'm myself quite interested in a lot of the questions raised.
But I really dislike the incredibly personal framing of the post. I know Jarred a bit, and my experience of him is that he is a genuinely nice, thoughtful person. I also know that Bun has pushed the JavaScript ecosystem forward in a meaningful way. Even if one disagrees with specific technical choices, we need people who push boundaries (also with agents), try things.
Pushing boundaries often comes with rough edges. It is fair to criticize those rough edges. It is fair for Zig maintainers to say opt out of LLMs and thus to not have a lot of goodwill towards Bun. But the parts about "stinky manager", "slop" and what sounds like second-hand employment gossip are completely unnecessary and beneath the technical argument. I also think that as a user of Zig there is plenty of stuff wrong within Zig itself that needs addressing before making those kinds of statements about other projects.
At the time of writing, about 4% of Bun's Rust code sits inside an unsafe block (~13,000 unsafe keywords across ~27,000 lines / ~780,000 lines), and 78% of those blocks are a single line — a pointer that came from C++, or one call into a C library.
I assume this statement is meant to sound reassuring, but it doesn't matter whether an unsafe block is a single line: if you violate safety guarantees inside the unsafe block, all of the code outside the unsafe block is potentially unsound as well!
The initial merge of the Bun Rust port contained obvious cases of this kind of unsoundness: https://github.com/oven-sh/bun/issues/30719
The linked issue was addressed by the maintainers enabling Rust's Miri tool in CI. The "What's Next" section of the blog post includes Miri (which runs for a growing chunk of code in CI), so I guess it's good they're working on that.
(To try and be fair to Bun: Rust that contains safety violations could still be more maintainable than the Zig they replaced, depending on the quality of the Zig. Still, "number of LoC per unsafe block" is not a quality metric - especially if there were no other coding practices, expertise or automated checks applied to those unsafe blocks.)
I think the point is not to be reassuring but that the unsafe block comes from the project requirements rather than from the porting process. If they're calling a C library then there needs to be an unsafe block, and there is no way to refactor that away.
I mean, other rewriting the C library too, which I guess might be on the table later?
If they're calling a C library then there needs to be an unsafe block, and there is no way to refactor that away.
At 10,000 call sites? (78% of 13,000.)
EDIT: Maybe this is uncharitable, and it's speculative because I don't want to go and look at their codebase, but my guess is exactly that this outcome is caused by the porting process and they're passing around a ton of raw pointers inside the Rust code (even if that pointer originated at an FFI boundary) rather than isolating the calls into external libraries and then figuring out how to apply safe data structures on the Rust side.
Ok, fair, I'd agree that they probably have the exact same call-sites as the original zig code and probably the next stage of the port should be to do some refactoring to group those behind safe abstractions.
But my understanding of their claim is just that they're pointing out that most of the unsafe code doesn't result from the porting process introducing unsafe code as a translation of zig code, but instead is mostly from the porting process doing a line-by-line translation of zig calls into c/c++ code.
I'm also not surprised that they have unsoundness in the rust code, because the zig code was full of UAF and OOB. Of course a direct port is still unsound. But at least now they have better tools to detect and reduce the unsoundness over time.
If I was in charge of the port I would try to first get to a rust version that is roughly as unsound as the zig version and then incrementally improve from there, and that seems to be what they are doing.
I'm also not surprised that they have unsoundness in the rust code, because the zig code was full of UAF and OOB. Of course a direct port is still unsound. But at least now they have better tools to detect and reduce the unsoundness over time.
I agree on this part. Despite everything I am somewhat curious how this stage goes for them.
I don't think it's uncharitable, but Jarred tweet replied awhile ago that they intentionally made the initial port stay closer to the current structure, at the expense of dispersed unsafe sections, because it was easier to sanity check / verify. You could argue for or against that trade-off, but making one is better than chance!
Whether they'll do extra passes at some point to isolate FFI regions... ¯_(ツ)_/¯
I mean, other rewriting the C library too, which I guess might be on the table later?
Heh, I can't wait for the +18765432,-7654321 pr that shows up again musl and the subsequent blog post about it
The vast majority of the unsafe usage I've seen in the rewrite is not for doing FFI*. It's usually wrapping some raw pointer manipulation code, presumably ported from the Zig.
*: and besides, it is good practice to create a "safe wrapper" around FFI calls, to minimize the amount of unsafe code needed to interface with foreign libraries.
I mean, it's obviously a flawed metric, but that doesn't mean it has no signal. 4% seems right in the middle of the curve for unsafe code usage in Rust across the ecosystem. Having 96% of the code checked by the Rust compiler is quite reassuring, even if a single bug in the remaining 4% can take down everything -- that's true for all Rust projects, after all.
Personally I find it quite impressive that they got to just 4% with a mostly automated process. That's not a trivial achievement.
it doesn't matter whether an unsafe block is a single line: if you violate safety guarantees inside the unsafe block, all of the code outside the unsafe block is potentially unsound as well!
Yes, but there is an ENORMOUS difference between using unsafe blocks to interoperate with C / C++ and using unsafe blocks to work around restrictions imposed by Rust. The first adds almost no new risk beyond the risk already present by saying "this program uses some C / C++ libraries". The latter does add additional risk. I think it is valuable to distinguish between the two in a project which has already been advertised as using C / C++. I care whether it is 12% of the 13,000 unsafe blocks are work-arounds to the language rather than interop or whether it is 60%.
There's a dichotomy being presented here where you have to either choose a "style guide" or a programming language feature in order to avoid bugs. The sleight of hand misdirects the reader
I’m sorry but the sleight of hand is Andrew’s in this case. From the bun blog post:
For Zig code, when exactly should we be running the cleanup code? If we're passing the same *T to many different functions, how do we know when it's no longer accessible and can be cleaned up? How does it work when some functions need to continue to reference the memory after the function is called?
Loading the TigerStyle website, this is the answer:
Allocate all memory at startup. Don't allocate after initialization.
And that works for them! But that’s an almost useless advice for the majority of software.
I used bun for a few side projects and had a very slop-y experience so I tend to accept all the criticism here about shipping stuff and worrying later, but I also think the core technical issues are very real.
The argument for shipping all the million lines of unreviewed code is that the test suite is good enough to catch everything. Then why are you saying you have so many annoying bugs in the Zig code? What happened to the test suite being sufficient to catch everything? It's not sufficient to catch bugs in Zig code but it is sufficient to catch bugs in 1 million lines of unreviewed slop?
This paragraph is written to be sarcastic, but it ought to be a question that motivates the Zig developers to rethink their position on program correctness.
The entire history of C is a story of skilled and diligent professionals attempting -- with various degrees of success -- to stop teenagers from smashing their stacks and overflowing their buffers. This history is ongoing, just the other day there was CVE-2026-57589 in the OpenBSD kernel, and I don't know about you but I would bet money that the typical OpenBSD kernel developer is better at writing secure C than the industry average.
Then Rust comes along and demonstrates that introducing a few fairly simple new language primitives (lifetimes + single mutable reference + unsafe annotations) solves a huge swath of correctness problems all in one go without losing the performance advantages of manual memory management. You just tell the compiler what you want, it'll check your own claims for internal consistency, and tell you if you accidentally dereference a free'd pointer. Hallelujah.
So the question is: why might an automated rewrite from Zig to Rust, enacted by a statistical text generator that can't reliably perform third-grade math, produce a more correct program? And the answer is that a language with compiler-enforced memory safety and a rich type system can wring more value out of a pre-existing test suite, and this is a good thing, and Zig would be better off if they moved some of the correctness out of the user's test suite and into the compiler.
I noticed that you neglected to mention compilation speed. Zig compiler project is about 600,000 lines of code - roughly the same size as Bun before the rewrite, and I'm clocking 16s to build from scratch with a clean cache, followed by 90ms for each subsequent edit with incremental compilation enabled. What are the corresponding measurements of Bun post-rewrite?
I suspect the answer to this one is "not relevant", because compiling 600,000 lines in a single compilation unit with a clean cache isn't an interesting benchmark. Especially if all of the edit-build-test loops are driven by an LLM and the tests themselves run in CI.
Then Rust comes along and demonstrates that introducing a few fairly simple new language primitives (lifetimes + single mutable reference + unsafe annotations)
"fairly simple" here is doing some seriously heavy lifting.
I chuckled. But borrow-checking is certainly simple compared to other contemporary attempts. There were a lot more heavy-formal-methods-style projects going on back then, and it was surprising that a relatively small addition to HM ended up being good enough. Most of the complexity in rust comes from the interaction with generics/traits, and from various adhoc ergonomic fixes that in hindsight could have been simpler. But actually just writing a simple borrow checker is fairly easy, especially compared to writing and integrating a general proof checker.
I'm not sure the author is convincing me of the thing they're thinking... I don't have all the details of course and I'm not deeply familiar with the bun source, but this post effectively seems to say "you don't need to have a special feature or a hardcode style to be safe/stable - with us you just need to spend lots of time/money, not like this messy example". Which... yeah, you probably can do that, but is that really a good outcome? Is it good to be relived that some user of the language moves away, because they'd rather have a safe abstraction enforced at language level than effort level? Is that kind of "only pure and well engineered projects welcome" attitude a good idea for the future of a language?
If the idea is that Zig people want only perfectly designed software using it, or they'll publicly talk down the project's quality... that's a negative signal for most of real software, and good to know ahead of time.
If the idea is that Zig people want only perfectly designed software using it, or they'll publicly talk down the project's quality
There are a lot of good Zig projects that are not 'perfectly' designed nor 'perfectly' implemented. There is though a legitimate interest in evaluating why a given project is in the state it is, especially if the project is big, influential, and hires from the programming language community.
I agree that for an established language there is no point in having the maintainers whine that they don't like your stuff, but Zig is a much younger project and it has a small community still, and when a project the size of Bun makes moves, the effects are felt a lot by the community.
In this specific case I share Andrew's sentiment that it was really cool seeing Jarred learn systems programming to get Bun off the ground. He wasn't an expert and his software was not 'perfectly' designed nor implemented, but that's ok for somebody who is learning. It is a very different thing when you get VC money, interrupt your learning process too early, and end up causing distress to your new employees because you don't know how to be a good boss, nor you can set a well-reasoned technical direction.
Very few people who get VC money start our either as good bosses or with all the knowledge they need. VCs prefer people who are tenacious and quick learners.
Is that kind of "only pure and well engineered projects welcome" attitude a good idea for the future of a language?
For a language that rather explicitly wants to be a modern successor of C? Arguably, yes.
You can't be a successor of C without accepting everything and the kitchen sink. That's what C enabled for many for decades. There's an astonishing amount of crap code which was written by lowest cost contractors for decades before LLMs and it's worse than what Opus can produce today. I'd argue a "modern successor of C" needs to take that code quality and either point out more errors at compilation time or safely at runtime. Otherwise, it's just modern syntax sugar which doesn't provide much value.
I hear you, but:
It is entirely plausible to me that Rust will overtake most places where C or C++ was used in the past, but Zig will nonetheless be an important language for certain niches where its tradeoffs make sense.
I'm not disrupting Zig is somewhere in between with functionality - it definitely is. I just disagreed with the label of "successor". C was for everyone. C's successor needs to embrace everyone too - including terrible code - and lift it up, not punch down.
But at least one author explicitly does not care about the low end:
sipping delicious tea from a mug that says "It Tastes Like It's Not My Problem Anymore".
TigerBeatle gets a lot of praise in the Zig community, but the fact is that it's an extremely niche software. It's not possible to do what they do, if you are working on a dynamic runtime and exposing that runtime to the user. But the one thing is, Zig is best used for problems, where you can batch resource management, which both simplifies it, and also makes it faster. For example, I was super skeptical about writing HTTP servers in Zig, all the string management, etc, but it turns out per-request arenas make it a non-issue. Your memory usage might be slightly higher than with a heavy GC, but probably not wildly and it will be much faster than the GC.
The post claims they were fuzzing their Zig code, while during our calls the whole Bun team told us that they were not fuzzing anything. This appears to be an outright fabrication.
Bun landed fuzzing in Nov 2025, so presumably after Andrew had these conversations but before Jarred wrote his post.
This is afaict the only technical claim in the whole article, and it's false, trivially could have been checked to be false, and also includes a slight on Jarred.
I like Zig a lot and had previously had a lot of respect for Andrew Kelley but this post was incredibly offputting.
We became increasingly horrified at the programming practices we saw in Bun's codebase. Hacks on top of hacks. Abuse of assertions. Most of all, recklessly speeding past feature after feature with very little time taken for reflection and elimination of bugs and technical debt. Jarred was already writing slop well before he had access to LLMs.
Where was this surfaced at the time? Where was the steering and mentoring of one of the most visible public Zig projects. Andrew, in this post, seems to have no qualms about speaking his mind openly, but did he do that during the period of becoming increasingly horrified?
Reading these words now, after the event, just feels like a petty attack - "we knew it was bad all along, so good riddance".
They say they had monthly meetings with bun and brought up issues. I have no way to verify what was or wasn't said in those meetings but it doesn't surprise me that Zig wouldn't have wanted to publicly shame Bun (well, until Jarred's recent blog post). From a marketing point of view, publicly shaming one of the top three Zig projects (in terms of visibility) would not have been a good look.
The main problem, however, was code quality.
The sleight of hand misdirects the reader away from the main way bugs are eliminated: by dedicating engineering resources to it.
Perhaps the amount of bugs comes from using a C-like language that requires meticulous manual care to avoid writing runtime bugs.
Even C++ would be a safer choice because of RAII.
When you have to dedicate significant resources to avoid/fix runtime issues that are made impossible at compile time by other languages, the programmer isn't entirely at fault.
Basic / dumb question: Why do people use Bun, despite its self-admitted low stability?
Is it that much faster than node.js? And the built-in tools are good and better than the node.js equivalents? (bundler and package manager)
And it is appealing to some people over Deno? (which I would imagine has higher stability in terms of memory safety, having been written from Rust from the start)
Bun is (was?) fun. It packages what used to be many separate tools into one. It's fast. It mostly "just works". So many things that used to take multiple tools, custom config, or were soooo sloow, are nice under Bun.
Bun can also produce (near) static binaries, so you can package JS services in an OCI container that's much, much smaller (and simpler, and safer - if you go distroless) than a typical Node.js continer. (Not that important for most; and still bad compared to Go… but I liked that aspect.)
Disclaimer: I have not used Deno, so I can't compare these two. I have never used (and would not use) Bun in production, but I have for a few small hobby projects and it was a very pleasant experience compared to Node+npm+eslint+tsc+jest. (But even on such small scale, I have experienced Bun bugs and AI slop hallucinations in the official docs)
Basic / dumb question: Why do people use Bun, despite its self-admitted low stability?
Stability is always a question of what you do. Node is also not a pillar of stability. I had to put plenty of workarounds into node because even the built-in fetch function now sometimes hard crashes node on windows.
People use bun because it's good. It's fast, it lets you redistribute binaries in a nicer way than node's SEA and it's really nice to use. The built-in typescript support was much better than what node had for a long time.
edit: this was meant to be a reply to the parent
rewrites are a terrible idea
Proceeds to rewrite.
The method is interesting but this reads like a marketing article to me. No breakdown of how much it cost (ctrl+f "cost" results in 0 results), no risks associated with the rust rewrite. Nor even a concrete explanation of why the rewrite happened in the first place. If I were to guess why the rewrite happened, it could be due to Zig's no ai policy or some internal mandate that anthropic wants to focus on using rust.
No breakdown of how much it cost (ctrl+f "cost" results in 0 results)
This bit seems at least relevant, if it doesn't answer your implied question outright:
Pre-merge, this took 5.9 billion uncached input tokens, 690 million output tokens, and 72 billion cached input token reads — around $165,000 at API pricing.
Nor even a concrete explanation of why the rewrite happened in the first place.
I feel like the blog tells a coherent story? From what I can tell:
Bun has historically been crashy despite the measures the devs took to catch issues and they wanted something that could address those issues more systematically:
We could have kept fixing these kinds of bugs one-off in perpetuity, but we owe it to our users counting on us to do better than that, and systematically prevent these kinds of bugs from recurring.
The devs originally started off with a plan to more rigidly enforce a particular coding style coupled with introducing smart pointers:
Having a rigid style guide with clear ownership expectations explicitly spelled out in the type system was a real option for Bun....
<snip>A year of zero user-facing impact [due to a rewrite] is not a realistic option we could consider. So, enforcement through code-style to fix stability issues was our best bet, and was our plan when we added Rust-inspired smart pointers to Bun's codebase.
But Jared wasn't too enthused about that solution and decided to try an LLM-assisted port to Rust:
But honestly, I didn't want to do it. Homegrown smart pointers offer worse ergonomics than Rust, with none of the guarantees.
What if, instead, I spend a week testing if Anthropic's new model can rewrite Bun in Rust?
And then when that experiment looked promising decided to go all-in:
At first, I didn't expect it to work. A few days in, a high % of the test suite started passing and I saw how much the new Rust code matched up with the original Zig codebase. My opinion went from "this is worth trying" to "I'm going to merge this".
At least to me it looks less like an up-front decision to rewrite into Rust and more "Rust looks like it provides solutions to our problems but we can't rewrite due to negative impacts said rewrite would have. Hmmm, I wonder how an LLM port would work out... Hey, it looks promising, LLM rewrite it is!"
It's bizarre to me that if someone announced a new javascript runtime then it would seem obvious that rust is the right choice rather than a memory-unsafe language, but if someone rewrites from a memory-unsafe language to rust then get so many people asserting it must be a marketing stunt or the result of some political battle, because there is no other possible reason to want to port to rust. There's some weird path dependency in the reasoning here.
FWIW I agree in part, but also the concern is more than mere path dependency -- it is about the magnitude and suddenness of the change, and also the seeming lack of care with which it was done. If you were building it from scratch in Rust, to get to the same point, you'd probably have gone through many versions in between, each of which would have been incrementally validated. (This is why it's important that committal decisions be made carefully, and certainly I personally would not have used anything but Rust in 2022.)
Sure, I understand concern about quality of the port, I'm just surprised by people asserting that the port can't possibly have been motivated by wanting memory safety and must have some other driver.
The marketing label is not related to the rust choice but to the lack of logic of this story.
> Be Bun
> Zig is awesome, Bun better than Node.js
> Acquired by Anthropic
> Zig too much bugs
> We need a rewrite
> Thanks God Claude exists and it's powers are superhuman
> Claude rewrite it to Rust
The choice of Rust is irrelevant here but the reason behind the rewrite are not. If Claude was so powerful why not ask it to just fix the problem?
> Hey Claude fix all Bun bugs. Made no mistakes.
The problem here are the untold parts of the story.
Moreover, if all the problems were CVEs related, why not use Fable to fix them. They told us this is so powerful in discovering security bugs they need to ban it. Like a tiny Kevin Mitnick living in our terminal.
Zig is awesome.
One bajillion lines of code later... maybe we should have used rust. Damn. Too late to rewrite.
Mythos access and free api usage... huh, maybe it isn't too late?
Anyone who has ever worked on a big project can relate to making a bad decision and later wishing they could change it. I don't see anything confusing about that.
It's marketing to the extent that any technical blog post from a company is always marketing, but we generally allow them if they have good content. I found it interesting and useful to see a case study of one of the first big LLM rewrites.
Acquired by Anthropic
Zig too much bugs
We need a rewrite
We don't actually know that this is the order of events, do we? If anything, the blog hints at the opposite order: the PR adding shared pointers to Bun's codebase (after rejecting a "normal" rewrite if the blog post is to be trusted) was merged on 2025-08-20, and Anthropic's acquisition announcement was on 2025-12-03. The port to Rust looks like it started around 5 months later.
If Claude was so powerful why not ask it to just fix the problem?
Moreover, if all the problems were CVEs related, why not use Fable to fix them.
My guess would be because that would only solve issues at one point in time; i.e., it would not be the systematic fix the devs say they wanted.
I don't think the arguments rest primarily on that "path dependency", that is just a matter-of-fact. You are the one adding the "because there is no other possible reason" bit, at least from my reading.
IMO the reason people see this as a marketing stunt/political is that it is written by Anthropic. You can disagree, or find that argument weak, but I don't think it is primarily a question of rewrite vs. greenfield.
Pre-merge, this took 5.9 billion uncached input tokens, 690 million output tokens, and 72 billion cached input token reads — around $165,000 at API pricing.
I was curious how much new code has been added since the merge (as everyone seemed to agree it needed a lot of cleanup at that point).
> git show 23427dbc | grep '^+' | wc -l # additions in the squashed commit for the rewrite PR
1011076
> git log --oneline 23427dbc..HEAD | wc -l # commits to main since the rewrite
745
> git format-patch --stdout 23427dbc..HEAD | wc -l # additions since the rewrite
748618
So about 75% more added LoC on top of the original rewrite. If we assume this is all developed using similar LLM agent cost-per-added-LoC (big assumptions, not sure how reasonable) then it'd be another $122,000 or so.
I think the reason for the rewrite is well-justified? Constant memory safety issues and fear around playing never-ending whack-a-mole with memory issues. (Even if some engineers would deal with this another way, choosing to LLM rewrite to Rust is also a solution to the problem.)
“ Pre-merge, this took 5.9 billion uncached input tokens, 690 million output tokens, and 72 billion cached input token reads — around $165,000 at API pricing”
This is 100% a marketing piece.
And yeah I agree that the reasoning for the rewrite is very vague.
You might think of it as a marketing piece but I can tell you that lots of engineers were waiting for this blog post ever since the merge.
fwiw, my perception is that engineers broadly have demonstrated time and time again that with juuuuust enough technical veneer, we will get VERY excited about a big corporate marketing event. doesn’t mean there is no valid reason to be excited, just means that the marketing is working.
Something can be both marketing and interesting/informative. It's important to keep in mind that it is marketing, but that doesn't mean we should just ignore it.
It's definitely a marketing article (even if it wasn't intended to be one), but in reality it's impossible to calculate the cost, especially if the devs had access to the pre-release Anthropic models. We can though estimate the cost if we, mere mortals, were to rewrite something that huge using claude models now.
Amazing post! Zig and Andrew Kelly might perhaps be the savior of (open) software from all the slop everyone's happily lapping up.
Thank you for sharing this. It's important for programmers to realise the character of Zig leader and to rightly stay away from thinly veiled personal attack, passive aggressive tone and general immaturity.
The most salient technical impedance mismatch for what bun is doing that I recall Jarred mentioning was that it was more complicated to manage lifetimes between js-land garbage collected things and Zig-land manual memory management. He preferred Rust's destructors with Drop vs Zig's defer. This sounds similar to Ladybird's reason for going with Swift over Zig, the OO impedance mismatch. Are these complaints valid? What are the right solutions to these in Zig and how can it be easier for users?
Now, it's not our business to police what our users do, but you may have noticed people screaming in our faces about memory safety constantly. You can imagine how we might want to put some social distance between ourselves and a project whose irresponsible software engineering practices invite the exact kind of criticism that people are eager to level.
There's a dichotomy being presented here where you have to either choose a "style guide" or a programming language feature in order to avoid bugs. The sleight of hand misdirects the reader away from the main way bugs are eliminated: by dedicating engineering resources to it. You're not giving TigerBeetle nearly enough credit. Quite simply they put in the time to find and eliminate the bugs, they make an effort to maintain a healthy relationship with ZSF, and Bun did not do that.
It is extremely telling that this blog post doesn't address Rust or its features at all, which of course was the primary motivation for Bun's migration.
To be clear: you have to be out of your mind to think putting human labor towards something that could easily be checked by a machine is a "good engineering practice".
Zig understands this well already: nullable pointer types, tagged unions, error set inference, explicit handling of memory allocation errors; these are language features that move what would have taken extra human labor to something the compiler can check for you. If "engineering resources: were all you needed to avoid bugs, why have types? Why not write assembly all day?
This post is mostly useless for analyzing Bun's implementation or the success of their rewrite and is far too focused on psychoanalyzing Jarred. If you need to punch down on one of the largest software projects written in your language because they weren't "holding it correctly", then your language is screaming for improvements.
I actually don't have any personal criticisms of Jarred.
If you're making personal attacks, at least own up to it.
We could have kept fixing these kinds of bugs one-off in perpetuity, but we owe it to our users counting on us to do better than that, and systematically prevent these kinds of bugs from recurring.
A great reason, but I'd have also accepted "the vibes around Rust are great."
Congratulations to Jarred, the Bun team, and Anthropic on pulling this off.
I have mixed feelings on both the bun post as well as Andrew's response.
For the bun post, while well written and articulated, it feels completely corrupted by the VC ecosystem. Now with the acquisition by Anthropic, it seems an imperative for bun to move away from being associated with an outspoken antagonist to its company's very existence. I think calling it "misaligned incentives" underplays to the gravity of the situation. How could Anthropic maintain a popular project using a language where the maintainers refuse any of their contributions (code or even donations)? Further, the migration also plays off like a PR/marketing stunt which further erodes the valid struggles Oven has been dealing with using Zig.
For the Andrew post, while fun to read about spilled tea, is not surprising given his other comments on this very site. While I don't respect the personal insinuations from Andrew's post (regardless if they are true), I am genuinely interested in learning about Bun's technical frustrations and how to properly handle them in Zig. I maintain a popular project in Zig and want to learn more. Let's focus on the tech!
I don’t think that critique of AI works here.
The source here is Bun (mostly written by Jarred) and the output is clearly a derivative work of that source. Where is the OSS code that this work has supposedly copied in this output? A human programmer would have created much the same code - even made the same mistakes probably - because the code is a line by line rewrite of Bun from Zig into Rust. The only OSS code reflected in the Rust version is the original Zig code. There’s no training input turning up in the output here - unless you think writing an API call constitutes copyright infringement, which the vast majority of the programming world will disagree with.
You can argue that LLMs themselves internalise OSS code & that makes them infringing, but OSS licences allow you to read & internalise their code: Human programmers learn coding by studying OSS code, so why can’t an LLM do the same thing?
I'm making a simpler argument than "the work is already under a different copyright".
They surely own the code they already wrote and are free to use their own hands to make derivative works.
The problem is that even if it were a derivative work, it would be a derivative work that they don't OWN!!!!!! If I write a Harry Potter fanfic, J.K. Rowling does not automatically get to say "copyright J.K. Rowling" on top of my words.
The problem is that even if it were a derivative work, it would be a derivative work that they don't OWN!
You seem to have misunderstood the legal situation around LLM-generated code, and possibly around copyright law in general.
Just because some text was generated by an LLM does not mean that it cannot be owned by the person who prompted the LLM, and possibly by other third parties if their work was reproduced to the appropriate degree in the output.
If I write a Harry Potter fanfic, J.K. Rowling does not automatically get to say "copyright J.K. Rowling" on top of my words.
If you used ChatGPT to translate Harry Potter into a different language the J.K. Rowling would in fact hold a copyright on the output, and would have the right to sue you for infringement if you tried to distribute your translation. Fanfiction exists as an intentional violation of copyright law that the original owner may choose to ignore as a gesture of good will.
Well I'd agree that they own the prompt they gave the LLM, but after that the law gets very fuzzy.
...and even if my HP fanfic was infringing on Rowling's copyright, that doesn't mean that she would automatically have the ownership rights to distribute my infringing work -- it just means that she could sue me and force me to stop distributing it.
Well I'd agree that they own the prompt they gave the LLM, but after that the law gets very fuzzy.
It does not. The law is very clear that copyright propagates through mechanical translation, even if the result is very different from the original input. Otherwise the copyright attached to source code would not propagate to compiled binaries.
...and even if my HP fanfic was infringing on Rowling's copyright, that doesn't mean that she would automatically have the ownership rights to distribute my infringing work -- it just means that she could sue me and force me to stop distributing it.
Yep, that's how copyright works.
Do you think that some third party holds copyright on the text generated by an LLM translating Zig code to Rust? If so, who?
Now if LLMs ACTUALLY DID mechanical translation the evidence that might be a reasonable argument, but investigations into what they do when asked to "mechanically translate" show that they basically just write a new creative work in the target domain drawing from everything they know about the target domain.
Let's say a write a API docs, and Google runs an LLM to summarize it. No creativity was involved in the prompting. If I understand your reaction to my fanfic example, you're saying I now own the output Google generated, that its copyright would legally belong to me. Do you agree with that?
Now if LLMs ACTUALLY DID mechanical translation the evidence that might be a reasonable argument, but investigations into what they do when asked to "mechanically translate" show that they basically just write a new creative work in the target domain drawing from everything they know about the target domain.
You don't have to speculate about what the Zig to Rust translation of Bun looks like. The code is public.
Let's say a write a API docs, and Google runs an LLM to summarize it. No creativity was involved in the prompting. If I understand your reaction to my fanfic example, you're saying I now own the output Google generated, that its copyright would legally belong to me. Do you agree with that?
If Google copies a snippet of your site (such as the <title>, or some small chunk of the body) into its search results page then you retain the copyright to that snippet, and Google is allowed to copy it anyway due to the doctrine of fair use (though note that some jurisdictions don't allow this; Google wouldn't be allowed to provide summaries there).
If Google fed your entire page into an LLM and had it produce a summary for use on the SERP, you'd likely own the summary, to the extent it contains copyrightable content (vs just a list of facts, such as a table of function signatures). Again, Google would be allowed to serve that summary as fair use.
If Google fed your API doc into an LLM for a summary and it generated a Markdown rendering of the complete original document then you would own the copyright (as before), and also the fair use defense would be greatly weakened, should you decide you wanted to pursue a claim of copyright infringement against Google.
If Google fed your API doc into an LLM for a summary and it generated a chapter from Harry Potter then J.K. Rowling would own the copyright on the LLM output, not you, and there would be essentially no fair use defense possible.
So the question remains: if the copyright owner of a Zig codebase uses an LLM to perform a mechanical translation into Rust, and you believe they do not have copyright permission to distribute the resulting output, then whose copyright do you believe they are infringing?
This isn't some hypothetical. Google runs Deepwiki. I'm asking: do I own the content on the Deepwiki page for my project?
They claim to have the right to generate a solely-derivative work form my content, then they claim that they own that work enough to license it as MIT work they own. I'll sue them to kingdom come if I ever find out they're doing that to me -- putting their copyright message on work of which the copyright legally should belong to me
This isn't some hypothetical. Google runs Deepwiki. I'm asking: do I own the content on the Deepwiki page for my project?
Link the DeepWiki page for your project if you want an answer. From your profile I'm assuming the string to search for would be bablr, but the DeepWiki search page had no hits for it.
edit: Also DeepWiki appears to be run by some startup (https://deepwiki.com/ -> https://devin.ai/ -> https://cognition.com/) so I'm confused about what you think Google's involvement is.
They claim to have the right to generate a solely-derivative work form my content, then they claim that they own that work enough to license it as MIT work they own.
I'm not sure where you're seeing anything about DeepWiki content being licensed under the MIT license. Using https://deepwiki.com/torvalds/linux as a convenient example it doesn't say the generated output is provided under the terms of the MIT license (or any other license for that matter).
But when I look at your GitHub projects, they have LICENSE files which start with The MIT License (MIT), so if DeepWiki generated docs from those repositories and specified the MIT license then that ... would seem accurate?
I'll sue them to kingdom come if I ever find out they're doing that to me -- putting their copyright message on work of which the copyright legally should belong to me
What would be the cause of action?
I will never give them even tacit permission to generate the page, as I feel requesting it would be. I have also sent them an email detailing my non-consent.
The cause of action would be copyright infringement. Didn't you just tell me that if the only work they did was mechanical translation, I would still be the copyright owner?
By the way, here's where they grant you the MIT license to use any content on their site: https://deepwiki.com/deepskies/DeepWiki/5.2-usage-rights-and-limitations
This of course presumes that they own ALL the content on their site, despite not having written any of it.
You linked to auto-generated documentation for https://github.com/deepskies/DeepWiki, which is a completely unrelated project that just happens to have a similar name to deepwiki.com.
It looks like it's a nearly-empty stub repository with an MIT LICENSE file, so the auto-generated documentation talks about what the MIT license means.
It is extremely obvious from even a cursory reading that the page you linked is not a description of the deepwiki.com licensing.
Wow, OK, my bad. It seemed self-evident to me that they would address the legal basis for the content, but I guess not. What right do they claim to have to publish the content, then?
even if it were a derivative work, it would be a derivative work that they don't OWN
This is not how copyright works. If your understanding of copyright law is this confused then I don’t think there’s any way to have a productive conversation about this.
I thought the copyrightability of LLM-generated works was still an open question in US case law, at least nominally?
See https://sfconservancy.org/blog/2026/mar/04/scotus-deny-cert-dc-circuit-thaler-appeal-llm-ai/ where the question is squarely punted on, based on the very particular claims in Thaler v. Perlmutter, and the fact that SCOTUS simply did not grant cert in this case.
Anyway, the point being that I don't think arguing "based on my own analysis of copyright law I don't think largely machine-authored works (including software) are copyrightable by the human(s) involved in the process" shows the kind of confusion you want it to.
Note the case you linked to is about a related question of whether an LLM can be the registered author of a work, not whether the output of an LLM can be copyrighted. The court held that you can't register some code with the US government as "Copyright 2026 by Claude R. Anthropic".
Right, that's what I meant by "the very particular claims", maybe I should have been more explicit here.
I don't think that's relevant, though, as the point is only that this seems to be the only related case to have worked its way through the courts (I may be wrong here, if there are more I'll apologize and retract all of this.) and it is very limited in scope.
This is not so settled as to be a foregone conclusion. Certainly I think the attitude that "it is not even worth engaging with you if you are not convinced of the general copyrightability of LLM output by its human users" is a bit harsh.
The copyrightability of LLM-generated de novo works is an open question in US case law in that it hasn’t been completely tested in court yet. (Legal opinions I’ve seen suggest that the raw output of an LLM would not be copyrightable, but output that has been tweaked by a human in some way could be.) As the sibling comment to mine states, Claude itself cannot assert copyright over anything.
However the assertion that a translation of existing human authored code with established copyrights from one programming language to another by an LLM creates a derivative work of the original is, I believe, a straightforward interpretation of current copyright law as interpreted by the courts.
Feel free to argue the case! I’m open to counter arguments.
I'm aware that a court could reassign intellectual property as part of a settlement of a lawsuit, but that's more like damages: ownership of IP is changing hands.