Rust: Enterprise Services Need Not Suck

Rusty Sword, by Paulo Dala

I practice Barbarian Leadership. Standing on the back lines with hand in pocket giving orders is missing the fun. More importantly, knowledge is created on the cutting edge of action. People you work with know this. They value modern, non-hierarchical organizations where a leader dives into the fray, sword in hand, and gets to know intimately the problems and tools for solving them. So I dove into the fight despite knowing that it is “hard language”.

Rust is a relatively new programming language from Mozilla. It is compiled like C++, modern and functional (though not strictly so), and known for a catching many errors while you are still typing in the editor and before the code even reaches the testing phase. It is named after a fungus. Don’t ask.

I set out to use this new tool to see if the blade was well balanced and sharp. I needed to evaluate the hype and check how this can benefit our consulting clients at Futurice.

A Clear Winner

Rust smells right. That is an understatement- I fell in love. 30 years in the industry gives you a 6th sense for technical success and failure. I also picked Java as a winner in the early days. It was, but that time has passed. Now we have something better, and it will transform the productivity and reliability of enterprise service development much as Java did in it’s day. Now Rust has the ability to be the one, mainstream tool we use to solve many of today’s different domain problems. This matters for enterprises, because learning and combining many mismatched and proprietary tools is a big drag on developer productivity- almost as big as low reliability libraries, but we will get back to that.

Understand that my interest is in steering a technology adoption path that that is 1 to 3 years forward looking from now. Rust is not mainstream. Yet. Sure, it has won Stack Overflow’s coveted “Most Loved Language” for two years in a row (correction: three years in a row- thanks Raghav!) and adoption is steadily growing, but other languages remain more heavily used and have larger ecosystems of libraries to choose from. Rust is still young and stretching its legs, but it has a secret weapon, reliability, that has the potential to transform what we expect from digital services.

For other languages, reliability and associated maintainability over time usually means classic heavyweight TDD (Test Dragging Development) practices. These have been necessary, but always feel like a kludge, as if you grandmother keeps the room clean by listening for the noise every time she knocks a vase off the mantelpiece. A respected developer once confessed to me that despite the heavy cost in time, the real purpose was to keep less skilled developers within a big development team in line- they could not commit to the common repository unless they crawled through various circus hoops and re-wrote the tests to pass again. Keep that in mind in the contrast with Rust below.

Rust quickly starts to feel like a drug. You want more if, like me, you are obsessed with speed and productivity. To fully appreciate it you need to understand the problems Rust elegantly solves by design. Rust still offers system and unit tests, but they are typically much lighter and faster to right since the language by design has already covered many cases elegantly. It is a fine edged tool annealed over 8 years of experimental iteration by a brilliant team including several PhD s in Type Theory. OK, let’s not hold that against them.

Our current user of Rust is still limited but interest is growing. At Futurice Haskell remains the favorite for internal development when customer demands are not a concern. TypeScript and Elm on the web front are also held in high regard. We have done some data-driven web services and Vulkan and OpenGL 3D work in Rust and are moving toward it for embedded and robotics work. The web and database side is elegant if you stick to the most common libraries like Rocket and Diesel, but finding the best examples and style to work from remains a challenge in such a fast developing field.

Have your cake and eat it too

Rust is a contradiction. It is a compiled low level language that sometimes outperforms C and there is no contest with Node.js for web services. Yet it is also a first-class high level functional language with modern tools that focus on developer productivity. It has perhaps the most useful generic type system and lifetime management in the industry. This allows extensive automatic code analysis to catch errors early. It also reduces the amount of memory used to be in some cases one third that used in garbage collected languages. Server side applications in particular can scale much more elegantly and reduce cloud infrastructure costs when proper memory and thread use allow more full hardware utilization without missing a beat. No one ever complains that your service is too fast.

The result of this virtuous combination is light and fast enterprise services that accelerate and corner like a Koenigsegg while scaling. Keep in mind that enterprise services now need to be everywhere, and the new “full stack” targeted by Rust means embedded systems costing 3€ to desktops, phones, servers and even web pages. WebAssembly apps run as bytecode in your web browser. They are almost as fast as a native compiled application but, like any other web page, there is no installation required. Rust is well positioned to dominate this growing space. How much can you save with only writing your data objects and business logic once, then deploying flexibly where needed with just interface changes?

