Rust for web development: 2 years later
kerkour.com
kerkour.com
Please feel free to subscribe to the newsletter where I will announce when it's available :) https://kerkour.com/subscribe
I'm working on it 2 days a week beside writing the book.
The next major milestone is receiving emails in the inbox, but I think it will take 2-4 months to have it working.
https://crates.io/crates/dropshot
It may or may not interest you!
I'd say the most powerful part of FastAPI is that it integrates everything in a relatively opinionated way, that you would spend a lot of time setting up Flask plugins/extensions for to get an equivalent feature set.
I'm not sure I'd say it's based on OpenAPI(?), but it does automatically generate OpenAPI based docs from your Python code. There's no intermediate step, the '.../docs' route just exists at runtime.
Java/Go will deliver similar perf for most web apps, and have more mature tooling, python will be better for ML, C++ for systems programming, JS/electron will be better for the frontend and java/scala for distributed processing.
Rust has the innards to do all of these things at the same time with one shared code base (albeit somewhat poorly today). It's the only one of the above languages that hasn't made some decision which makes a use case impossible such as running on a VM, no function serialization, no direct hardware bindings etc.
In the other hand, having less features have help me in re-factor not just the code but how I do the whole thing, making more focused choices to be able to solve problems with less complexity.
Eventually the design you get (partially because the lack of support for things on Rust) is much better overall.
To make things more concrete: I use nearly 0 JS and no "single page apps", use tailwind and have reduced, a lot!, CSS designs issues, have more control in how mutate things, have less API surface, make better use of what PostgreSQL have, etc.
https://github.com/secretkeysio/jelly-actix-web-starter
I built it because I was _also_ frustrated with the same level of abstraction you mention. Granted, I do agree that that Django/etc are more feature-rich, and that's definitely not getting replaced overnight.
This doesn't inspire much confidence in the evaluation of the writer.
It really didn’t seem horrible back then.
Praises are generally dismissed when they seem to contradict this principle
That being said I'm sure that rustaceans disagree about the "No Silver Bullet" part (when you can compile to WebAssembly, write HTTP / TCP servers, embedded development and much more).
For distributed problems I'd prefer something like Elixir. This may even be true for web dev (I admit I haven't explored it as much in Rust; just, a lot of what I've had in web services is IO bound, with strong process isolation expectations, and that's perfect for Elixir)
For heavy math, Julia or maybe Python + libs.
To build a DSL, a Lisp.
For something largely integrative of other libraries, whatever language those libraries are built in.
For certain types of problem solving and optimization problems, a logic language like Prolog.
Etc.
Rustaceans tend to be a pretty practical bunch, so I'd imagine most of them do agree with it. It was also the one part of your post I didn't agree with (if taken literally)
I'm certain they don't. For one, Rust can't even be used in a niche but important class of safety/mission critical software until a certain level of certifications (i.e. DO-178C) are reached so by that measure alone it is disqualified. For two, what targets the languages compile to are a necessary but far from sufficient measure of a language's practicality - the most important ones have nothing to do with the language and everything to do with ecosystem and tooling.
While it's doubtful there's a single programming language to rule them all, I seriously doubt the panoply of languages we are faced with is the optimal solution. At some point as a developer new languages stop bending your brain in new ways, they just become the same thing with all new baggage to deal with. I can certainly see where a person is legitimately in search of the last language they ever need to learn.
Is that contradictory? Non-adjustable wrenches still exist, and are still used on a regular basis. If you do a lot of work on at a single size they're nice because they weigh less, fit in smaller spaces, and you don't have to worry about then getting jostled and changing size on you.
This is, of course, folly. Just as one who thinks himself the best to rule the kingdom is probably the worst choice for the job, so too the one who thinks himself 100% enlightened is the least likely to actually be considered enlightened by his peers.
Something I realized doing c++ professionally for the first time last year, it's nearly three different languages. There's an inner core of procedural C, the mid-90s new/delete/raw pointers OO business that got big during the heyday of COM/ATL/other Microsoft technologies, and then what's come to be known as "modern C++", with smart pointers and a lot more automatic stuff.
What I most enjoyed about C++ is how, as someone put it, it feels like an armory with everything on offer from a pocketknife to a nuclear weapon. It integrates with everything, you can write code any way you want from embedded assembly up to functional, and it runs everywhere, on any platform, and can link with Android, Windows, Linux, .NET, Java, whatever.
I'm starting to think garbage collected languages are headed for obsolescence. Like maybe, with better languages, we could ditch all the bullshit of pip, and gems, and all that, and get back to a time where you could just download something, run it, and not have to worry about some gigantic runtime environment that eats all your memory and requires a ton of configuration. It we could pull that off without making it incredibly hard to write simple code, that'd be cool.
In short: I'm pretty sure GC isn't going anywhere, even if some of its usecases start to get covered by non-GC'd languages.
I'm very interested in programming languages and expect new and better ones to be discovered in the future. At the same time yesterday I noticed that I'm not as hungry for new languages as I were before: Rust is good enough that I can live with it being the last language in existence.
This rings a Node.js fandom bell in my head; I'll be very careful taking authors opinion seriously.
Edit: I've myself been working on writing a websocket pubsub server in Rust and I can tell you the ecosystem is not as developed as projected by author.
If you asked me five years ago, I would have said "never." I was just asked this ten minutes ago, and my feelings are now "depending on your constraints, it can make a lot of sense, but I don't think it's going to be something for everyone."
What does Rust have to do with that? Are you trying to implement Rust's high-level programming language concepts in silicon so the generated assembly would run faster compared to amd64 or M1 or whatever-used-in-servers?
Can I ask which IDE do you use for writing code and for debugging? I read your book (which I think is a great starting point), and now I wanted to start playing with Rust, but for embedded (ARM, bare-metal). I have ~20 years of experience writing mostly C for embedded.
What I want is something that allows me to inspect memory, view disassembly, stack trace, setting breakpoints, watching expressions. Much like Eclipse + ARM GCC (GDB) + OpenOCD does, or KEIL uVision, or IAR EW, to name a few IDEs. IDEs I found now supporting Rust are more oriented towards desktop/server development and very limited on the debugging side. I cannot rely on println! since it would require semihosting and I don't want to walk that path yet.
I need something more low-level to really understand and learn what's going on and how it's achieved. Thanks.
Semihosting is annoying, but it is really easy to get going in Rust on bare-metal arm. https://docs.rs/cortex-m-semihosting/0.3.7/cortex_m_semihost... We basically have a build-time config to switch between semihosting and ITM, though we're probably at the point very soon where semihosting will basically never be useful again.
Happy to answer more questions if you've got 'em. Our stuff is still closed source but will eventually be open. You may also want to check out https://knurling.ferrous-systems.com/ too; we are using some bits of it but not going whole-hog. Similarly with the rest of the Rust open source ecosystem.
OK. I was thinking to assemble a "Press F5 to debug" solution to speed up my learning process. I'm used to command line tools and hacking stuff together too, so I should be fine if that is the current state of the art for debugging (but it would be difficult to convince my coworkers in the future). I wonder if a combination of Eclipse for Rust and OpenOCD plugin is doable. Or perhaps cortex-debug[1] for VS:Code. I have some research to do, to explore the different solutions.
And I'm stuck on Windows too, since many of the tools I use require Windows.
Thanks again.
> Initial support for Rust code (most functionality is working; disassembly views and variables view may still have issues)
So, that's pretty cool.
https://www.youtube.com/watch?v=Meqhiogdp1o&list=PLP_X41VhYn...
A 2x refinement may be a difference in degree, but a 10x refinement will be a difference in kind that will enable other kinds of innovation.
I've fiddled around with Rust web proof-of-concepts and I tend to agree that the language is somewhat-but-not-completely suited to it, and that the ecosystem is coming-along-but-not-quite-there-yet. But I have a small sample set for those impressions; I was looking forward to reading a more in-depth anecdote about the ups and downs and how to overcome different limitations, as well as a some informed speculation about the future.
I like Rust but I think it's too "low level" for web development. Ok, it's a better C++ but I wouldn't use it for web development neither. (And yes I agree with the points raised)
For a specific component of a web service where performance is very important absolutely. For a direct connection from a customer or an app, only in very specific cases.
How does Rust help prevent logic bugs? I thought tests helped prevent logic bugs. Or does the author mean "works" in that it runs where an interpreted language would not (i.e, syntax error)?
Enums help prevent a lot of logic errors.
Rust excels here, in my mind, because of its expressive type system which can allow you to encode logical building-blocks as types and hoist the logic into the type system, eliminating even more specs in favor of compiler errors.
Ultimately, with a sprinkling of logic tests, you can feel confident that compilation means success.
> Or does the author mean "works" in that it runs where an interpreted language would not (i.e, syntax error)?
More than that, but close. i.e. you won't get NPE from java. Syntax error or type mismatch from interpreted language.
In addition, NewType pattern will stop you from passing seconds into a function that takes ms and vice versa. You won't get data races. You also won't get an `undefined is not an object`.
Long story short, due to language verbosity it's hard to make logical mistakes.
I guess you build Go binary in building the docker image. You should build Go binary then build the docker image instead (5 seconds duration).
One the other hand, even if you build Go binary in building the docker image, 5 to 10 mins duration is still not a typical build duration for most medium-sized Go projects. One minute is enough.
By throwing everything on the heap, I doubt you see much improvement performance-wise over Node or Go. You probably even come out behind idiomatic Go which makes good use of the stack. What's the point?
Often times, I Box something and tag it with a "review this" for later. If it somehow becomes a bottleneck, well, it's relatively simple to solve in most web-framework use-cases. Haven't really needed Rc, only needed Arc for shared data structures (rare).
If you're just doing a CRUD app, you're probably right.
But if you're wrapping some complex logic that itself makes sense to writ in Rust, then I can see why you might want to write the web interface to it in Rust as well.
Unless what you want to build is tiny and simple and you don't need a lot of features, or it's so massive that you can invest on building everything that you need.
That's actually a problem I would say, most web dev use Java/C#/Go/Ruby/Python/Node/PHP etc... which all have a GC, so it's a big shift for 99% of people. It completely change the way that you design your app.
As a troglodyte myself, I don't disagree with you, but you're being unnecessarily demeaning.
> And you can’t use rust for front end work.
You certainly can (for example https://yew.rs/), but as usual there are certain caveats and limitations.
Rust also gets you:
1. Better performance
2. More importantly: much better safety guarantees. Rust web services tend to be set it and forget it. They don't break. they don't crash. They only rarely have bugs.
As someone that's coded in both... eeeehhhhhhh
Memory management in Rust can be a real bear. Just, for example, creating a closure that references a variable outside of its scope is not simple. You can make your life a lot easier by wrapping everything you reuse in Rc<> to make it reference counted, but then you're eating into the performance gains that are the initial selling point, and after a certain point you're just manually implementing the things that JavaScript does for you.
Don't get me wrong, I love Rust. But I wouldn't want to use it everywhere I use JS/TS today.
Well sure, but how often do you need to do that in a web API endpoint handler? In my experience: not often at all. Rust can be hard, but generally isn't for this use case.
> You can make your life a lot easier by wrapping everything you reuse in Rc<> to make it reference counted, but then you're eating into the performance gains that are the initial selling point
Frameworks like Rocket or Actix-web will handle this for you. In my experience it doesn't tend to affect performance that much. Remember: Node is single-threaded. Multi-threaded + atomics + optimised compiled code is still significantly faster.
It's a lot simpler and more performant than in other languages. Rust will tell you if the closure might outlive the variable you're referencing, and it's easy to pick the best option for addressing the issue (move semantics, Rc<>/Arc<>, lifetime specifiers etc.) while keeping best-in-class performance. This is a big part of what Rust is best at, and it's hard to get these advantages any other way.
It's fast on Linux where containers are native.
Build times can pile up pretty quickly as systems grow over time. I have to say with that code base the big sin was some extreme macro misuse. It's still possible to see times like that without heavy macro usage though.
That was a native linux build on a fairly modern i7 laptop.
Rust wasn't designed for this.
Before rust, all the mainstream non-gc'ed languages (i.e C/C++) were not recommended mainly due to potential security issues.
The only options left were gc'ed languages (e.g Python, Java, Go).
Now Rust enters which addresses a lot C/C++ issues but the ergonomics, lack of tooling & learning curve is too much for lot of basic web services.
For large scale web services, investing in Rust makes sense to make it more performant & resource efficient, especially a lot of $$ is riding on it.
Certainly Rust has done lots of cool stuff to make living without a GC easier. And maybe it has sufficient compensating advantages to make it worth using for things like webdev (although I wish more of its proponents would try different statically typed functional languages that share some of those advantages but don't make you manage memory manually). But lacking a GC is still pretty clearly a disadvantage outside of a few areas (namely, those where people often use C++).
Also, pflock you have a small typo there. You probably meant to say from Go to Rust, not Go to Go :)