On the flip side, building massively scalable systems based on blocking IO is rife with problems and I've found that enforcing architectures that make it manageable have a way of obscuring the code and making it difficult for people to intuitively get right as well. I personally find the explicit functional style to be just as intuitive as structured and/or OO and therefore find that when I need it, a platform like node that makes the knife's edge that is asynchronous programming explicit and manageable with a good functional style is a good trade-off in the world where I am trying to find less bad options to a hard problem.
Sometimes you have to step back 20 years in order to break through the layers of assumptions that were added in the interim. I doubt node is the last word on the topic, but it is a refreshing interlude to what was becoming an unwieldy calcification of the theory of how to program computers. The water will find the right course eventually as we experiment with the different styles.
Agreed. I'd take a Node.js implementation over straight C any day.
"On the flip side, building massively scalable systems based on blocking IO"
Please remember that's an implicit false dichotomy. "Blocking" has to do with the runtime and the VM, not the visual appearance of the programming language syntax. Erlang is non-blocking, but it is also structured (and functional). In fact, by my personal standards Node.js is still a blocking language; you have to jump through hoops to get non-blocking behavior and you only get it when you ask for it. In Erlang or Haskell, you simply get it. Go ahead and do a lengthy math computation if you'd like. Take several minutes. You won't block anything else in the meantime. And you don't have to manually break the computation up yourself. Just do it.
I say Node is stepping back 20 years not because it feels primitive compared to C#, but because it feels primitive compared to the "really existing, I use it in production code" Erlang runtime. Also Haskell, except I can't say I use that in production code. And probably Go (still waiting for someone to confirm), and Stackless Python, and several other things.
(If you know the choice exists and you don't choose it for some reason, hey, great. Like I said in my first message above, I've got my own async-event based program I have to maintain, and I'm the original author, it was my choice, because when I took all the issues into account, it was the right choice. But you ought to choose with an understanding of the full picture and all the relevant choices, and understand all the tradeoffs, not because you think that async event-based programming is better than everything else at everything. It's got some really serious drawbacks, and there are really-existing, production-quality, "web-scale" things that can be used that do not have those drawbacks.)
Using Erlang vs Node on my current project was a serious consideration. It is well thought out and its message passing and lightweight process based design is more evolved than anything node has or likely will have. It's also Erlang and I have found productively programming in it to be incomprehensible. Maybe its a personal problem, but it is what it is. Ditto for Haskell. I was surprised to find that my brain didn't bend that way.