I started learning Rust and I love the language a lot, I tried Golang and I really didn't enjoy programming in it. I'm am currently working on a new business idea and I was planning to use Rust to write the REST API in.
Does anyone have experience using Rust for the backend? I read comments from people two years ago that said "Rust isn't good for backend development, It wasn't built for that".
The thing is I see so many new backend products being built in Rust especially Blockchain related services which is the domain I'm in.
What are your thoughts on this? Am I going to go down a painful road with rust and web development?
At Oxide we are doing backend development in Rust, with our own framework: https://github.com/oxidecomputer/dropshot/#dropshot
Dropshot sounds interesting, I really like the integrated OpenAPI support. And it is extremely well documented.
It is at version 0.5. How stable is it already?
I am not sure how stable it is, but I would imagine that unless there’s a guarantee, the answer is “no guarantees” :)
I read comments from people two years ago that said "Rust isn't good for backend development, It wasn't built for that".
That really surprises me. Do you have a link?
Even two years ago there were success stories about porting a service to rust and getting lower latencies.
I honestly lost the link but they guy was basically saying Rust is intended for systems programming. Even though is was almost 3 years ago I think most of the web frameworks at that time have matured a lot.
There’s a good argument to be made that Rust’s ownership and lifetime model, while amazing and an excellent tool for writing efficient memory–safe programs, is not always the best tool for the job. This is not due to any deficiencies of Rust, but only because of the excellence of other available languages.
Rust for web backends is not the obvious choice, while Rust is the obvious choice for anything lower–level.
I would note that Rust can adapt nicely to situations where performance isn't as important:
.clone() and returning by value will avoid most lifetime issues.
Ownership is perhaps a bit more subtle -- especially when you'd have cyclic data-structures in JS/Python -- but for backends I generally find that ownership is not an issue as most data just flows in and out in a straightforward linear fashion.
C was also 'intended' for systems programming and managed to sneak into everything
And yeah I think async has gotten better in the last 3 years, which is a big factor in how easy it is to do web backend (HTTP server, DB client) stuff
How is that state of Authentication in Rust? Do I have to implement everything myself or is there accouple libraries that will assist me. If not, then I'll just open source my solution that I'll create for my product.
Hmm I must know the old ways then, I'll research this new way of Authentication, I never heard it before.
Zero Trust is marketing speak for securing all systems across users-- human and machine. It's not a modern new invention of technology but a polished presentation of currently established solutions.
Writing your own authentication and authorization is very costly. I rolled my own because of timing (early adopter of rust for web dev). Avoiding that work by using security services saves so much effort. I haven't carefully studied the Ory projects to attest to their quality but others seem to have gotten on fine with them. Also, oso is a new addition for authorization.
Security is a huge time sink.
Not op, but let me ask a question too. I'm really interested in trying rust for backend but it has always seemed to me that rust isn't quite there yet.
So, let's say I need to build a generic rest API. I need libraries for:
Authentication. Or maybe integration with authentication services.
Scheduled tasks ( or a cron file generator)
Testing ( I mean structured tests and libraries for stubbing)
Integration with telemetry services(newrelic/datadog)
So, can rust respond to those requirements?
rocket can do a lot of these tasks on it's own
I've been writing APIs (RESTful JSON and gRPC) with Rust for the past two years and generally liked the experience. It was a small, basically-one-man-show for a bit which gave me lots of flexibility, so we could absorb things like the
async intro and a couple of breaking changes between
actix-web versions without too much trouble. I also shy away from a Rails/Django-y approach these days, as most of what I'm working on is well outside the standard CRUD + web templates setup that those frameworks excel at.
Outside of the language itself, the frameworks I've used have been
tonic. I wouldn't choose
actix again, I don't think... when I used it, it was in a bit of a strange place between "batteries included" and "implement this complex trait yourself, good luck". Hopefully that has improved, but I'd probably reach for something like
tide or even
hyper + a router for a smaller web framework that would tend towards a lower level (and hopefully do so with a bit more simplicity along the way).
rocket would be easiest by far for someone coming from e.g. Django, and I really like the direction and management of the project. Just be aware that it's pretty macro-heavy, which means that you have to do a bit more learning beyond Rust-the-language into Rocket-the-collection-of-macros. But those macros are definitely pretty! And
rocket has a great middleware and auth layer (in a way that
actix-web didn't when I last worked with it). But you're giving up some sharpness in your tool along the way between the macros and the general bent towards full-stack-ness (in the spirit of e.g. Rails instead of e.g. Sinatra).
By far my favorite backend web API framework has been
tonic, although that's for
gRPC specifically. If you're not wed to REST, I'd encourage you to give that a try.
I was surprised how much I liked the workflow.
In my case, speed was not a significant reason for the switch. I didn't even benchmark gRPC vs serde, since the performance of either was sufficient for my use-case.
The biggest reason for the switch was the cross-language nature of protocol buffers (which could be replicated with any number of
proto3 alternatives) and the batteries-included support for bidirectional streaming across server-side languages + server -> client streaming in web.
As I've worked with it more, I've really enjoyed the workflow of building new features by making a change in the protocol and then following the compiler out from that point (either "forwards" to the generated clients or "backwards" to the generated messages and service trait). You could certainly replicate that workflow by sharing a library of structs, but only if all of your API consumers are in Rust-land.
I've deployed several production backend services with Rust. I've used tokio + actix, tokio + warp, but my favorite so far has been async_std + tide. Async_std + tide isn't nearly as performant as the Tokio and actix (these two libraries are designed for SPEED). I would prototype with tide and if your service starts taking a real beating, then you can easily migrate to actix for a 30% perf bump.
Async_std + tide is very simple to get up and running - the minimum app is 3-4 lines and it has all the things you'd want from a web framework. The docs aren't as great, but the interfaces are really straightforward compared to Actix/Warp. It's really simple to use (dummy proof) and gives just the right amount of control without being too difficult to play with.
I've really enjoyed the experience of sqlx + typed-query for DB stuff. serde_json is super handy and the built-in error handling is way better than Go/Ts. My frontends are still react, but I'm working on changing that ;).
Overall, 10/10 experience for the basic CRUD app.
That's really good! I'm also using React for my dashboard that will manage enterprise accounts away from regular users accounts.
We built our backend in Rust and it works great!
I think you'll be fine.
async is still a bit tricky, but totally do-able.
What company do you work for/ what kind of service did you build with rust?
And what web framework did you use?
It's a common high-level langage, with lot of developers, a solid community, lot of packages, it will make your product cheaper and faster to dev at start.
Rust is a low level langage, it require a more fundamental understanding of how computer work.
I started Rust without a solid mental model of CPU and RAM, without any C/C++ knowledge, from scratch, and it take me years to get the "Eureka !".
Meanwhile, in Rust, if I want to do a parallel computation that share state, I can create 2 threads with the standard library, but then I need to wrap all my type with Mutex<T> because bad news ... it's not safe to share state in thread ... or I can move my data, but I can't because it's shared in more than 1 thread and thus multiple thread mean multiple owner at same time ... so let's go for Mutex and don't move data, just send reference. But then I need to be sure my reference has 'static lifetime, otherwise my data will be destroyed while thread has a reference to use theses data ... Rust don't allow that, compiler error ... but I can use library-proprietary feature like scoped thread ... or maybe go a step back, I can simply wrap everything in Arc<Mutex<T>> to do reference couting and share state in multiple thread, or I can use library-proprietary async runtime that will do scheduling itself and don't go with threads but with async function. There's to many road, if you don't understand the pro and cons of everything, you are stuck in a giant pile of mess. But if you understand why Rust won't let you do [insert-something], it will make you a better developer in all langages.
Also, if you want to write a Rest API, don't forget the OpenAPI protocol, a really nice feature to have.
This is not true. Those Promises will run concurrently, assuming they're well-behaved asynchronous code, but they will not be executed in parallel. Node gives the programmer virtually zero control over parallelism, and there is no way to have shared-state parallelism. Shared-state parallelism is the most insidious thing in all of computing, and most high-level languages do everything they can to prevent you from doing it because they can't keep you safe if you do.
Hey what about Go? Why do you recommend Node over Go?
Because I was used to Node.js (and then Deno), and it's still used and good to know that you can use your front-end skill in backend with the same langage.
At this time, Go was really a nice addition for backend service. All of my friends who writted C started to love it. Didn't found any usage since Node.js was competing with it and at this time I didn't have any "performance application" to do. But like I said, my coworker and friends who used C really liked Go.
Hey thanks for the detailed response. So would you say you'd recommend Go over Node for a newcomer to both?
I think it is definitely possible... and the language is very well suited for web and backend development. Things like authentication and similar can be compiler proven if done right. Injections can be avoided using the compiler and so on. There are no garbage collection latencies. So to build a backend to last I'd say it is my favorite language.
It is not fast to do some prototyping though as there is no native "admin-interface". Django or similar are much faster to get something working.
If you want to build it in rust I highly recommend: https://www.lpalmieri.com/posts/2020-05-24-zero-to-production-0-foreword/ and the following chapters... He describes the whole development process including setup, testing, observability, error handling and much more. He does explain everything in such a way that I guess you should read the articles to judge if it is suited for your purpose or not. - Also don't hesitate to buy his book which is basically what he wrote in the blogposts.
what about Rust in comparison to Go for backend development
I never used go so my opinion is not really solid. But you can checkout this: https://discord.com/blog/why-discord-is-switching-from-go-to-rust
I guess the essence is go is easier and faster to first deploy, rust is harder and takes longer to develop (especially when learning). With rust you can avoid some errors by compiler, where you have to do so in go by genius or testing... I guess the Garbadegcollector performance hit only hits really big deployments.
I do quite a bit of backend rust for my side projects, and it's a mixed bag. I use rocket personally, I'm not in love with it but it gets the job done. Async is a bit weird currently. I'm on 0.5 rocket to take advantage of async because I want to make async requests from some of my endpoints, but that means docs are lacking and some projects that integrate with rocket, like Juniper, need some manual tweaking, until 0.5 lands and other projects catch up.
You'll have to do a bit more manual work for pretty much everything, compared to like django or something. For example for auth I use jsonwebtoken, which is great but its not integrated with Rocket to the degree auth solutions are integrated into django, express.js, etc, so it requires a bit of glue work.
Database stuff is alright. Diesel is definitely the best solution I've found, but its hard to learn, gives confusing error messages sometimes, and the migration and modeling stuff isn't as integrated as it is with Django/Rails, where you can just change your models and the migrations get generated. Definitely slows down the pace a bit when your models are changing often.
Some libraries just aren't as mature as libraries in other ecosystems. I use Stripe and I have to run with a mix of vanilla reqwest queries, and using the stripe-rs library, because it doesn't cover all the use cases I have.
Compilation times are kind of annoying, I've only got a few thousand lines but compilation time was at like 15 seconds until I did some linker changes, which definitely slowed down the pace of development a bit. After spending some time on it, its down to ~5 seconds, which is very acceptable for me, but it did frustrate me for a while.
All that being said, I'd still choose Rust over any other language, I'm not trying to discourage anyone from using it. But if you're coming from like Django or Rails, you will have to operate at a different level than you're used to, and things that require a one-line import in those frameworks can take an hour or two.
Why would you still choose Rust then?
Besides the drawbacks of the other languages, there’s also a ton of rust stuff I like; I won’t go over all the pluses because there’s already tons of “this is why rust is awesome” content out there. But basically all my complaints boil down to “we’re early”, which is something that I’m comfortable with; the libraries are improving all the time, so everything that’s slightly annoying is getting less annoying over time.
I've tried it about a year ago and didn't like it, and I'm currently prototyping a service again.
So, it works, but it's not as focused on developer happiness and productivity as I'd like. You can do everything, but important helpers that I love in other languages and frameworks are missing. The IDE experience has increased a lot, so I'm loving that now. SQLx is pretty good, but not a full ORM, if that's what you like. There's Diesel, but that's not async.
Then, there's inconveniences. actix-web has been on 4.0-beta with Tokio 1.0 for a while, but libraries like actix-session are still based on actix-web 3, so you don't really get even the most basic session capabilities out of the box. I love Tide, personally, but its community is much smaller.
So, it really depends. Do you need to be quick at prototyping something with all the help of a big framework? That doesn't exist in Rust, yet. Things like Rails, or Django, or even Phoenix are missing. If you want to do more yourself, and want a lower level approach, the Rust experience is pretty good already.
My other alternative is Golang and I honestly don't want to use a big framework like Django.
I'm also fine using raw SQL to on the backend which could work and SQLx looks cool too!
Basically I rather learn a set of tools that will allow me to customize a backend to the way I need 100%.
I personally dread every time I have to write go, but the language was basically designed from the ground up to get junior developers writing backend services quickly so if that's exactly what you're looking for then it is the obvious choice.
If you're just looking to use this project to learn the language then you can write backend services in rust and it's a much nicer skill to have in the end.
Exactly the same with go, I never had the excitement I had with Rust when I was coding go. Basically I'm looking for a language that I can write all my future backend products in. I'm not looking at this from getting a programming job perspective because Golang had more jobs. I'm picking the next language for solely building all the ideas for products I have and seeing which Idea makes some money. That's kind of why I gravitated toward Rust.
I agree. When I was comparing both languages I was just drawn to Rust, I really didn't like the coding philosophy in Golang. It was to simple way to repetitive so DRY doesn't exist in that language.
hey. update? What did you end up choosing and why. How did it go?
Rust has a larger threshold than other languages, which can be a general issue. I think it's fine!
You will be moving into a new ecosystem you never used, and that will always be painful at times.
I use actix-web and sqlx. I'm really happy with both, but actix-web is in beta and sqlx uses a lot of feature flags that you need to set, so there can be some stumbles on the road when setting up the configuration.
To get started, you can do a minimal amount of error handling with unwrap, then expect, then map_err, then using traits to convert errors.
Same with logging, you can start with print macros, then move to proper logging of the responses, then move to structured logging.
I'd recommend buying the book "From zero to production in rust" https://www.zero2prod.com/index.html.
If you are setting up CI/CD, here's an example of how I do it based on feedback here on Reddit: https://github.com/marcusradell/monadium/blob/main/.github/workflows/cd.yml.
I think Rust will be my main lang for web backends, but I just want to be transparent that there is a switch-over cost and a generally slower development speed. The slowdown I see comes from the fact that I actually need to handle every damn error, while in in node.js I would have pushed a buggy feature to production faster and go "whoopsie!" when it crashes.
Hey can you give a rough estimate of the difference in development speed between Node/Rust? Thanks
Sure, can you define development speed?
Well, I'm just pointing out where you mentioned there is "generally slower development speed" for Rust. I know it was awhile ago so you probably forgot that you wrote that. Assume we're speaking of a backend web development project where you'd be using Rust + Actix Web vs Node + ExpressJs. How much longer will Rust take to write, generally speaking of course. 2x's, 3x's etc. Thanks
Haha, yeah I totally forgot what I wrote :-P
I'd say that actually producing similar code for a basic crud web server is about the same in both JS and Rust for the normal success-case workflow.
Error handling in JS is pretty non-existant and you need external libs just to serialize Error-based classes. I'd say it takes about x4 more times to handle errors in JS.
The Rust stack requires more effort to setup the infra and CI/CD for. Let's say 4x more.
We have also found issues in Rust where complexity skyrockets because of a library type signature.
For example, we wanted to return a preconfigured actix-web app. We had to ask on the Discord server to solve it. That was a 4x slowdown.
We also wanted to do a preconfigured layer for sqlx that works for both mysql and postgres. But we aren't proficient enough yet. We duplicated the code and moved on. Not a pleasant experience. 4x slowdown.
As we get better, these cases become rarer. So let's say that it's a 10% chance of a 4x slowdown for some specific features for us right now.
The main speed-up for us is that our Rust code often just works. We do less rework of done features. Refactoring is smoother as well. Let's say JS is 4x buggier and 2x slower to refactor.
Now will everyone have the same experience? Nah.
I can code fast and with high quality in JS/TS as long as I'm solo. But in most teams, lots of clean code architecture discussions tend to just land better in Rust.
In JS, I have had so many ridiculous discussions on why mutating globals is bad, why we should write tests, why types are useful, why performance matters, etc.
I find that Rust sets a good foundation to build a high-performing team culture on.
We use Dart and Flutter on the frontend, and I have the same issues. I tend to struggle to explain the value of clean code because of the language.
Hey thanks really appreciate it
If there's something else you are wondering, feel free to DM me here or @marcusradell on twitter. I'd love to help more fellow Rustaceans!
Oh also, has Actix improved since you last wrote this comment up here a year ago?
Yes, the issue feels like a solved one now.
You will probably notice it at some point in the Rust ecosystem though and be confused over the error message the first time. But not a big issue anymore IMO.
I tried to write our backend at my current co in Rust last year and it was very difficult. I started writing some backend stuff in the last month again and it's vastly improved. You will miss out on specific comforts from other languages, but the pace of improvement is very fast.
The ORM stuff wasn't nearly as stable as it is now, so database stuff was too big a pain to keep moving forward with it.
I have recently be transitioning our Node web server to Rust. I cannot recommend it enough.
The way Rust forces you to structure your code is truly a blessing. We personally use GraphQL over REST (if appropriate I'd certainly recommend it for the ease of use and type safety). Compared to JS GraphQL integrations, the use traits and macros feel much less hacky that the various workarounds sometimes required in Node.
Error handling can also be done very well, making it very clear cut what errors are internal and what are shown.
This is a neat writeup https://www.reddit.com/r/rust/comments/cdg5b4/rust_in_the_on_of_the_biggest_music_festival/
I am writing a small backend with Rust now. I am using Routerify and sqlx (postgres) with tokio and postgresql. I am also using reqwest for interacting with Slack APIs. Writing testable code seems to be a bit difficult. For example, if you'd like to have a test harness that automatically rolls back transactions after the tests are done, we need to inject an sqlx executor to my CQRS layer. While it is definitely possible, there aren't many sample code bases or documentation that makes it apparent. I find the project enjoyable. But then again, I found learning rust enjoyable.
Why rust and no Python? What are the technical reasons you need a compiled language?
Note: if you answer “speed” and you did not measured the effective speed up, you gave the wrong answer
I'm mostly doing Blockchain based products and I saw Rust was a big player in it due to frameworks like Substrate & ICP that were written in Rust and support Rust so, I decided to go with it because of the features I want to add down the line that will use it. Also WASM has great support in Rust. So those were my main reasons I wanted to pick Rust as my server language.
We're currently in the process of moving parts of our PHP backend to Rust, and I personally think that's actually one of the strongest sides of Rust. Before that I used it for UI development, where it's a real pain due to the lack of adequate middleware.
We're even doing verification steps like SQL schema validation at compile time, which means that if it compiles there's a very good chance that it's going to work.
I think it's great if you need the performance but others like Go are faster to develop with while still being very performant. I'd probably choose Go for most services even though I love Rust
If you're working on a new business idea, I recommend you use the language you are most proficient in and the best available open source libraries and frameworks available. Adopting Rust will cost you time and effort that can be better spent on business development.
What leads you to think that it will only cost you two months? What if I said that it can cost twice or more, depending on what your requirements are and what decisions you make?
Rust looked very similar to Swift so I didn't think it would take that long, but I do know a decent amount of TypeScript.
I looked at Tide before looks cool but Rocket had really nice documentation.
I'm prototyping a new backend in Rust right now. It was surprisingly simple to get a basic API receiver set up with actix web, using serde with structs to represent the various payloads on their endpoints. I like that I can keep things logically grouped in modules, like a main.rs for bootstrapping the whole thing, api.rs for the API routing/mapping and payload structs, etc. Plus the built-in unit testing of each module is helping me prove out the components too.
It's going to replace a Java backend, and I'm already liking the difference in startup time (naturally). actix made it dead easy to wrap in logging too. Questions to be resolved: debugging, runtime management (we heavily use JMX in our legacy products). But we'll get there. There is certainly enough promise here that we are proceeding. Next up is figuring out if I want to use sqlite directly, or go through something like sqlx.
I'm not happy.
Perfectly happy with Rust.
But this project is on a temporary funding hiatus, and to make matters worse, the future prospective clients demand implementation languages that have available external security & quality analysis tools of their choosing.
Which means we are going to be constrained to lowest common denominator languages supported by tools like Fortify.
At least I learned a lot. :/
We are using Rust for Backend with Graphql on ApiGateway. The bottom line it's great. We rarely ever face codebase related bugs and our fixes are mainly due to external environment.
I love how rust eliminates side effects and the rust compiler errors are the best and most comprehensive I've seen.
I just finished writing a server for my final project at uni. We used Rocket, Rusqlite and React. I didn't intend to use React, it was chosen by the frontend team, but we managed to integrate it quite well. We used JSON to communicate between the frontend and backend, which was super easy because of Serde.
If I had to do it again, I would probably do the same thing. However I think I would just use the latest unstable version of Rocket, and switch to SQLx or Diesel.
All in all I think Rust just makes sense for building servers, especially as crates mature. I think Rocket is really awesome and I'm looking forward to it landing on stable Rust.
Go for it dude Rust back on the back end is about as fast as you can get, it will require boilerplate tho
At our company we've been using Rust for one of our backend service for a year and I love it. The general experience of working with Rust as a language for the backend has been amazing. Would never go with anything else at this point for a service that only needs to interact with the world using a HTTP API.
For our stack we went with
rocketlooked good, but felt like they required too much boilerplate for everything and I've never been too fond of big frameworks. The choice between
warpwas much closer, but in the end
tidejust felt a bit more natural for me.
On the database side I went with
sqlxsince I felt like the extra ORM features
dieselprovided weren't worth the extra complexity it added. Writing manual SQL queries and keeping models up to date with it isn't that hard. And
sqlxhave good migration support for updating the database schemas, which I feel is the most important thing together with compile time query validation.
Parsing input from external services, and then conversion to the data models required for the business logic and then converting it again to JSON for output is easy and secure with
serde. Never felt as confident in the data parsing and usage in any other language.
Only issue I've had is figuring out how to do error handling. Tried a couple of different options over the last year, and currently using
ErrorKindenum attached to application errors to keep track of the various errors. That works nicely for now. The errors keep track of their kind and their source, so I can give good error responses to the queries with suitable HTTP codes and error messages.
Compile times could be better, but debug builds are fast enough to not be too much of an issue.
All-in-all I've found Rust to be a great language for writing a backend service.
Use thiserror + anyhow for error handling and alias your own Result through your app. That way you can match on the type of failure to generate the right http code.
Here’s an example:
That is more or less how I'm doing it now. Added a few specific error structs for some parts of the business logic to make it easier to track the error source. It's working great so far.
Do you happen to use or know if there's good openapi support? Either generating code from a spec or validating requests based on a spec? That's really powerful stuff if writing rest
I have not looked much into the OpenAPI options. Only thing I looked for, and did not find, was a way to create auto-generated API documentation.
We solved that by using the normal Rust documentation and just teaching everyone how to read the documentation for the endpoint handlers.
Thanks okay I see. Hope there'll be more work on this side. Having front end engineers reading backend source code to understand the api would not scale for us
Check out the comments in this thread
Thanks! I will check
awesome, but is it not tide, rocket, warp extremely slow in comparison to actix?
I have seen some benchmarks where they've been slower that Actix, but from my experience the speed differences in the frameworks are not an issue. There are other parts of the application that takes up way more time and resources (e.g database queries and talking to external services). Which is why we decided to prioritize a framework that we enjoyed working with.
The business logic part of the code is also decoupled from the framework as much as possible, so if we in the future see that Tide is a bottleneck we can replace it then.
nope in actual production environments (without stripping security headers) Rocket has almost exactly the same performance as Actix.
Really? Never heard of it before, do you have some document about it? It interests me, since I want to try rust for my personal projects, since I already do much c# development for backend and I dont want it to be too on my pet projects, and I found actix a bit confusing in the documentation. I heard rocket's doc is better.
What do you think about implementing some OO patters very much used in the C# and Java world, like unit of work and repository pattern? Do you think those are a good fit too for Rust backend development or the community actually uses other more fitting design patterns to work with Rust?
I have not seen a need for those patterns in our project, we've been well served with patterns better fitted for Rust.
It's a bit of a hassle having to send the database connection along to all functions that needs it, but it helps us reduce the places it's used and gives a good split between functions getting data, modifying the data, and then later on storing the data.