For the past two years, Bun has been one of the most exciting technologies in our stack.
Fast startup times, excellent TypeScript ergonomics, lower resource consumption, and a clear focus on performance made it an obvious choice for a startup like ours. We are constantly forced to move faster, optimize harder, and squeeze every possible bit of efficiency from our infrastructure. Bun promised exactly that, and in many ways, it delivered.
But today, we are making the decision to move away from Bun as the primary runtime for our infrastructure.
Not because Bun is moving from Zig to Rust.
Not because we suddenly distrust the Bun team.
And certainly not because of performance.
We are leaving because of how the transition happened, how quickly it evolved, and especially how it was communicated.
Why Bun Made Sense for Us
By the end of 2024, we were building a new payment ecosystem while already operating mission-critical services for more than 300 companies across Brazil, Chile, Argentina, and the United States.
These companies rely on our infrastructure to be:
- Stable
- Predictable
- Consistent
- Secure
- Highly performant
In payments, standards are unforgiving.
Downtime is almost unacceptable.
Runtime crashes are completely unacceptable.
Unpredictable behavior under heavy load is unacceptable.
At the time, we had services running across multiple runtimes and ecosystems: Golang, Node.js, Deno, and Bun.
Golang would have been the safest long-term infrastructure choice, but we simply did not have the time necessary to move at the speed required for the project. TypeScript was the obvious direction, and Bun had already been under evaluation internally for more than a year through side projects and microservices.
We had tested the good and the bad:
- Edge cases
- Runtime behavior under load
- Compatibility issues
- Operational concerns
- Unexpected side effects
After weeks of planning and evaluation, we made the decision to adopt Bun for the new platform fully aware that switching runtimes later would be expensive.
And honestly?
It worked.
Bun in Production
Since deploying Bun into production, we experienced remarkably few issues.
No major incidents.
No catastrophic runtime instability.
No serious operational concerns.
There were bugs and edge cases, as expected from a relatively young runtime, but nothing severe enough to make us uncomfortable running Bun in production.
Until the Rust rewrite.
The Rust Rewrite Changed the Risk Profile
The Rust rewrite initially appeared to be experimental, something interesting to follow, but not something that would immediately impact production deployments.
Then it accelerated.
Fast.
Much faster than we expected.
Before long, major portions of the runtime had evolved significantly, and the rewrite started becoming part of the production trajectory of Bun itself.
At that point, we had to stop and reassess.
We reviewed the repository, analyzed the migration strategy, and tried to understand the long-term operational implications of the transition. What we found increased our concerns considerably.
Today, the runtime contains:
- Pending migrations
- Mixed implementations
- Wrappers around existing Zig code
- Transitional layers between architectures
To be clear: this is normal during large rewrites.
The issue is not that Bun is being rewritten in Rust.
The issue is that, from an infrastructure perspective, this temporarily changes the runtime’s stability profile.
A transitional architecture introduces additional layers, additional uncertainty, and additional opportunities for unexpected behavior, especially under the kind of production workloads we operate.
We fully understand that this is temporary.
But we currently have:
- No complete roadmap
- No definitive migration timeline
- No clear stability milestone for the rewritten architecture
For many teams, that level of uncertainty may be acceptable.
For us, it is not.
From “Stable” Back to “Beta”
Internally, this changed Bun’s classification for us.
Before the rewrite acceleration, Bun had gradually earned its way from “experimental” to “production-capable” in our environment.
After reassessing the transition, we had to move it back into what we consider a “operational-beta” category.
And unfortunately, that category is incompatible with our infrastructure standards.
At that point, we only had two realistic choices:
- Continue running an older Zig-based version without receiving future patches and improvements
- Migrate away from Bun until the new architecture matures
Running outdated infrastructure conflicts directly with our engineering principles and security posture.
So once again, the decision was effectively made for us.
We are moving off Bun.
This Is Not an Attack on Bun
We still trust Jarred and the Bun team.
We trust Rust.
And we genuinely believe Bun has the potential to become one of the most important runtimes in the JavaScript ecosystem.
This decision is not ideological.
It is operational.
When you are responsible for critical financial infrastructure, you optimize for predictability above everything else. Even small increases in uncertainty can become unacceptable at scale.
As soon as the Rust architecture becomes mature, stable, and operationally proven under our standards, we will absolutely evaluate Bun again.
And honestly, there is a very high chance we return.
But for now, predictability and stability wins.
Top comments (5)
The part I'm missing in this post is, leaving Bun for? I read the post a few times and I couldn't find the replacement.
I can understand the security aspect. But engineering principles? The application is running in production, why update at all if there are no security issues? Any upgrade brings a risk of the unknown. That is why most people that build critical applications are conservative.
How much time would you needed more to finish the project? You took weeks to decide to go for Bun. Couldn't you spend that same time on Go?
The reclassification from "production-capable" back to "operational-beta" is the key sentence in this whole article, and most runtime developers would rather bury it than lead with it.
I get it though. We did something similar when our own storage engine went through a major internal refactor — had to tell customers "look, the old version is stable, the new version is not ready yet, don't touch it even though it sounds better on paper." The sales team hated it. The engineering team was right.
The multi-runtime approach is smart in theory but painful in practice. We run Golang for the microcontroller tooling, Node for the cloud bridge, and Rust for anything that touches the actual robot control loop. The problem isn't the languages — it's the operational surface area. Every runtime has its own failure modes, its own memory behavior under pressure, its own edge cases. And in payment infrastructure or robot control, edge cases are where you bleed money or break things.
The comment about transitional layers between architectures is the part nobody talks about when they're excited about a rewrite. A rewritten system that still has wrappers around the old code isn't a rewrite — it's a hybrid. And hybrids are harder to reason about than either side alone, because you have to hold two mental models at once.
The payment industry standard of "stability over novelty" exists because the cost of failure is asymmetric. A framework that restarts unexpectedly in a web app costs a user session. The same thing in payment processing costs something else entirely.
What was the breaking point that made the Zig→Rust transition harder to trust than anticipated?
No clear decision making process is declared in the article on what initiated the migration from Bun to Rust, or what was exactly the pain-points of Bun that Rust was supposed to solve if you move to that. Also in the teams I worked, you cannot randomly go for something big like migrating from language to language, you have to have a proposal of the benefits you get from it, and even then, the Product and Sale's Team might push back in a fight because they want their own features and bug fixes, not another source of uncertainty.
Thank you for the like.
I think you might have misread the post. It is Bun that moved from Zig to Rust. The post is addressing the choice that they made to use Bun, and that internal move from the runtime causes problems.
This is why in my comment the first thing I mentioned is that their new runtime/language is not unveiled. I suspect they move to another Javascript runtime, because moving to a new language would be more work.
it's interesting to see how communication can impact tech decisions, even with strong tools like Bun. at Moonshift, we focus on making full-stack app deployments easy - get a next.js + postgres + auth build live in about 7 minutes, plus you own the code on your github. if you're curious, happy to offer a free build to try it out.