Ask HN: Should I convince university against Node.js, maybe Rust/Go/Elixir?

12 points by marcus_cemes ↗ HN
I've been using Node.js and Typescript for many years, and I'm constantly frustrated when hitting issues with npm, the memory usage, bugs in libraries, the state of the web framework ecosystem and so on... I've been hired by a university course to make a full stack application to manage reservations. I've been very happy with Svelte in the past, it's a breath of fresh air, but I'm torn for the backend. My recommendation was Node.js, I'm very familiar with the gritty details, and it's easy to pick up when I leave. I also tried using NestJS and Prisma for a second time, and despite the amazing work that has gone into them, it's still painful for me to use when straying away from the "chosen path".

I also recommended Rust (been using just over a year, I've loved it so far, compiled code feels so much more powerful than janky and fragile dynamicaly-typed languages), Go or Elixir+Phoenix (anything to get away from Node.js, but they are all quite different), but my supervisors aren't too keen on a new language.

I'm not after performance, but a clean and maintainable architecture. I've heard good things about Django and Ruby on Rails, although I'm not particular keen on either. PHP would likely not be suitable, it has to do some background processing work. I feel like I could make any language work, it's just Node.js' dependency problem that gives me nightmares.

I would value some feedback or advice, I'm doing my head in with decisions.

13 comments

[ 3.2 ms ] story [ 37.2 ms ] thread
> and it's easy to pick up when I leave.

Your head is in the right place. Use whatever you think is going to be the most maintainable by your successor. Only you can make the right decision. Every ecosystem has warts, there are no silver bullets.

Too true. I'm just wondering whether an ecosystem with better design and first-class developer tooling (unified linting, formating and compiler and native module system) might be easier than having to learn the Node.js/TS/Prettier/ESLint stack, even if pointers and memory management might seem a bit scarier at first.
We all have our favorite stacks. I think at the end of the day you want to use Rust, which is fine. It is new and interesting. I'm getting into it as well. You just need a way to rationalize it in the institutional setting.
Here are some random points, but you have more context at the end, so make the decision that fells right to you.

- I heard a lot of npm dependencies nightmare, but somehow, we do not hit that much. Once in a while (a couple of months at most), we get some weird errors, delete node_modules, and are back at it. IMO, TypeScript is a must for any code > 10K LOC (and I use it even with 100 LOC).

- NodeJS/TS's benefit is that it is the same language for the backend and frontend, allowing students to focus on the patterns rather than learning another language.

- However, I love Rust, and I think it is an excellent fit for cloud/web backend. We are moving our NodeJS/TS backend services (web service & job service) to Rust, at least for new ones. Still working on the blueprint, it is quite an effort, and the big question is how long it takes for a whole team to learn Rust well.

- If the university understands the pros/cons of Rust and want to "invest" in it, it might be a good idea to have a Rust backend. However, if they have no clue what it is, it might be too early for them.

- IMO, Rust will become more mainstream in the years to come, especially for backend services. It might take 5 to 10 years, but I hope and think it will get there.

Those are not recommendations, just thoughts, as this is a very contextual decision.

Best of luck, I am sure you will do well, you seem to have all of the right questions.

How does Rust compare to Go in terms of performance? I know that Rust supposedly should be more secure at handling memory than Go. Does Rust have the same mature libraries that Go has? Building a RESTful API, or an HTTP(s) server or for that matter any kind of server (UDP/TCP) should be quite easy to do in Go, due to the awesome net standard packages (libraries) included with the language. Does the same apply to Rust, are the net packages of Rust mature enough? I am just asking out of curiosity :)
I am not a Go developer, I just looked at it from afar, but I understand that the GoRoutine was the cornerstone of high concurrency performance.

In Rust, you have the async/await/future model. You can combine with MPSC (multiple producer single consumer) to have similar message-passing patterns or use traditional Mutex to access shared data. Although the async/await was not designed from the start, the Rust ecosystem has embraced this new concurrency model, which works very well. Tokio seems to be the major future executor crate available that most libraries gravitate around.

