Hacker News new | ask | show | jobs
by gorjusborg 27 days ago
Here's the thing:

I was first interested in Bun because it was written in Zig. I was interested in Zig because I respected Andrew Kelley's decision-making, and his taste matched my own.

I got really excited about Bun for many reasons after that, but they essentially came down to a similar root: the decisions were ones that I respected and would probably have made myself if I had thought of them.

I was a little concerned when Bun was acquired by Anthropic, but forced myself to remain cautiously optimistic.

This behavior, though, is exactly the sort of decision-making that I don't respect. I've got nothing against Rust, but if this is how Anthropic is managing Bun, I can no longer bet on it being a reliable part of my toolkit. It isn't just the code, it's the thought behind it that I have to trust.

I was so excited by Bun for many of the use-cases I have, but this just turns me off completely. This looks like an Anthropic internal-only tool, based on the behavior.

4 comments

Bun is really interesting project, but the amount of segmentation faults in issues was too concerning for serious production usage. I guess this is one direction to fix it, but let’s see.
It's inability to be compiled from source without a fork of the zig compiler made it unusable in many corporate environments that require deps all be from source as well (or very hard to integrate at least)
Like many alternative implementations,I forsee Bun losing the little mindshare it has managed to achieve.

I don't have a single reason not to pick nodejs when doing JS.

I can understand where you are coming from, but I myself am coming from a quite different place. I'm a long-time Deno fan, and to me Bun was less interesting because a.) it seemed like a much-less-ambitious Deno, and b.) I don't want to learn Zig, so I wasn't likely to try to hack on Bun itself, even just recreationally.

But, I warmed up to Bun over the last couple years almost against my own will — trying to maintain a pretty large body of TypeScript code in a runtime-agnostic way (including even Node, since 24.2). I don't want to make any specific TypeScript runtime a requirement for my TypeScript code, unless there are really good reasons to do so.

But Bun (like Deno) kept providing those reasons. Postgres, SQLite, S3, websockets, local secrets (Keychain/wallet), bundling, compilation, killer speed. So I (somewhat grudgingly) started using Bun more, and even made it a requirement for some of my projects (albeit, in ways I could walk back later if needed).

Today, I have a bunch of API servers and frontend app servers which are bun build --compile --bytecode single executables ,that can run and be deployed virtually anywhere.

I've been very happy with it so far. But also, I don’t think that the way I am doing it is super-common, and now that they are doing this, uh... extremely ambitious LLM port, I am perfectly positioned to regret all of my decisions around Bun if this port ends up sucking.

So I'm a little nervous, but... what if it doesn't suck? That would be cool, because a.) they will have shown something interesting about what is possible with LLMs (albeit if you are rounds-to-a-trillion-dollars valuation frontier AI lab, lol, but still). And b.) going forward, Bun will be developed in Rust. We all have our own preferences, obviously, but to me, that's a win.

And if it does suck, though — that's super interesting too! Will be annoying to me to re-architect my Bun-specific shit to Deno, but for the world at large (and me, too) that's still interesting information!

Because Bun is perfectly positioned to do a huge LLM-powered port. They are one of the premier TS/JS runtimes, it's obviously and insane marketing pillar for the AI lab that bought them, they have unfathomable resources and access to the cutting-edge models that all of us don't get to play with yet, and for all intents and purposes, they have unlimited money to do this.

So if they can't do it — which will be really obvious, I think, if true — then it really just isn't possible yet, and all the naysayers were right.

>and to me Bun was less interesting because a.) it seemed like a much-less-ambitious Deno

I don't know, I've followed Deno, and it appeared to me an incredibly low ambition from the get go.

lol — what you're saying doesn't make sense to me, but I'm sure it makes sense to somebody

What I was specifically referring to is Deno (originally) trying to fix the (glaring, fundamental) problems that Node imposes on the world, vs just do them faster.

Yes, but "fixing some fundamental Node problems" is a low bar, hardly the high mark of ambition now, was it?

And to offer a counter example, something like Dart appeared much more ambitious to me.

I guess it depends on how you define ambition. If you are talking about in an absolute sense, yeah of course, the Dart project had to build a whole language, VM, and ecosystem. That's way more ambitious than Deno.

Though if you look relative to the team size and resources going into it, a project like Deno can still be considered ambitious. Creating an alternative ecosystem to nodejs is a large undertaking.

OK. But without changing programming laguages, "fix some fundamental Node problems" vs "don't fix those problems, just run them faster, and maybe inline the most popular dependencies"...

Surely we can agree that one of those positions is relatively less ambitious?

Well it remains to be proven how they can make a business out of fixing nodejs fundamental problems.
> what if it doesn't suck? > And if it does suck

Why not both? How about that: perfectly fine for Anthropic but suck for everyone else.

well to me that would still count as "it sucks"

but sure anthropic might not agree

Is there much value in it being written in rust if it's all AI slop?
Well "slop" is doing a lot of work there. If it's all incomprehensible garbage-code that no human can understand? Then... yeah very marginal value to me, in terms of hacking on it.

However, I think if it turns out that that's the case, then their port will fail in two ways (to paraphrase Hemingway): gradually, and then suddenly.

I don't think this port can be a success unless they end up — on the other side of it, not necessarily immediately — with maintainable Rust code.

if they succeed nothing will change for you
If they succeed the software will be more reliable with less memory issues that are very likely significant security issues at least some of the time.

When we've seen linux having a new significant exploit every other day now thanks to LLMs being better at weaponizing memory bugs this seems significant.

