Yes, there are downsides: it's not a natural model for many people; you do still have to consider many complex concurrency-related issues; and control flow libraries are usually needed to make complex code much more readable. But these are either easy to deal with or intrinsic to the complex problem at hand, and the above still stands: once you understand how to program with this model, the "default" implementation usually scales very well.
Yes, Node was not the first to do this, but that's not relevant to anything.
Besides all that: I'd put Node's postmortem debugging and dynamic tracing capabilities up against any other dynamic environment.
As a side note: it's enormously condescending to tell people that a very broad technical choice is not only wrong for their technical problem -- without even knowing what it is! -- but that they're also part of some mass delusion for even thinking that there's anything to it. I hate arguing about this stuff. You keep trashing Node, and we'll keep using it to build large distributed systems.
I presented two different ways of writing a single-threaded, event-based function that can handle "an awful lot of concurrency without ever thinking about threading issues or managing thread pool size to balance memory and concurrency". Essentially, it is possible to get good concurrency in a single thread without the use of many nested callbacks or abandoning the language's natural control flow primitives. It's not necessarily the case that you can't have both event-based concurrency and sane code.
Yes, other environments have compelling concurrency models. As for control flow: it doesn't matter much to me whether the control flow abstraction is built into the language or merely a ubiquitous construct in the code I use. (In fact, that's a tradeoff, too: I like that I can go inspect, modify, and extend these non-primitives easily, and I've done so to add better observability.) The Go example is interesting, but less explicit -- that, too, is a tradeoff. It's all tradeoffs; to pretend like one thing is strictly worse (or better) than all others is not founded.
If you're trying to script a nonblocking system where everything is nonblocking all the way up and down the stack, you're going to end up creating a parallel ecosystem to the normal one, and confuse people by not allowing them to do the normal things they would do in language X.
And speaking of ecosystem, that's another really good reason to like node. The stream programming that is coming out of the community is brilliant, and the focus on constructing large projects by writing thin modules that use other thin modules ('onion oriented programming') is fantastic.
I've been doing a lot of Scala recently, and it's extremely noticeable that despite the languages power to do things in many different ways, the Scala community frequently seem to choose a strangely convoluted path filled with hidden magic going on behind the scenes where every new library you depend on feels like learning a new language from scratch.
It might well be that the Go community is also as good as the node community for some of this stuff, but the community and library ecosystem is a definite plus point.
By "all of these observations aside," I mean that I hate working with it personally, and I'll be using Erlang/Webmachine thank you, but I learn new ways to think about modern problems every day from many of the great people that are part of the nodejs juggernaut.
He makes a lot of comparisons with Go, but Go was created after Node. Many of the languages he notes as possible replacements for the non-blocking rant are obtuse (I love Haskell, but there's no way it's not obtuse)
[EDIT] - turns out they were made pretty much at the same time 2009... Learned something today, I guess. Felt like Go came after node to me but I guess it didn't
Also, I must be the only one that doesn't really mind callbacks. Maybe it's stockholm syndrome.
I also think node should get kudos for at least seeming different enough to prompt the move from enterprise customers. Any move away from burdened "enterprisey" software is worth praising I think. Not because java is bad/lame by default, but instead because it might prompt other companies to lust after something new that might be better (whether it's python, node, go, or haskell is irrelevant)
However, I think once you start trying to manage go routines and all their channels, and all the messages that are flying around, go will start looking less utopian. Of course, a lot of that is subject to code architecture (well architected code will be easy to follow), but I feel like no one's found enough of the dark corners of go yet.
Oh one thing I wanted to mention - Why didn't you include any samples of go routines in your code?
Unless I am misunderstanding go immensely, a statement like "(task3(task2(task1()))" wouldn't actually be asynchronous, you would need to spawn dependent go routines right, and wait on completion on the channels?
Correct, because you're passing the result of task1() into task2(), and the result of that to task3(), afaik.
I imagine Twitter every day looks online at these node articles and just laughs. That's a team that realizes Java != JEE and that JVM programming is a great thing to be doing.
Not every usage of Java involves Java EE, but that doesn't mean Java EE isn't a really valuable tool for many of us. It has had a bad name in the past, but last version have totally changed that and it's now a very sane tech.
Twitter of course is a highly specialized thing that operates on a Scala that almost by definition not every web site out there will be at. It makes sense to build a lot of their own tools and only use lower level infrastructure as a base.
So the JVM and Java is low enough for them to build their stuff on, but many parts of Java EE may be too high level for their very specific use case.
The infuriating thing is that it's not the technology that makes the difference, it's the clean slate and getting away from stupid policy. I bet the Paypal people could have written a better version in Java than the Node version, if they weren't required to use the existing internal library and follow existing coding standards and deploy using approved infrastructure and...
It's not like Node invented evented concurrency. Something like Twisted predates Node by many years, for instance.
However, if twisted were it's own language, it may end up looking much like node. Twisted is just a library (a damn good one, yes), but if you were to try and transform it into the base framework for an entire ecosystem people might also rail against it from time to time, due to the async-by-default nature.
Also, to me, twisted seems like a much more high-level tool (replicating protocols over simple parallelization/concurrency), than something like gevent
I've done toy examples, and watched lectures (Erik's C9 lectures are amazing), and I just haven't found anything to write in Haskell.
At this point Haskell is starting to seem like the sketchy guy in the corner at a party. "Oh you think I'm obtuse? just drink a little bit more of this kool-aid here"
The 2 points I always hear from Node.js are:
1) Node.js is fast. It is really not that fast. It all depends on what you are comparing it to.
I like the idea that is Node.js, but I don't think it is mature enough to take over the backend. I think there are other more mature languages right now that do the job without making programs look like spaghetti code.
I think people should take this article with a grain of salt, and keep getting their hands dirty in Node.js. I think it has a future in the cloud.
I think this addressed your question indirectly.
FWIW I think Elixir holds a lot of promise for the future. Projects like https://github.com/dynamo/dynamo look really cool. Of course, it's new, and alpha. But maybe we could all give it a try?
Elixir adds some nice metaprogramming features, and I love that it exists. Erlang is used for a lot of Important Things in production, and its value to many developers is stability and fault tolerance. Erlang moves slow. It's nice to see a sister language that can more rapidly develop new language features (maybe some of the goods ones will get added to Erlang (:
Joe Arms post about Elixir is pretty interesting 
If something indeed is going to take that long, perhaps you shouldn't be making the user wait on it either. Queue that shit.
I have have written a few web apps in Go as well spending most of my time writing things like high performance proxies, CDNs and databases in Go, and IMHO Go is a "more least worst" way to write highly concurrent code compared to node.
It handles each request in a forked subprocess so it's a lot more straight forward.
You could think of pure functional programming (haskell/ml) as a similar extreme -- Haskell gets a lot of concurrency/parallelism guarantees for free just because of how the language was built (pure functions,etc)... Is it wrong to think that node took a similarly crazy step, but in their case, they weren't able to rebuild the language, and that's what you get?
If I wanted to event-loop, or lightweight thread stuff in python, I'd need some libraries, and many of the ones that you might find are not very easy to learn.
This statement depends heavily on the runtime environment. Consider either Erlang or fibers as implemented in C/C++, for example.
Fun unrelated anecdote: someone was showing off their concurrent Node.js web scraper and as requests piled up, it was apparent that it could handle no more than 5 concurrent requests. Why? The HTTP library's internal concurrency limit defaulted to 5.
http.createServer(...a simple function...)
Once you get deep enough into to it to realize that it creates a tendancy towards complex deeply nested code and that making a good, maintainable application is a non-trivial task... it's far too late. Because of the 'fast' feel of it, you're convinced that these are just things you have to figure out and learn best practices for - it couldn't be that the 'fast' feel was deceptive to begin with.
This client restriction is deeply irritating. A project I was involved with is about creating a general purpose hypermedia API, and building up documents involved following the links in parent documents back through the API, which meant that a single request can end up requiring hundreds of further calls to satisfy, which seemed like no problem at first with node.js' easy concurrency (and an auto-scaling fleet of EC2 servers), but the client connection limit turned out to be the cause of a lot of timeouts and prompted a lot of working around.
In larger cases it turns into a mess, but by that time there is already a buy-in. Run a short little demo, looks fast, read about how "cool it is" on the web some place. Ok let's rewrite everything in it.
Quite often once people started heading the wrong path, it becomes hard to look back and say "Yeah this is the wrong way, let's turn back". That is just basic psychology.
At the same time, I think Node.js is great. It is great as a differentiator when you ask people why they picked it and see what they say. If they come back with the list in the article (basically list "evented","async","webscale" jargon), then that tells me they don't quite understand what is going on underneath. Which is not bad, people have the right to be confused, but it just lets me know on what level to converse with them on.
It's definetly not simple to write webapps in nodejs,where a simple exception can take down your entire node server.
I'd even say go concurrency model is simpler and easier to use than nodejs.
I mean, really, is there any other criticism here? There is a valid point about the true nature of Walmart and Paypal's rewrites, but that's pretty tangential.
There's kind of a thing about some completely rookie mistakes in error handling, but that's really not relevant to anything, and again, tie into the "I'm bad at callbacks" thing.
I'd really be interested in some criticisms of node that aren't variations on stories of the author's past difficulties with callbacks, as most people who use node have no problems with them.
EDIT: Downvotes? Please, point out to me the part of the article that is not about callback troubles.