Rust for Microservices: One company’s adoption journey from .NET

Rust for Microservices: One company’s adoption journey from .NET

Rust is excellent for systems programming but a less obvious choice for general purposes like implementing microservices.

At QCon London though, principal engineer Luca Palmieri, from open banking company TrueLayer, described how and why his development team moved from being primarily .NET coders to programming new microservices in Rust.

TrueLayer Principal Engineer Luca Palmieri speaking at QCon London

In May 2020 none of TrueLayer’s 30 developers used Rust. By December 2021, the team had grown to 100 developers, 23 of whom use Rust, with 44 of its 164 microservices written in Rust, comprising over 200,000 lines of code and 86 crates (Rust binaries).

Why? The journey began in 2019 when latency problems in an API were traced to garbage collection issues in .NET, the details of which are “gnarly,” Palmieri said, and fixed by upgrading to a later version of .NET.

At the time, however, frustrations with the issue led developers to experiment with a proof of concept implementation in Rust, which does not use garbage collection, addressing just this part of the service. It performed beautifully and “the latency was extremely flat,” said Palmieri.

This code was never deployed, but inspired the team to work more with the language. They interacted with the Rust community, hosting meetings of the Rust London User Group and running training workshops. By end of 2020, the company was ready to implement new services using Rust rather than C#.

Risk vs reward

Adopting new technology is risky on all sorts of levels, Palmieri said, which is why dull but well-established technology is preferred by many organisations. Other factors which may count against Rust include an immature ecosystem of libraries and community knowledge, skills shortage, and the  difficulty of retraining team members. Migration from C# to Rust is harder than between C# and Java, for example, because of fundamental differences in the language design.

It is only worth it, Palmieri said, because of the strong benefits. Performance is one but not the most important. The biggest benefit, he said, is what he called composition without “surprises”, where the unit of composition is a function. When using a function, developers need to know what is the expected input structure, whether input is mutated, what is returned, and what exceptions it may raise.

With Rust, this is baked into the language. This is one of several aspects of Rust that reduce dependence on unreliable mechanisms like comments and documentation, in favour of compiler-enforced checks. The benefits go beyond this, to the way the culture of  the language impacts the culture of the team and their approach to development.

A function in Rust enforces numerous checks that reduce coding errors (slide from QCon)

Palmieri, who has written a book called Zero To Production In Rust, said that despite the notorious Rust learning curve, they have found that C# or JavaScript developers can become productive in Rust “in just a couple of months.”

The key, he said, is that it is not necessary to learn the entire language, but to focus on the core subset that is required for what a developer needs to work on. Interacting with the community has also been beneficial, and despite the shortage of skilled programmers, the fact that many developers specifically want to learn and work with Rust makes it easier to recruit.