So, at zero cost abstraction, all of that allows taking advantage of NIO OS capabilities fully, with extremely efficient async/await/future design choice and implementations (there are some good reading out there about the design decision).

For example, I made a quick video on how to do a "blocking" Redis Stream Read over NIO, which shows concurrency with one thread.

Rust to Redis with Async/Await - https://youtu.be/uD5hBVHwyDM

Thanks for those, I agree. Although I think the term invest you used is very applicable, there'll definitely be a larger barrier to entry.

I don't think they've every heard of Rust and it is a relatively minor project for a small section of the uni. As much as I would love to jump on the Rust bandwagon, I feel more confident that Node.js would be a more "justifiable" choice. It might be easy to understand well written Rust code, but trying to implement something new will need an understanding of lifetimes and memory management.

I would love to see Rust in the web spotlight, it shares blood with C/C++, but it has real potential in higher level abstractions as well. It would be great to have a solid go-to web framework, like Phoenix or Rails, we'll have to wait and see. Good luck with your own endeavour!

I think you have a good point, Rust might be too much for them (at least for now).
I have been doing NodeJS, TypeScript full stack for quite a while now. I haven't really hit any issues that you are describing of, honestly, so I would just go with Node.
I may just be an old school Node.js developer but I don't like using frameworks like NestJS and Prisma. Like you said they don't give you very much flexibility outside of the "chosen path".

I think in order for students to learn they should be using lower level packages directly. So something like Express or Koa + the SQL driver directly. Learning the core concepts underneath is more valuable to students than learning a specific ORM or framework that abstracts all the details away.

Learning how to deal with dependencies is a similar thing. I don't think any course would be complete if it teaches Node without also teaching how to build a Dockerfile to package up your application and the snapshot of it's NPM dependencies as a container image.

Building a compiled binary with Rust or Go is one language specific way to solve the problem of packaging dependencies, but you have an opportunity to also teach students a general purpose tool like Docker container images, which can be used to solve lots of different dependency packaging and distribution problems, not just for NPM, but also your static files, your specific runtime binary versions, any system packages you might need, etc.

Yes, I completely see your point. I really enjoyed using Koa on its own (still in production), and have recently come to respect Fastify after listening to a JS Party podcast with the author. I'm seriously considering going with a lightweight library, as satisfying as annotating routes with decorators is, I'm not sure the benefits out outweight the problems its caused. But I'm also a fan of not having to re-invent the wheel every time I want to make an application...

There's nothing wrong with old-school, but I do feel a dagger going through me when I see `var Protocol = module.exports = function () {` as a function declaration in a modern codebase. My TS code looks very similar to Rust or Go code. The fact that such syntax is possible is paretly why I want to move away, even if it does show just how versatile JS really is.

I'm a bit more worried about dropping an ORM. I've also tried knex + objection for my own website, but still feel it's not quite there. Pure SQL scares me, especially with TypeScript. It feels like a lot of boilerplate for different entities and very little safety in case of mispelt SQL queries, but I respect the power and simplicity of SQL.

I'm not sure Docker gets much love outside of the cloud. Writing a Dockerfile is wonderful, actually reploying and running them is a whole different story... It's a very practical tool, but I'm not sure it can live up to the academic status needed to teach it.

Valuable to students, yes. But it all requires solid reasoning and justification, and that's perhaps harder for a student :D

I would agree with Svelte for the frontend. I would teach Go for web server fundamentals or Python + FastAPI for quickly building a backend.
Not a tech stack recommendation, but I'd suggest teaching from putting together HTTP response strings, and build their own abstractions / tools from there, instead of going straight into libraries like express / koa (e.g. i think the middleware architecture hardly makes sense for people who don't know the inner workings of a http server). Same with frontend I think it's better to start from putting together simple html string from the backend, experience why it can be tough for building rich applications, try to build own mini / frail tools, then move to the established frameworks. The gist is: Understand the problem before learning the solution.