We aren’t fully there yet. Embedded frameworks like RTFM are still growing a broader base of device support, and WebAssembly 1.0 applications struggle with the limitations of the brand new container in all the major browsers so they must still be combined with JavaScript until support matures. However, consider this key difference in how WebAssembly services come into being: every piece of Rust code has pass the very strict compiler tests. Every piece of code, including the Rust libraries you pull in to make up many of the key functions of your application, is much more solid and maintainable.

Code Quality is Required

The point is the quality of code which comes out, not just from your development team but from all the helpful functions they pull in from others to achieve their goals. In the Rust ecosystem, best practices are required. Many of the things that in other languages are optional like edge cases and cleaning up unused resources that cause logic mistakes are handled for you, so entire classes of expensive TDD tests become obsolete. You need to work hard to get bad code off your desktop. This is hugely liberating to the team because they can “hack without fear”. Yes, developers need to think harder, and no not everyone want to work this way because it is different and they need a bit more skill and awareness of what their program will do so they can explicitly spell that out to the compiler.

But the results are clear: many developers love it. I would argue this saves time over a more forgiving language, but only if the reliability of the code matters or it will be maintained over time. A developer can look at a Rust function written by someone else and know exactly the preconditions and assumptions because they are spelled out explicitly in the method signature. The contract is explicit. But if you just need to quickly hack together a dancing monkey website that won’t be around very long anyway, go ahead and use something quick and dirty that works for that narrow use case. It is easier, and good enough.

Rapid Feedback Means Hard Is Easy

One of my math professors in engineering school had the nickname “No Mercy”. He enforced a strict and disciplined way of doing things. This allowed us to solve complex nonlinear differential equations we would otherwise struggle to approach. It sucked at first. He was the best. Rust is similar. The key is the most curmudgeonly opinionated and difficult compiler in the industry is analyzing your code live as you type in the editor. Fortunately this professor is always with you and will tutor you and often includes helpful suggestions when spitting back your early attempts covered in red ink. Think of it as the most strict code quality static analysis tool you have used, running live as you code. Like me, your developers must first journey through the humbling experience of finding out how many bad practices they have until the compiler educates them. Oops, but much better than going live with those issues undiscovered. And what a pleasure it is to bump a dependent library up to the newest version without fear.

Catching issues so early in the development cycle saves time, and the quality guarantees implicit in your code and by extension the libraries you rely on in the vibrant Rust ecosystem mean many unit and system tests become unnecessary. Linking in legacy libraries is usually part of the transition, but in the long run less tests saves a lot of time and money. This is perfect for businesses to raise their game and save money. You no longer have to trust that all your employees handle all corner cases. You are covered because the tooling is annoyingly thorough in surfacing problems before they become problems. Case not handled, type mismatch, index out of bounds, null pointer, dangling pointer, garbage collection pause, concurrent access violation- these simply vanish. The services your company offers are better for it, and your customers can feel the difference when your service hums like a new sports car engine without missing a beat.

Practical Steps

We need to be clear about the inevitable downside. Developers are supremely lazy and there are not yet many Rust developers out there. It tends to attract an elite crowd. This is natural- the future is already here, it is just not yet evenly distributed. Learning a different way of thinking is expensive and slow, often requiring a significant own time investment. User interface development with Rust is also currently immature, so engines and back end tools are more suitable for early use cases. It is not for every project, but the revolution has already started so take a moment to check for yourself to see if it smells right for some of what you do. I predict that will steadily increase as you learn to expect higher quality from all your projects.

A step by step approach to anything new is wise. When you are considering your next project, gain some familiarity with Rust on a small scale and evaluate where it may offer some differential advantage to your business. Move systematically and start with simple tools to follow the process through to completion at minimum cost. Make sure the libraries you will use support all the features you will need. The sort of small tasks you might script or wire together with Python are a good place to start. A good digital change consultant can help you identify the low hanging wins, train your staff in a boot camp kickoff, get wet with you in an initial joint project, then periodically mentor your team. You, and your customers, will be glad you did.

Paul Houghton, @mobile_rat
Director, Wizardry and Development
Futurice