> They could have built this in Java, .Net, Go, really any shared memory concurrency runtime and threading, and would not run into any of these issues.
Right, they'd have brand new issues because they were dealing with shared memory.
Are you genuinely telling me there are no issues with sharing memory between different threads?
Node.js is 13 years old now. I get that a lot of people think it's some new thing that only dumb frontend programmers who only know JS use, back in my day, grumble grumble. But at this point it's established, mature technology, es6 is an expressive language (much, much more so than Go, C# or Java). The multi process concurrency model is sometimes a pain in the ass and sometimes just want you want.
I've used ASP.NET and node.js in anger, have you? Or do you just attack it because you hate the JS of 2010?
> But at this point it's established, mature technology
I have to disagree. Day to day I maintain a variety of node.js, scala and kotlin services. By far, the most gotchas have been from the node.js services.
Simple things like validating incoming payloads are made ridiculously complex. You can get a library to do that, but which do you use? And then most of them don't export the typescript type signature so you don't get any type safety unless you re-define the type in typescript.
Let's say you want a tiered caching library? I've spent weeks of my life debugging concurrency issues because the memory store shared objects whereas the redis store didn't (because they were serialised and sent to redis). That's on the most voted caching library for node.
The quality of node.js libraries in general is far below that of scala/kotlin, and the maintenance cost is way higher. You can't easily tell if signatures for the apis of the libraries you import have changed as well. The ecosystem is still moving very fast, and while I agree that es6+ makes it a much better language, it causes its own issues when interacting with older code/libraries.
Expressive as the language may be, in production systems it leads to poorly understood code because of all the ways to do simple things, and the gotchas associated (something i believe it shares with scala).
> The multi process concurrency model is sometimes a pain in the ass and sometimes just want you want.
Give elixir a serious go and see if you ever say this again. Concurrency should be managed, much like garbage collection has been for 30 years.
Simple things like validating incoming payloads are made ridiculously complex. You can get a library to do that, but which do you use? And then most of them don't export the typescript type signature so you don't get any type safety unless you re-define the type in typescript.
I strongly recommend Zod[0]. You write your schemas in code, it validates incoming JSON at runtime, and you end up with either an error or well typed code. The schemas themselves are powerful (you can check properties of strings, etc), and the derived typescript type comes out for free and looks like a human wrote it. A very powerful tool, with a very intuitive interface.
Give elixir a serious go and see if you ever say this again.
Ah you hit me where it hurts - really need to seriously try the Erlang ecosystem.
> "Are you genuinely telling me there are no issues with sharing memory between different threads?"
Where did I say that?
I use C#, Go, Java, and lots of JS/Typescript. I like them all. I find C# far more expressive then ES6, but that's just subjective preference. The point is that the vast majority of web frameworks simplify everything to a URL route that runs some backend logic and returns some response (HTML/JSON/etc). Requests are already well isolated and you don't need to worry about threads and memory.
I can't even think of what shared memory issues a typical website like Yelp would have. Can you provide an example?
However if you do need to worry about complex multithreading, memory access and concurrency, then Node is a poor choice. The other language stacks are not only faster but have the proper data structures and ergonomics to handle it while Node/JS is single-threaded, requiring more work and creating more bugs.
I remember from using Tapestry (a Java framework) in the day, it had really aggressive in-memory caching, and you had to be really careful to disable it for components which rendered personalised or user data. We had some huge privacy leaks (which luckily we caught quickly) because we didn't realise it had this behaviour, as it didn't generally show up in local development.
Right, they'd have brand new issues because they were dealing with shared memory.