What attracted you to Bun over Deno?
I'm not the person you asked, but for me, it's the package identifiers. Demo puts URLs to web infrastructure in source files, like Go. In my opinion, this is a huge mistake. There should be a mapping from logical package identifier to web infrastructure, and this mapping should happen outside of the source files. I believe in this very strongly.
Deno supports import maps, which are the mapping outside of the source files.

But yes, URL imports have a variety of other issues (duplicated dependencies, no resource integrity), though Deno solved them in later versions (npm registry support, lock files).

The only benefit of Deno is its permissions system, which has been great for safely letting agents write and run scripts on my file system.

This hasn't been entirely correct since late 2024

https://deno.com/blog/your-new-js-package-manager

Thanks, this is a good correction. I haven't looked seriously at Deno since way before late 2024. The "URLs as package identifiers" issue is what initially attracted me to Bun over Deno, but it may not be relevant anymore.
What’s the downside? Go does library versioning very well, IMO, but I like to hear other opinions.
The core issue is philosophical. Whether you happen to have public infrastructure which provides a web front-end for your git repository, and what exact server that web front-end happens to be hosted on, ought to be completely incidental to compiling source code. But since you ask, Go is the best example of how this can go terribly wrong in practice, IMO. Here are just a few scattered pain points I've encountered:

* In order to follow convention, you need to decide on git web hosting infrastructure before you start writing code. The tooling asks you for a URL the moment you run 'go mod init'. My preferred way of doing things is to start work on a project just on my computer and then maybe put it on one or more online git web host eventually, if the project goes anywhere. That order doesn't work with ideomatic Go. To work around this, I write mostly non-ideomatic Go where I use the name of the project instead of a URL as a package name.

* I view hosting infrastructure as incidental. I may throw a project on GitHub. I may change my mind and move it to Codeberg. I may move it to my own git forge. I may get tired of hosting my own git forge and move it to sr.ht. With Go, each of these moves requires a huge "touch a bunch of lines in every file" style commit if you're using the ideomatic "git web host as package identifier" style required to work with 'go get'. In other languages, it requires at most a readme change, and for dependencies, it requires at most a git submodule or package manifest change.

* Go requires that you use a Go-compatible git web host. Because Go decided to make URLs look like 'example.com/foo/bar/baz/qux', it has no way to determine which part of that is the git repo and which part is a subdirectory of the repo; should it 'git clone example.com/foo/bar/baz.git' and look at the 'qux' subfolder or should it 'git clone example.com/foo.git' and look for 'bar/baz/qux'? The only solution is for Go to make an HTTP request to 'example.com/foo/bar/baz/qux?go_get=1' and parse the response HTML and look for a Go-specific meta tag which tells Go what part is a git repo. This is an immense "layering violation" and extremely ugly hack in my opinion. This feels so unnecessary too, since this is an easily solvable problem: just make URLs look like 'example.com/foo/bar/baz:qux', so that Go knows to look for 'qux' in 'example.com/foo/bar/baz.git'.

* Private repos are a horrible experience. You need to convince Go to not look them up in Google's package checksum database, you need to convince Go to not get them from Google's caching infrastructure, you need to make a ~/.netrc file with credentials, you need a git host web frontend which understands and supports the way Go + .netrc makes authenticated GET requests. If any of these things are misconfigured, you get a cryptic error message about how terminal prompts are disabled on Google's servers. It's all very brittle and hard to debug, and the guidance has changed drastically over time (editing your global .gitignore to rewrite relevant HTTP sources to use SSH used to be the advice, but that had its own significant problems).

* It has the "feeling" of being decentralized since it's all just git URLs, but in reality, Go's tooling depends heavily on Google's centralized package cache and checksum infrastructure which has been introduced over time to smooth over foundational issues with the design.

I was once part of separating a complex project out of a company and moving it to its own infrastructure on a different domain name and git host. The Rust and C++ repositories were a breeze, just change the URL in a CI job. The node.js repositories required changing some references in the source code from one NPM org name to another but were otherwise painless. The Go repositories were absolute hell.

I have considered writing a blog post about all this.

Don't forget:

* No relative imports.

* The `require` directives from the `go.mod` files of your dependencies are always ignored.

Those two combined, mean that there's no easy way to fork a dependency. It's doable, but some of the maintenance overhead could have been avoided.

We don't even get a `go mod tidy` flag that lets us say, "yes, I understand the risks, just copy any `replace` directives that you find in my dependencies". With a flag like that, even if the `replace` directive is still copied everywhere, at least it's automatically copied during a routine `go mod tidy` invocation.

They already have `// indirect` comments, so those could have a `// indirect, replaced by X` comment or something like that.

Yea I’ve had troubles with relative imports when working on two or more go projects that had to be designed together.
I completely encourage you to write this as a blog post, you’ve articulated all of the concerns I had with Go’s package management wonderfully.
All great examples why I only touch Go when it cannot be avoided, like Docker related projects.
Thanks, I am lucky to avoid those issues working with go, but now I’m annoyed that those decisions were made, I have honestly never thought about the trouble that assigning URLs as import locators could cause but yea that would be a pain if we ever had to deal with any of that.

Thanks for your time writing that. A blog post would be great.

> Demo puts URLs to web infrastructure in source files, like Go.

This is optional, but also really, really handy for standalone scripts that don't need to come with a package-lock.json or deno.lock file (if you're not aware, Deno did a lot of changes to package management in later versions).