We rewrote a Go service in Rust and our velocity tanked for a quarter.
For a full quarter, our feature velocity significantly dropped after we re-implemented a Go service using Rust. The performance improvements actually happened.
Why we did it in the first place
We are a small startup. Each engineer is important, and each week is even more important. Our backend was built using Go, which was performing well. It was fast, reliable, and we could easily find resources to hire. However, we became infected with that fever. The phrase "Rewrite it in Rust" was being used in all kinds of situations, and it sounded very appealing with its promises of memory safety, no garbage collector pauses, and blazing speed. We told ourselves it was an investment in the future. What we actually bought was a quarter of silence.
The numbers nobody warns you about
I may not have the exact metrics we use internally, but I can direct you to an individual who shared accurate calculations transparently. In a retrospective from November 2025, engineering manager Noah Byteforge wrote that a Node.js-to-Rust backend rewrite "dropped API response times from 340ms to 28ms. That's 12.1x faster."
And the other metric:
- A 65% decrease in sprint velocity.
- They didn't deliver a single story point for three weeks.
- The time it took to send out new features increased by 185%.
- The time it took for pull requests to be processed increased by 320%.
- Scores from the "I feel productive" survey dropped from 8.2 to 4.1.
Most importantly, the kicker is what he says in his own words: "We'd won the technical battle and lost the war that actually mattered." He also admits that if he had been forthright about the 6-12 month per engineer ramp, "the business case would've fallen apart immediately."
That retrospective was so relatable, it read like our own diary. The battles with the borrow checker and the compile times just snuck entire weeks away from us. The wins were real. That's the trap.
I must give credit to Rust because the safety benefits are not exaggerated. The rewrite done by Byteforge reduced the memory footprint by 80%, going from 2.1GB to 420MB. CPU utilization also went down to 8%, and there were no more crashes related to memory.
Similarly, Discord experienced this in February 2020, and had to rewrite their Read States service because Go's GC pauses kept interrupting it. This was because their use of Go would inadvertently heap allocate every time it was invoked, triggering GC pauses every two minutes that caused significant disruptions.
A developer forum comment that has been widely cited regarding the rewrite says: "Rust makes some common, poor-performance things difficult... It's more work up front." The "up front" is clearly doing a lot of heavy lifting here. It's not that Rust is no good. It's that, for a startup, "up front" really translates to "at the expense of the critical differentiating features that are keeping us in business."
The teams who did it right didn't do a rewrite
Here is what I still remember. The businesses that made it through this transition, for the most part, did not accept the complete rewrite. By rewriting Turborepo from Go to Rust over the course of the past year, Vercel faced the mammoth task of rebuilding a significant portion of their architecture... while keeping the business running. "A full rewrite is an extraordinarily expensive endeavor, not to be embarked upon lightly," co-founder Guillermo Rauch admits.
As we've seen already, when it comes to rewrites it's often not the technical challenges that eclipse the plan; it's the logistical ones.
InfluxData took a different approach, it paid for it with time. CTO Paul Dix started a rewrite of the InfluxDB core from Go to Rust in 2020, and it wasn't completed until 2024. It took us more than four years of intensive engineering work to get to the same functional level as the other solutions on the market. Only a well-funded, existing company can afford to make such a bet. We are not InfluxData. We had a runway, not a research budget.
What I'd tell past me
The real lesson to learn here is not "Rust bad." It's that a language migration should be treated as a business decision disguised in engineering clothes.
Here's the truth I avoided:
- Multiply the per-engineer ramp time by every engineer on the project.
- Add the features you won't ship during that ramp.
- Ask if your customers care about 28ms vs 340ms, or if they care about the thing you didn't build.
The answer was uncomfortable for us. Response times were not the reason why people were leaving. It was the missing features.
If you're in real pain - memory leak, GC spike, real performance wall - do it incrementally. Strangle the old service one endpoint at a time. Keep shipping. Only do a full rewrite if you have the time and money to build a quarter of what you have now. The "Rewrite it in Rust" people always seem to forget to mention that. ๐
So, let me ask you this: Was there ever a decision that was technically right, but in the end, it's what caused your team to lose what was truly important?
Comments
No comments yet. Start the discussion.