If you don't have any need for concurrent sharing of data and never really miss having destructors in a managed language, then I'd guess that Rust wouldn't be a great fit for a CRUDy backend.
Scala and Kotlin are great choices there. They have good type systems (everyone loves Rust's enum types, which are just ADTs and exist in many other languages as well), they have garbage collection- so no borrow checker headaches, and they have the massive Java ecosystem if and when you need it.
On the other hand, all programming languages are greater than the sum of their parts. Rust is more than just a checklist of "borrow checker, fancy enums, no exceptions, move semantics, etc, etc". You might just love the language even if it's not "objectively" better for your use case than something else. That's where I am. I spent years doing C++ and I instantly fell in love with Rust. It's not perfect, but it's usually my first choice when doing almost any project. I only ask myself "Is Rust such a bad fit for this task that I'm significantly hindering myself?" and/or "Is FooLang so PERFECT for this task that not using it is stupid?".
There are already several languages that server that niche better. I myself use phoenix/elixir which is batteries included. I have a nice toolbox of production ready libraries. I can prototype/build endpoints much faster than I would in rust and the sub 200ms req/res times (including the database call) is plenty fast enough.
That said, there are a few things I'd consider rust for.
1.cpu intensive jobs - elixir and any language with c interop have rust interop and I'd be happy to delegate those jobs to a service written in rust.
2. optimized large data structures, discord did something akin to this for their chat system
3. serverless functions - having no runtime or garbage collector makes for a gloriously fast cold boot if you're into that sort of thing.
In short, While you CAN user rust for web development, I dont' think its appropriate for most web development related use cases if you're trying to develop software for a client. IF its for fun, Then by all means, go nuts! :)
Rust has a great async story compared to other languages, which benefits IO-bound workloads even more so than CPU-busy ones.
Saying that it is "great" is really overselling it at this point, unless the languages you're comparing to are mainly C or C++. I would also toss Ruby in that category for now, but they seem to be working on making async better with Ruby 3+.
When compared to Python, JavaScript, or C#... Rust's language support for async isn't really that impressive to most developers, although the implementation has some technical characteristics that are nice for people who care about the low level details. The ecosystem is pretty lacking, even though it is much better than it was a few years ago.
Compared to the aforementioned languages (including Rust), Go and BEAM-based languages are just on another level.
I'm sure both Rust's language ergonomics and the ecosystem will improve over time, but Rust's goals also make it unlikely to ever be compatible with my definition of a great async system... which is the model Go and Erlang use where the developer can't tell that every single sequential process isn't running in a separate OS thread -- and, by extension, every function is automatically async with no distinction that I have to worry about.
In Go, I can spin up as many goroutines as I need, and I don't have to worry about any single goroutine blocking an executor like I have to worry about in Rust.
Yes, some async runtimes in Rust have worked on clever things like monitoring the executor threads and spawning a new executor to steal a blocked executor's work queue... maybe some day that will be a battle tested solution. Like most of the Rust async story, there are rough edges that could benefit from some more time.
(I have worked professionally with both Rust and Go for several years, and I think they're both great languages with different trade offs... I'm not trying to bash Rust here.)
I can't tell if that is pulling V8 in as the WASM interpreter or not. Obviously, I would prefer that they leave others in the dust without having to pull in a huge C++ codebase, but it still sounds promising either way!
Although, on closer inspection it seems like wasmer is using LLVM as a backend to get that good performance, which tempers my enthusiasm a little bit. I see that wasmer also supports the Cranelift backend, but the promised performance blog post[1] doesn't seem to have been published yet, so I don't know how much of a difference that makes in the real world.
A ~13x difference in JIT compile time (LLVM vs Cranelift) is huge, and waiting on LLVM itself to compile can also be... exciting. LLVM does good work for AOT compilation, but I don't know how I feel about the trade-offs of using it as a JIT. If a massive C++ code base is going to be pulled in anyways, I would almost rather them pull in V8 than LLVM... but that's just my opinion, since V8 seems to be very well optimized for the JIT use case.
But, I'm glad there is the choice to use Cranelift (and presumably exclude LLVM from the final binary) if that fits a particular use case, and I'm excited to see that follow-up blog post whenever the wasmer team has time to publish it.
Thanks for the kind words!
There are some nice opportunities to bring LLVM compilation times closer to the optimal ones in multithreaded environments. We are currently working towards that and hope to get something tangible in next releases... stay tuned!
And I personally, say yes. But that comes with some caveats. You will be entering an ecosystem that doesn't have all the libraries that folks coming from the rich history of Java has, so you will most likely be signing up for some extra work.
But, this is also a great opportunity, because it means that you could be responsible for building a missing library or feature.
Ok, so this is an 'opportunity' for some, but a 'big cost' for others.
So remember there are very few Rust devs out there, it is a little bit hard, and though a good chunk of devs might jump at the chance to learn, others, not so much.
It would be a really hard thing to rationally do a 'crud app in Rust' at this moment in time due to all the above reasons. There's a lot of added risk for really no benefits.
If you have a core team that has the skills, ability and is willing to commit to it, then maybe. But we have to think beyond that, when you need another 100 devs ... and people maintaining it ... one can see how other things factor into the equation.
If there is some specific reason and the conditions are right, and if that reasoning is not warped by our own natural tendencies to 'want to use Rust' then there might be an opportunity ... but generally not.
As team members get more excited about 'the problem they are solving' and less 'the tools they use' - you might see an inclination towards other tools, for the most part, at least today, for CRUD-ish kinds of things.
Nothing you said is wrong per se, but it’s also not entirely accurate. First, there are very good db connection libraries available to Rust users, with good connection pooling options. Second there are good ORMs if that’s something you enjoy using. Third there are excellent application server options in Rocket and Actix available.
Your comment implies these don’t exist. It’s more the edge cases, and the things outside the DB that will be issues. And even there, you’d need to get into specific areas that would cause issues due to lack of available implementations.
In terms of developers out there that want to work with a language, there’s no better response to that than it’s “the most loved language”, and that may translate to many people adopting and expanding its use.
It's outclassed by other stacks in almost every way for this purpose, and provides no material advantage most of these scenarios. Null safety never was a problem in CRUD apps, and, though performance usually is, it never boils down to 'speed of execution'. And of course, the long list of disadvantages, the most obvious of which is inflexible and slow development, especially in scenarios that require adaptation.
I can't think of a scenario wherein it would make sense for a CRUD app. Some associated micro-services, sure, but not for the core of the app.
As a Rust dev coming from Java, I will tell you nulls and proper error handling in Java are still major runtime issues, a cause for many rollbacks and emergency fixes.
There is even the promise now with wasm and other tools to use Rust from the bottom to the top of the stack without any compromises (in terms of performance, memory usage, or type safety).
Rust might not be the language for you and that’s fine, but your opinion is not shared by everyone.
This claim requires some data to back it up. I know at least a few people (including myself) who are more productive in Rust than in other mainstream languages typically used for CRUDs like Java, C#, Python, Ruby or PHP.
Rust is for harder problems. The ones you'd otherwise have to do in C++. I'm working on a client for a virtual world in Rust, and it is far easier in Rust than it would be in C++. Full 3D, GPU usage, networking, lots of state, a constantly changing big world through which you can move, compute bound, multiple threads. All my code is in safe Rust, and I've never had to use a debugger.
Write your embedded software in Rust. Write your networking software in Rust. Write databases in Rust. Write browsers in Rust. Write complex games in Rust. For ordinary server side web jobs, it's overkill.
Go is for system-level programming that mainly consists of plumbing api endpoints together. i would recommend it for building middlewares in a server environment
It's been a slow side project for the last month learning the ecosystem and figuring out how to properly deal with types etc.
But now I have a page that uses an opaque cookie stored in the database to identify the logged in user and return proof of success in a rendered template. My goal was to keep server latency for that request below a millisecond, and it ended up being about 100 microseconds on my laptop, so 10 times faster than I was hoping for. I'm just not sure how I could have achieved that with, for example, Django.
So I guess what I'm saying is that it's slow and challenging for me, at least in the beginning. But it's getting faster and easier over time. And in the end, I'm creating something with performance and reliability that would be hard to achieve in another way.
Impossible.
Also look at startup time, disk size for installation...
But the real benefit is when you want to hack/refactor your code months or years later (or someone else working on the code): languages with strong type systems can help prevent sooo many error in those cases. Compare that to Python where many errors are only discovered runtime.
With that disclaimer: as of now, what rust lacks is a comprehensive framework for web development.
I'm sure your story in the J2EE world is similar to rails: you have libraries that you can use to abstract away a lot of repetitive things such as authentication. You probably also have a framework-aware test suite that integrates with something like Selenium. You may have abstractions around javascript build systems like Rails' webpacker that allow you to easily integrate SPAs directly into your app using the same overall tooling. There's so much code you don't have to write, and you probably don't think much about it, and you probably just take it for granted.
This is not the story with Rust. There are some frameworks such as Rocket you can reach for, but when I evaluated the situation ~6 months ago I realized I couldn't justify using Rust for this yet. From a web development perspective, there was just too much busy work you'd need to do.
I don't think this is an inherent limitation of the language, by the way. I think Rust is a lot of fun to work with and I wouldn't hesitate to use it once a more robust library ecosystem is developed for this use case. I'm always keeping an eye open for places where it would fit what I do, like a small performance-sensitive microservice for example. The type system is powerful, it's great (as a Ruby developer who last worked with C++ a long time ago) to work with a compiled language again. The type system, Rust linter, and compiler together catch many classes of trivial errors that you need to test against in Ruby.
I hope it'll get there one day!
Also, from a performance standpoint, it seems to be _really_ good: https://www.techempower.com/benchmarks/
This example in particular piqued my interest: https://github.com/actix/examples/blob/master/async_pg/src/m...
I have no experience in Rust whatsoever, but I feel inspired to try it out.
The TL;DR is it may or may not make sense for you. Engineering! We are finding it valuable, but you may have different needs than we do. Ecosystem maturity is variable.
Since this is a side project for me, there wasn't much risk if it ended up being a bad decision. Multiple times throughout the project I got frustrated with the DX of existing http frameworks I tried and ended up building my own [2] on top of hyper. However, after launching my site and seeing how it performs in production, I could not be happier with the result! I had a bit of Rust experience before the project but learned a lot more through building this.
For you and others, I think it really depends on the situation. Building a Rust CRUD app will likely take longer than the other languages you're used to as the ecosystem is under heavy development, especially with async/await. So if you or your team are in a rush, I'll just echo that you should build with the tools you already know. If you have time and budget to experiment like I did, it might be worthwhile and I can promise it will be fun :)
[1]: https://github.com/sfackler/rust-postgres
[2]: https://twitter.com/jakedeichert/status/1205230350160539650
You need to pay attention in how align the whole software stack. Pairing Rust with tailwinds and htmx or Hotwire simplify so much stuff is like cheating.
For regular CRUD flows having enums/traits/iterators make domain modeling very good and found is more productive to me than F#/Python at the domain layer.
I do my own micro SQL-orm layer (I have the need to talk to +6 RDBMS and be dynamic at runtime), and most db libraries in the rust ecosystem are mature enough now.
I find recently the whole auth is not as mature as you find with Django (aka: Not need to code part of it, you can certainly do it manually), but anyway is now better to offload to key cloak or similar.
Also, the fact I can do mutation + imperative code locally yet give a functional feel make some hacks around this on F# unnecessary.
But probably the biggest thing is that Rust make idiomatic things like conversions with From/Into/AsRef/etc instead of rely in your own conventions, making code more readable in the long run.
Other source of simplification is serde. A lot of my stuff is transfer/(re)encoding of data and have a "de facto" idiom for this help a lot.
One thing that F# make far easier and I miss much is the sequences (https://docs.microsoft.com/en-us/dotnet/fsharp/language-refe...). Making iterators is boilerplate and wish Rust have generators in stable.
I found a decent library for this in https://lib.rs/crates/genawaiter but is not the same as have it in-build.
With this kind of library, your rust code is the same as processing regular html forms, is only the HTML that need to be annotated.
MAYBE you could optimize partial rendering detecting just the portion to change:
https://htmx.org/docs/#requests
But I not bother with that.
Additionally while the community is growing rapidly you wont find the same depth of ecosystem that you have with Java. Client libraries will be half baked and still be a work in progress a lot of the time.
If the business stuff is not performance or time sensitive it would probably be better to use something like Java/Go/Python, maybe elixir, that will have good turn around time with reasonable performance.
A good litmus test for the moment is probably "Would I write this in C++ five years ago?" if yes Rust might be a good option today with a few caveats, like GUI or GPU programming still being in their relative infancy in Rust.
Some of the arbitrary, random things I've learned:
1. Given how nice and powerful language is, Rust works relatively well with less experienced engineers. Potentially. You can build very nice APIs which are straightforward to use.
If you can stay in this territory, everything is great.
However, there are some hard walls in Rust which are really difficult to jump over. And once you hit them, you really need somebody who understands Rust really really well and is capable of working around those issues.
2. It was quite hard to find the right balance between engineering time, compilation/linking time, safety, ease of use, performance, etc. Might be my personal biases, but I had to make some questionable decisions to keep compilation times / turnaround times at bay (like, unsound plugin system, custom serialization framework or test framework using nightly Rust features).
3. The type system is really, really nice. This alone compensates for a lot of things.
4. Ecosystem? Simply amazing. High quality libraries, documentation and everything.
5. Ecosystem again? Lots of things are still missing.
6. Performance? I'm 90% trolling here, but my experience was that Rust is not "blazing fast" by default. Not for "enterprise" software. You have to do some legwork sometimes. I've built some simple tool to do certain transformation between JSON and XML, and out of gate it was ~2x slower than Java equivalent (yes, with release build). Turned out, strings are not that cheap to clone if all you have is a bunch of strings. I did make it like 5x times faster than Java in the end, but it did require some weird tricks (like forcing hash map to look for a "derived" key than I give it).
There were some other cases where performance was reduced by simple things (like, having "heavy" Result vs having error variant boxed).
I think, this is "easily" counteracted by adopted practices and libraries (optimized error types, for instance), some standard patterns (like don't be afraid of Arc, they are better than to move huge data chunks around), maybe, good profilers as well.
This is probably also my biases talking here, frankly, I don't think it mattered at all (performance was killed by database, as is very common with enterprise systems). Also, in the end, it was fast (outside of database woes).
7. Overall, I find Rust very exciting language to work with, which was a big driver (but that doesn't necessarily scale -- you'll have to have some answer prepared when less experienced engineers will ask you "but why can't I do like I did in Typescript in those trivial 500 lines of code").
Would I do it again? Probably, but with understanding that whoever pays for it, might be paying for my "fun" on top of the product they are getting. Which is not necessarily a bad thing -- "fun" is also a factor in attraction and retention of engineers.
I'm also not going to lean into the "dark side". Like, if all you care is to get some half-broken whatever out as quick as possible, Rust might not be the right choice. It makes you think about "right or wrong" a lot, imo.
Yeah, if you're doing a lot of cloning, you'll probably run into performance issues at some point. A common way to solve that problem is usually to use references instead of cloning.
Of course, writing your code that way takes more work/thought/planning.
Right. I think, we ended up with having everything from the list:
1. String 2. &str 3. Cow<str> 4. Arc<str>, for interned strings (thin Arc would be even better & there is probably a crate for this) 5. Something like owning_ref::ArcRef<Owner, str> 6. One-off tricks where you actually need to construct a new string, but don't want to really construct it (for example, for hash lookup).
#5 I think is undervalued, actually; it's amazing for "enterprise" kind of stuff where you have large trees of data you need to pass around & you don't want to use straight borrowing (like &'a Whatever) because lifetimes are too infectious. And you don't want to use Arc at every corner (like, say, Java would do, not quite, but in semantics).
My problem, though, was to explain all the nuances given that they usually have nothing to do with the "business" part of the problem somebody was solving.
Yeah, I completely agree. A GC provides a lot of benefits in terms of clarifying the intention of business logic.
Unless, of course, performance/memory usage is an important part of your business logic, in which case Rust is exactly what you want.
Lack of GC in makes it harder to write but easier to read.
Another one I really love is ability to destroy objects on final operation. E.g you close something and it can't be used any more. Most other languages can protect using such closed object only with runtime exceptions.
Some languages like Java don't even make a distinction between "object A is composed of B and C" vs "uses B and C" (in both cases they'd be references)