MediumSquare
Programming

Our Rust Rewrite Took Nine Months. Here Is What Actually Got Faster

The benchmark we bragged about improved 6x. The thing users noticed improved by 11 percent.

150

Two years ago my team in Wroclaw rewrote a pricing service from Python into Rust. We had good reasons. The service was slow under load, it used a lot of memory, and we had two engineers who were genuinely excited about Rust. We estimated four months. It took nine.

I am not writing this to say the rewrite was a mistake. It was mostly a success. But the story we told in the company all-hands was simpler than what really happened, and I think the real version is more useful.

The benchmark we celebrated

The core of the service is a function that takes a basket of products and computes a final price with discounts, taxes, and loyalty points. In Python, our microbenchmark ran that function about 1,800 times per second on one core. In Rust, it ran about 11,000 times per second. That 6x number went on a slide.

Memory dropped too. The Python service used around 900 megabytes per instance. The Rust one used about 70. We went from twelve instances to four.

Team seen from behind looking at a monitor wall
Team seen from behind looking at a monitor wall

What users actually felt

Here is the less exciting part. The median response time that clients saw went from 84 milliseconds to 75. An 11 percent improvement.

Why so small? Because the pricing function was never the slow part of the request. When we traced a real request end to end, about 60 percent of the time was spent waiting on two database queries and one call to a loyalty service owned by another team. Rust does not make the network faster.

We had known this, sort of. We had traces. But the CPU graphs were dramatic, and the rewrite felt like the obvious fix.

Empty highway at dawn with one distant car
Empty highway at dawn with one distant car

Where the nine months went

Roughly, the time broke down like this.

  • About three months on the core logic, which went well.
  • About two months on edge cases we discovered only by comparing outputs between old and new services on real traffic. Rounding rules for one country alone took two weeks.
  • About two months on the boring infrastructure: logging, metrics, configuration, error reporting, all of which the Python service had built up over five years.
  • About two months of running both in parallel, shadowing traffic, and slowly shifting load.

The infrastructure part is what everyone underestimates. A service is not just its business logic. It is all the small glue that makes it operable at 3am.

What I would do differently

If I did it again, I would fix the database queries first. When we finally did that, six months after the rewrite, median latency dropped from 75 milliseconds to 41. That one change, a missing index and a query that fetched 200 columns when it needed 9, mattered more for users than the whole rewrite.

I would still choose Rust for this service today. The memory savings are real money, roughly 1,400 euros a month in hosting. The type system has caught bugs in code review that would have reached production in Python.

But I have stopped putting microbenchmark numbers on slides. Now I put the user-facing latency next to them, so everyone can see both.

150
9 people clapped
Written byKrzysztof Nowak

Backend developer in Wroclaw. I keep a bug journal, argue about Rust, and test AI tools so my team does not have to.

More to read