
After a year of using Node.js in production - 0xmohit
http://geekforbrains.com/post/after-a-year-of-nodejs-in-production
======
placebo
I usually don't respond to anything which I feel is just another "language
war" provocation, but whenever I see these type of reviews I'm mystified. I've
developed in many languages and frameworks, both well known and lesser known -
decades of client and server side of C/C++, Javascript, Lua, Java, Python,
PHP, Perl, Lisp. Pascal (just to name a few) in projects of all sizes, and not
once did I have the thought "this language sucks". I think there are a few
reasons for this: 1) Even after all these years, I'm still passionate and
excited at the ability to sculpt logic, regardless of the "material" I need to
use. 2) A "keep it simple" approach - no way to overemphasise this. Know the
advantages and limitations of the language and stick to what works. Keeping
things simple should be like a fractal - existing at all levels of
abstraction. 3) I'm very wary of hype. New, shiny and trendy does not
necessarily mean better, especially when the hype is in conflict with keeping
things simple. I find that when you understand the playing field, mark the
areas to avoid and keep things as simple as possible, the elegance of the
design and implementation usually makes the advantage of language X over Y
insignificant, and I feel that blaming failure on the language used is like
blaming a bad novel on the word processor used to write it.

~~~
astrobe_
> I feel that blaming failure on the language used is like blaming a bad novel
> on the word processor used to write it.

Sure. If you're a good novelist you can write something great even on a
keyboard with a broken 'e' key (btw, your 'I' key is about to break; you
should replace it asap).

But novelists don't have deadlines and when the novel is done, they usually
don't take reader requests to change this or that part of the story.

"The advantages and limitations", what works and what doesn't, "areas to
avoid" are precisely the point of that kind of review.

~~~
placebo
> (btw, your 'I' key is about to break; you should replace it asap).

haha - touché, point taken :-)

Deadlines seem like a great excuse for compromising quality. Sure, life is
complicated, the boss is demanding, the mortgage has to be paid, the children
need to be supported etc. etc. but compromising quality and enthusiasm (they
usually are correlated) because of the "terror" of a deadline will just leave
you at the mercy of the next "terror", only this time you'll even have even
less enthusiasm to fix the spaghetti. Doesn't sound like an enjoyable
existence.

Of course, very few people have the privilege of never having to compromise,
but it's never black or white and there are many more degrees of freedom to
choose the path with more quality than are implied.

>"The advantages and limitations", what works and what doesn't, "areas to
avoid" are precisely the point of that kind of review.

The "area to avoid" in the review is Node.js and considering that large and
impressive projects have been written in it, it seems that this is another
case of throwing the baby out with the bathwater.

------
beders
Now all of a sudden, having types and some standards to gather around doesn't
sound like a bad idea anymore ;)

I agree with one of the commenters: Lessons already learned by older engineers
(who went through similar woes with other languages/tools) are being re-
learned again and again.

The software industry is in a sorry state.

Unless you are a very disciplined team with a very strong sense of writing
modular code, don't use Node.js for any larger project. And even then, the
single-most useful function in an IDE 'Show Call Hierarchy' will never be
available when using a dynamically typed language.

That is not an issue for smaller projects. However, long before you even get
close to the the million lines of code project size, your tools will fail you.
Your debugging/refactoring times will explode and adding a new feature will
seem unsurmountable.

Instead, let's just re-write everything from scratch because the cool hipster
that wrote your backend a year ago has left for greener pastures...

I won't even try to guess the amount of technical debt produced with Node.js
and the likes each day in the bay area.

And, yes, I just used Node.js to write a Slack-bot. It was fun, took me two
hours and got me up and running quickly. That's the beauty of it. Just be
aware of the dangers.

~~~
encoderer
I've worked in three million+ loc codebases, in PHP, Python and Java. I don't
share your opinion that you need static types in these circumstances. You need
discipline, modularity, and most importantly you need to have been blessed
with gardeners and maintainers throughout the life of a project and not just
after a mess has already taken hold.

~~~
beders
Did you read what I wrote? I already said that you need a disciplined team.
Good luck keeping that team together for years to come. Not sure if you are
disputing the fact that keeping code around is a challenge, or not.

------
tylerlh
The Netflix.com site and webapp runs on Node (and talks to a number of
services written in mostly JVM based languages). While we encounter challenges
just as we would with any other language -- it works for us and I would argue
that it's a pretty big application.

There's always a multitude of ways to get something done, and it's up to you
to decide what tool will do it best. Don't treat any one language as an end-
all-be-all and you might find yourself much happier and more productive. Of
course, YMMV.

~~~
ChrisAntaki
> There's always a multitude of ways to get something done, and it's up to you
> to decide what tool will do it best

Well said.

By the way, what is Netflix's take on Promises vs RxJS?

~~~
ZoeZoeBee
I'm pretty sure Netflix is in the Observables camp, as Ben Lesh over at
Netflix is RxJs

~~~
Akkuma
I watched one of the recent Netflix engineering videos where they moved to a
customized version of React and I could have sworn in that talk they actually
moved away from Observables[1]. What was confusing is that the other talked
released at the same time they talk about enhancing RxJS.

[1]:
[https://youtu.be/5sETJs2_jwo?t=5m32s](https://youtu.be/5sETJs2_jwo?t=5m32s)

~~~
mikeryan
A friend of mine runs some UI engineering at Netflix from talking to him
reactive JavaScript is still heavily used.

~~~
Akkuma
I'm sure it is still heavily used, but it looks like there are two very
opposing views with one going so far as completely removing it.

------
joshmanders
These types of articles make me laugh. Typically a dev with many many years
experience with one language, learned all it's quirks, standards, etc decides
to try Node.js because it's the "new hot fun toy", and expect it to work like
their old language, and realize that is not how it works, doesn't know where
to find what and fails real hard to realize that JavaScript in general is in a
huge influx of updating at this moment, which by nature propagates to Node.js.

The end result is they get frustrated and go back to their old language.

~~~
eva1984
Yeah, so some js devs might need to stop overselling javascript to everyone,
pretending it is the one language that people are waiting for years...Just
saying.

~~~
joshmanders
You should try to surround yourself with developers who don't have such
attitudes. I am a fan of JavaScript, I love Node.js and I will often times
suggest it to newbies. But I don't pretend it's the be all/end all of
languages. Just like any other language it has its strengths and weaknesses.
It's up to you to decide if it's the right choice for you.

~~~
uptownJimmy
It is one of my most cherished professional goals to avoid ever working with
people who think like this. The message this sends to junior devs is so
backwards and wrong-headed that it defies discourse.

~~~
jackweirdy
Why? It seems like a reasonable statement - surround yourself with people who
think critically, not evangelically?

~~~
uptownJimmy
But I see your point as being precisely backwards: it's the JS crew who
constantly evangelize for their way of doing things, and that way of doing
things is completely inappropriate for anyone who isn't already expert.

"Choose your own tools" is advice for experts, and literally nobody else. It
smacks of the cowboy attitude, and that attitude is wildly unhelpful to almost
anybody doing professional work in software. Frameworks and coding standards
exist for a reason: not to be unreasonable strictures, but to provide guidance
and sanity in a staggeringly complex field of endeavor.

Many new devs and junior devs are flocking to the JavaScript ecosystem, and it
is one of the most troubled and chaotic ecosystems in all of software right
now. Anyone who is not a complete JS badass is simply not going to find Node
to be even a decent choice for learning best practices pertaining to the
larger world of application development. And I feel I'm stating that politely.

So: yet another JavaScript Pro tossing out the "choose your tools like a Pro"
advice-morsel is part of the problem, as I see it. I don't want to work with
people who toss the kids into the deep end and hope a few can learn to swim
real quick. I think people deserve a helping hand and a reasonable set of
expectations.

The JavaScript ecosystem has become self-parodying. Anyone who is oblivious to
that fact is inherently NOT a trustworthy witness. That is not to say that the
whole thing is rotten and worthless, but it IS messy as heck, and refusing to
acknowledge that is a sign that one is in denial about some pretty blatant
facts.

------
spion
> Coming from other languages such as Python, Ruby or PHP you’d expect
> throwing and catching errors, or even returning an error from a function
> would be a straightforward way of handling errors. Not so with Node.
> Instead, you get to pass your errors around in your callbacks (or promises)
> - thats right, no throwing of exceptions.

Promises let you throw errors normally. They will propagate up the call stack
in a similar manner. With bluebird, you will also get full stack traces in
development mode and the performance penalty for that isn't too bad.

> The last thing that I found frustrating was the lack of standards. Everyone
> seems to have their own idea of how the above points should be handled.
> Callbacks? Promises? Error handling? Build scripts?

Promises are in ES6 (i don't think it gets more standard than that) and have
well defined semantics, including error handling, shared between libraries:
[https://promisesaplus.com/](https://promisesaplus.com/)

I know that Bluebird's promisifyAll might seem like a bit of a hack, but just
try it out. It works surprisingly well, and its really painstaikingly tuned
for near-zero performance loss. It will probably be both less painful to do
and more performant than any manual attempt to wrap a callback based API into
a promise one.

~~~
pjungwir
I gave a talk about handling errors in Node a few years ago:

[https://github.com/pjungwir/node-errors-
talk](https://github.com/pjungwir/node-errors-talk)

At the time the solution was "use domains", but I think domains are deprecated
now. It was painful enough that I have stuck with Rails since then. I'm glad
to hear that Promises are an improvement!

~~~
koolba
Domains have been deprecated since at least 0.10. As of yet there's no
replacement for them and all node apps should be using them. There's no other
way to catch " _But ... but ... that can 't happen!_" type errors.

~~~
spion
There is no replacement because they're a fundamentally broken idea. They
require the following to happen, in that order:

* V8 needs to optimize try-finally

* Node core needs to add try-finally at every single place where callbacks are invoked and make sure all state and resource cleanup is properly done to support domains

* Popular libraries need to also add try-finally handlers for the above.

As to why this is a problem in node and not so much in other languages, its
because with node callbacks, the call stack goes both ways. In other
languages, libraries mostly call their dependencies' code. In node's CPS
style, you call the library but the library also calls your closure code. The
semantics for the 2nd part aren't well defined in node - the loose law
basically says: I wont call you twice, I'll try not to call you synchronously,
and you wont throw (and if you do the behavior is undefined).

With promises there is a contract and its enforced by the promise
implementation. Since Promises actually have error semantics, you can build
resource management strategies on top of them. [http://promise-
nuggets.github.io/articles/21-context-manager...](http://promise-
nuggets.github.io/articles/21-context-managers-transactions.html) \- and
consequently there is no reason to crash your server on errors.

~~~
lobster_johnson
Domains are used for another reason: To emulate thread-local variables. I hope
that support is not going away, because it's really handy.

~~~
spion
Its interesting that the same problem (TLS) can also be solved with something
similar to promises :)

------
Corrado
I agree with this article and find the Node.js community, and to a lesser
extent Javascript itself, exhausting. It seems like every 2 minutes there is a
"more" proper way to do something, which tells me that the architecture is not
yet mature, even though it's pretty old by now.

On a related note, it seems like every time you find something that doesn't
quite work correctly or conveniently in Node.js there is a "fix". Don't like
callbacks? Force Node.js to look more like other "normal" code and use
Promises. Having trouble getting Node.js to concentrate on one thing at a
time? Force Node.js to look more like other "normal" languages and use the
"async" library. And it just goes on and on and on. If I have to use all of
these other pieces and parts to be productive in Node.js I may as well just
use some other language.

I really wanted to like and use Node.js, but Javascript and the community are
holding it back.

~~~
eagsalazar2
Yes, the Javascript world is quickly evolving both on the front end and
backend, and of course that can be exhausting but I have to disagree with both
conclusions that (a) this means the tech is immature, and (b) the community's
readiness to make changes is "holding it back".

The js world is very unique in its ability to evolve quickly and things have
improved _massively_ over the last few years. Now, apart from the churn itself
and precisely because of that rapid evolution, front end and backend
development in javascript is amazing compared to most other options
(especially on the front end). So while you do have to be realistic about the
cost of the evolving ecosystem, it is just a tradeoff for rapid progress, not
a flaw.

If you crave stability, agreed, this rollercoaster probably isn't your ride.
But the evolution of node, the emergence of react/redux, es6, etc is amazing
and beautiful IMO and I'm totally enjoying every bit of it compared to the
staid mediocrity of my Rails, C/C++, and Java history.

~~~
rimantas
The problem I see that in this case "evolving" looks suspiciously like running
in circles without going anywhere.

~~~
royjacobs
A good example mentioned in the article is the "npm scripts -> grunt -> gulp
-> npm scripts" evolution in best practices for building.

------
programmarchy
Never had the problems with Node described in the article. Node forces
thinking about modularity and composition though, which I'd wager is what the
author is actually struggling with. Write functions that do one thing and
they're pretty easy to compose, even if they're asynchronous. It's really not
hard to debug what went wrong in the stack trace when you name your functions.

And I think exception handling is much worse than passing errors up through
callbacks. It forces you to think about edge cases. Not sure how python
handles this, but I can't tell you how many times I've seen Java or C# code
swallow exceptions which is much harder to debug IMO.

People really seem to have a problem with there not being "the one true path"
in Javascript, but it's not something that gives me much anxiety. Javascript
is incredibly moldable, which is part of what makes it so powerful.

------
eknkc
TLDR;

Author actually wants to use Python. Used Node.JS regardless, for whatever
reason.. It did not work the way Python works. Author is frustrated. Complains
that JavaScript is not Python.

~~~
fredrb
This. You can't apply some other language paradigms in every programming
language just because it's the only thing you know how to do.

------
Wintamute
> You use Grunt!? Everyone uses Gulp!? Wait no, use native NPM scripts!

Although couched as a criticism this is actually the community fixing itself.
The evolution from Grunt > Gulp > npm scripts is movement away from needless
complexity towards simplicity. Npm scripts are effectively just Bash commands
that build and manage your project, which sometimes employ small, unixy tools
written in Node.

This self correction was pretty quick, it happened within a few years.

> Unfortunately, there isn’t any one “standard” (like everything else in
> Javascript) for implementing or using Promises.

Yes there is. It's called the Promises/A+ spec, and its built into ES6.

~~~
Touche
NPM scripts are just a different problem. See:

[https://twitter.com/sindresorhus/status/724259780676575232?l...](https://twitter.com/sindresorhus/status/724259780676575232?lang=en)

[https://github.com/ReactiveX/rxjs/blob/a3ec89605a24a6f54e577...](https://github.com/ReactiveX/rxjs/blob/a3ec89605a24a6f54e577d21773dad11f22fdb14/package.json#L14-L96)

Already people are coming up with new "solutions" to this problem that looks
more like Grunt. It's a repetitive circle. Personally I just use Make.

~~~
Wintamute
So somebody found a project somewhere on the internet with an exceptionally
complicated build process, and you use it to say npm scripts are broken?
Sorry, that's absurd. Looking at that particular build process, I don't think
a Makefile could have been crafted to make it much simpler or smaller. In that
example, the problem lies with the complexity of what they're having to do,
not the tool.

Npm scripts are really just shell scripting, which means all the real progress
happens in the unixy Node tools that do the heavy lifting, where it should be.
It's a future proof and scalable approach for the vast majority of projects
imo.

~~~
Touche
It's an inflated example of what all npm script projects become, imo. First
you just have "test", then you add "build", then you separate your "test" into
one for the browser, one for Node, one for CI, then you need scripts that
combine those together; then you create different "start" versions depending
on environment... It blows up quickly.

> Npm scripts are really just shell scripting, which means all the real
> progress happens in the unixy Node tools that do the heavy lifting, where it
> should be.

That's fine, but you're missing critical features that Make provides; make
won't even rebuild a target if no files have changed.

~~~
Wintamute
Admittedly, my first 2 or 3 npm scripts based build processes did start to get
a bit ugly. But I'm much better at writing them now, so they stay pretty sane.

> That's fine, but you're missing critical features that Make provides; make
> won't even rebuild a target if no files have changed.

WebPack does this for me too. Also my ava tests don't rerun for files that
haven't changed while watching.

Genuinely curious, what scenarios precisely do you find this feature of Make
useful?

Also, Make isn't truly cross platform ... and since I sometimes work with
Windows devs this would be a problem.

------
kcorbitt
I've spent a lot of time writing Javascript on the front-end in the last year
using both React and React Native. I've found the React ecosystem to be a
sane, productive and enjoyable development environment.

Interested in sharing more model logic between our front- and backends, I also
investigated writing some new backend features using Node (we're currently
developing with Rails). But after days of research and playing around with the
available options, I came to a conclusion similar to Gavin's -- any reasonably
complex backend requires you to either roll your own everything, or try to
cobble together literally hundreds of tiny dependencies that weren't built to
go together, and then somehow keep track of all of their regressions and
breaking changes.

Node's fantastic performance and unique ability to share logic between client
and server are enticing, but I just don't trust the community and "best
practices" around it enough to bet the farm on it for now.

~~~
wrong_variable
The same problems you cite for node.js are the reasons why a lot of devs love
node.js.

Its much easier to do your own research and find the best module to solve a
particular problem you are having then to shoehorn into some larger monolithic
framework.

Also its a lot more fundamental then that - Node.js has prolly the fastest
iteration cycle for any platform out there since its so easy to create your
own module - it leads to some sort of Cambrian explosion of innovation and
experimentation.

EDIT:

Also OP seems to think callback hell and async programming is bad. The
important thing is those things are problems for python/.... too !

Its just that python doesn't have a good programming model to even begin to
address those concerns.

JavaScript at-least tries to say - "hey this is a problem we need to deal with
- concurrency is a issues we all face "

So when devs complain about callback hell - its just that they have never
tried to use python to do async in a neat way.

~~~
empthought
> python doesn't have a good programming model to even begin to address those
> concerns

This isn't even close to true. Anything JavaScript has to express logic in the
face of asynchrony, Python has too. There are a half-dozen asynchronous web
servers written in Python.

There's not as much of a culture of writing APIs that way in Python because
it's generally a terrible way to program, and threads/OS processes are good
enough for basically everything except HTTP servers with absurd numbers of
concurrent connections.

~~~
wrong_variable
> There's not as much of a culture of writing APIs that way in Python because
> it's generally a terrible way to program

I would love to see evidence for you making that statement. Almost every
programmer would put out their fav programming language as the 'right' way to
program.

> everything except HTTP servers with absurd numbers of concurrent connection

Once you introduce async operations in your code - you need to follow the
execution path through. http request can be async - but then what if the http
request results you doing a db lookup or some form of file handling ? you need
to make the whole thing event driven.

~~~
empthought
It's not like we didn't have cooperative multitasking for 50 years. Having
threads/processes and a scheduler is easier and safer, full stop. Potentially
long-running portions of the program don't need to be arbitrarily chopped up
to yield control back to the server, because they are pre-empted. Your system
is no longer at the mercy of the worst code within it.

Both nginx and Apache's event MPM handle HTTP connections with events while
the app backends are still using preemptive threads for running the HTTP
handler code, so it's clearly not the case that "you need to make the whole
thing event driven." You just need programmers who don't think, "well since
the browser doesn't expose threads to JavaScript programmers, clearly they are
useless."

------
narrator
I'm using NodeJS on a pretty big project.

Things I like:

* Async libraries make it easy to make things high performance.

* I like Sequelize as an ORM, once I figured out how the async everything works.

* The testing support is pretty good, both mocha and e2e testing using selenium

* The angular-fullstack generator was really helpful for getting started and setting up the deploy to Heroku.

* everything is open source. If I get confused with what a library is doing while I'm debugging I can just stick a print in the lib temporarily.

Things I don't like:

* "undefined is not a function". When something goes wrong. This is the error I get 80% of the time.

* async stuff silently swallows exceptions unless I put try{} catch(err) { console.trace(err) } everywhere

* There's a bit of a learning curve with promises.

* Needs a lot more automated testing than a really strongly typed language like Scala.

* Single Threaded. I know how to program using threads, so I view this as a disadvantage.

* No types. I have a lot of type checking asserts at the beginning of dao functions.

If I did it all again and my teammates would oblige, I would have probably
chosen Play/Scala. I actually reimplemnted things from a Play/Scala project I
did a while back (login/signup/forgot password/confirm account) and it took
less time in Play/Scala, even without passportJS and friends. I have about a
years worth of experience learning Scala before I started that project, so it
would probably take longer for a new Scala developer.

~~~
rhinoceraptor
> async stuff silently swallows exceptions unless I put try{} catch(err) {
> console.trace(err) } everywhere

Huh? That's not how async errors work in Node. Try/Catch is not async, the
catch block will not magically transfer to your callback function.

You check for the error as the first parameter in your callback, that's the
standard way of error handling. Throwing errors in Node is considered by most
to be an anti-pattern.

~~~
narrator
That's nice in theory, but third party libraries may throw exceptions if
unexpected things happen at runtime. You'd still have to put the try catch
block there and call the callback in the catch block everywhere.

~~~
rhinoceraptor
That's only for non-async stuff, which is very rare. If you're using some
wacky 3rd party code which throws an Error instead of the accepted convention
of (err, response) callback arguments (or returning a promise), I suggest not
using it.

------
mrmondo
We couldn't even stand 6 months let alone a year. Broken pack depts make it
hard to CI, poor performance, memory leaks, huge docker base images due to
deps, lots of single cpu only tasks that were too hard to scale out, an ugly
language compared to ruby or Python and on top of all that how poor the
package management with NPM has been. We've just ditched it and gone back to
Python/Django/flask and ruby for the ops tooling.

------
silviogutierrez
Same experience as the author. Tons of reinventing the wheel, and hundreds of
dependencies.

The majority of established companies that say they use Node in production are
doing so as a fancy proxy. All the "serious" stuff is done on backend services
written in other languages.

Moreover, asynchrony is a concept far more advanced than most people think.

We will likely continue to leverage Node as a fancy proxy. Adding Typescript
will only help. But it's likely that as Node grows into a mature platform,
other platforms will continue to fill in the gaps that Node filled.

See for example Node constantly adding [foo]Sync versions of methods, while
Python adds first class sync support.

------
firasd
I've been on a similar learning curve with Node over the last year, and it has
certainly been a rougher incline than other languages I've used.

The whole async situation needs to settle down, it's completely unacceptable
to write code with callbacks, promises, etc. This is because they are not just
challenging to deal with, but intrinsically wrong in concept. I have to wait
for a database query to complete, then pass the next thing to do to the
callback of the query? That can't be right.

Interesting article I found: "Async/Await: The Hero JavaScript Deserved"
[https://www.twilio.com/blog/2015/10/asyncawait-the-hero-
java...](https://www.twilio.com/blog/2015/10/asyncawait-the-hero-javascript-
deserved.html)

~~~
Silhouette
I find that JS often seems to tie programmers in the most extraordinary knots
just to implement even quite simple logic, because of the single-threaded
nature of the language.

In the programming model used by most other mainstream languages today, if
you've got some work to do that interacts with some external system and might
take a while, you'd probably start another thread for that task. You'd write
the required logic in the usual linear fashion, and just let the thread block
if and when it needs to. Modelling this using fork/join semantics and
techniques to co-ordinate access to shared resources from different threads
are reasonably well understood ideas.

Because there is no general support for concurrency and parallelism in JS, you
only get one thread, and so in most cases you can't afford to ever block it.
Consequently, you get this highly asynchronous style that feels like writing
everything manually in continuation passing style, just so you can carry on
with something else instead of waiting. That in turn leads to callback hell,
where you start to lose cohesion and locality in your code, even though
usually you're still just trying to represent a simple, linear sequence of
operations.

Async/await help to bring that cohesion and locality back by writing code in a
style that is closer to the natural linear behaviour it is modelling. However,
even those feel a bit like papering over the cracks in some cases. Async/await
kinda sorta give us some simple fork/join semantics, but as the blog post
linked from the parent shows, we have a lot of promise-based details remaining
underneath.

Fundamentally, the problem seems to be that JS is increasingly being used to
deal with concurrent behaviours, but it lacks an execution model and language
tools to describe that behaviour in a natural, systematic way as most other
widely used languages can. Being strictly single-threaded avoided all the
synchronisation problems in the early days, when the most you had to worry
about was a couple of different browser events firing close together and it
was helpful to know the handler for one would complete before anything else
started happening. I'm not sure it's still a plus point now that we're trying
to use JS for much more demanding concurrent systems, though.

~~~
Touche
> Modelling this using fork/join semantics and techniques to co-ordinate
> access to shared resources from different threads are reasonably well
> understood ideas.

Writing thread-safe code is anything but easy in languages that support
threads.

~~~
Silhouette
I respectfully disagree.

Dealing with _shared state_ is not always easy when you're working with
multiple threads. If you can't reasonably avoid that sharing because of the
nature of your problem, and if your choice of language and tools only provide
tools on the level of manual locking, then I agree that writing correct,
thread-safe code has its challenges.

However, there are plenty of scenarios where you don't need much if any state
to be shared between threads. That includes almost every example of JS
promises or async/await that I've seen this evening while reading this
discussion and the examples people are linking to.

There are also plenty of more sophisticated models for co-ordinating threads
that do need to interact, from message passing to software transactional
memory. These are hardly obscure ideas today, and I don't think anyone could
reasonably argue that for example message passing makes things complicated but
async/await/promises make things simple.

------
deedubaya
For all the comments on here about how unfair the author was, there sure is
minimal feedback on the problems they highlighted.

~~~
snappy173
the feedback is: stop expecting javascript to act like python

~~~
deedubaya
How productive!

~~~
snappy173
sorry if that came off harsh, but that is actually the feedback, and it's
valid. whether or not javascript/node is better or worse than python, it's
pretty clear that bringing a python style approach to nodejs is going to cause
problems, especially with error handling and async stuff.

------
mrgalaxy
I have used Node.js in production for about 5 years now and I must agree with
the sentiment that JavaScript is "Easy to learn, impossible to master". Yes,
error handling is a little confusing at first but it stems from JavaScript's
asynchronous nature which is naturally complex for the linear mind.

My personal sentiment is to just use Promises, like everywhere. ES7
async/await will really help with this too.

------
clessg
For web applications, I've been very happy with the up-and-coming Phoenix[0],
a framework for the Elixir language.

Very well-designed and thought-out, fast, productive. Leans functional and
immutable rather than object-oriented and mutable. It's kind of like Rails but
without most of the problems.

[0] [http://www.phoenixframework.org/](http://www.phoenixframework.org/)

~~~
deedubaya
I've found Elixir to be a delightful language with very palatable syntax
compared to ruby. It has been a really enjoyable transition, with some vague
reminders of the parts I really like about JavaScript.

------
emilong
I've been using Node in production for a few months now, having come from Ruby
(Rails & Sinatra) immediately before, but having used JavaEE and PHP before
that. I find it... fine.

For error handling, bluebird's typed error catching
([http://bluebirdjs.com/docs/api/catch.html](http://bluebirdjs.com/docs/api/catch.html))
is working well for me and I'm finding it analogous to my experiences with
Java and Ruby.

I'm rather used to using ORMs as well and I use Bookshelf
([http://bookshelfjs.org](http://bookshelfjs.org)) on top of Postgres for this
as well. It definitely has room to grow, but it's also fine.

I've also gained a dependency injection container (Bottle.js, see my write up
here: [https://blog.boldlisting.com/declarative-dependencies-for-
un...](https://blog.boldlisting.com/declarative-dependencies-for-unit-testing-
node-js-services-45542ceb5703#.gaf9om7zj)), which I sorely missed in my Rails
days and which gives a lot of structure to the application.

I think the biggest concerns on which I'd agree with the author are the pace
of the community and lack of agreement on things which are well-decided in
other, more well-established development environments.

That being said, there's huge potential with Node because of that. There are
more coders in the world than ever (I'm assuming) and Javascript is a great
low barrier to entry language that encourages people to explore various
runtimes. In 20+ years of coding, I've not seen this level of excitement and
engagement in a development environment. While it may be rocky for another few
years yet, I suspect we'll end up with a very productive platform, simply
because of the amount of involvement. Of course, it's totally understandable
to want to wait for that before jumping in. :)

As a relatively new Node developer, I'm much more concerned about the single-
threaded nature than the development environment, but so far even that hasn't
been a problem.

------
Touche
A lot of this is residual effects of the (slow) evolution of JavaScript. It
was thrust into the spotlight missing a lot of features and these features
have only recently been fixed by the language itself.

But Node has been around since 2009. 2009 JavaScript was missing _a lot_ of
features. It was basically a runtime only advanced users should use. The Node
maintainers had to make a lot of decisions that now conflict (to some degree)
with fixes that have come later to the language. They chose their callback
style; now we have Promises. They chose to throw in methods rather than return
an error in the callback (this makes it awkward to use fs with Promises
without a wrapper library). They chose to implement their version of CommonJS,
now we have the .mjs issue arise.

------
nevi-me
Been on Node and Mongo for 4 years now. Both have worked well for me.

JS has evolved a lot in the past few years, and with it came all the new shiny
tools that left us confused.

I think a year was too short for the author. Sounds like they were chasing
after every cool thing to make life easy.

Error handling is a pain yea, I've seen amateur folk try catch this and that,
I think that lends itself to being terrible.

One of the things I appreciate the most about JS is JSON. Crafting tens of
classes in Java irritates me. I find Python sometimes tricky also when dealing
with structs VA lists.

I've always stuck to the basics when I was learning how to JavaScript with
Node. I used only callbacks for 2 years until I understood what my code was
doing. Granted, I'd have spaghetti at the end of complex async queries, but I
understood what was going on. I moved to caolan::async and have been using
async whenever necessary. I barely use promises as I got confused by the early
adoption craze.

I learnt how to use Backbonejs, and a bit of Angular+React+Ember, but I found
myself comfortable using vanilla JavaScript. Only thing I use is Underscore
templates. I know I could benefit from shadow DOMs etc, but I'm content where
I am.

I think a good way to learn is to take things at bite sized chunks. I've
started using RxJS recently, and I'm loving it! I'll keep using JS as my
primary tool, but I'm slowly moving to Kotlin.

------
kartickv
If this article is true, it paints a concerning picture. I don't want to
research libraries, understand the pros and cons of them, run into problems,
then switch to another library, and so on. I want there to be a default that
works out of the box for the majority of use cases. There can be alternatives,
as long as there's a default that works out of the box for most people and
most use cases.

------
eldude
I train enterprise node.js for a living.

My recommendation is to just use songbird (which exposes the forthcoming
promise API from core, built on bluebird), async/await and the async
`trycatch` library so you don't have to worry about a 3rd party package's
choice of asynchrony. It also comes with optional long stack traces.

~~~
snappy173
>async/await

in my experience, async/await is a great way to layer indirection and
obfuscation over what is still callback hell. it may look better in the
editor, but it's hell to debug.

~~~
raarts
When I initially encountered event -based processing (libevent in C), those
callbacks were indeed difficult to wrap my mind around. But I learned to
structure the code in the editor, keeping everything together which made it
manageable. I 've worked with node for a couple of months now, and I find
promises to be more confusing, because it obfuscates the callback in my mind,
and makes it look like ordinary function calls.

~~~
spriggan3
The advantage of promises is that you can return them as a type, you can't do
that with a callback. If you fetch something from a database , your data
access object can return a promise and let the client code deal with the
result. Promises are composable by nature, callbacks are not.

------
SiVal
Really, just learn to use callbacks properly. Well, wait, actually, you should
skip that and start getting used to using promises instead--a big improvement.
Well, I mean, until next version is ready, and we can start using
async/await...until wasm makes better thought-out languages available.

Despite the sounds of this, I do like the idea of having an experimental
platform with which to gain experience using wildly different approaches to
the wildly changing world of web apps. I don't take it for granted that old
language concepts will turn out to be the most useful for the web platform.

So, I'm okay building a website for the PTA or ceramics club with this, and
I'm very interested in the experiences of others using a wide variety of
technologies and approaches, but I'm not sure Node.js would be a sensible
foundation to build a business on.

------
tonyjstark
This article definitely matches with my experience. I did two not all too
complicated projects on the side with Node.js and the the first steps where so
easy that it completely convinced me to go with it. After a while I tried to
dig deeper and went to meetups to see whether I do things right as in a
community accepted way and if I use the right tools and so on. Since then I
refer to the Nodejs community as the most hipster programmer community I've
ever seen. As soon as a framework was getting near a 1.0 version nobody wanted
to use it anymore, experimental features were used in production code, it was
horrifying. For me that ended this endeavour, I just could not keep up with
the pace. I always wondered if it would be different if I would have worked
full-time on Nodejs projects.

------
ldehaan
From reading the comments there are Still a lot of misconceptions about Js.

javascript is not new, it's been around since before most of the web devs out
there started working in computers.

nodejs supports multiple CPUs.

nodejs is stable.

JavaScript is retarded fast, and it's not c or c++ or any Compiled language,
and shouldn't be compared to them because that's unhelpful as a measure.

it is the only language for the web which enables you to work in the same
language on both fronts.

frameworks aren't JavaScript.

nodejs isn't JavaScript.

JavaScript is so flexible that it can be changed to suit the needs of those
writing it, so much so that you get whole new dsl's like typescript.

there are more conversations on the internet about JavaScript than any other
language being used today.

oh and nothing scales if you don't know how to write scalable software, that's
on you, not the language.

------
bschwindHN
Interesting analysis. I just finished a year of using Node for implementing an
HTTP API and a chat server, and found it to be actually pretty pleasant. I'm
not chasing the latest and greatest things, there's no ES6, no ORM, and I'm on
an older version of Node. But it works and has actually been quite stable! The
things I've missed are static type checking at compile time, and execution
speed (which is less of an issue when you're talking with databases all the
time). I'd be happy to write in more detail if anyone has any questions, but I
found I had the opposite experience of this author. The situation makes all
the difference though.

------
Chris911
Most of the problems described in the articles can be solved by simply using
promises. Error handling is centralized in your chain and any function can
throw and just like Python or Ruby you can catch anywhere you want. As for
consistency between callbacks, promises and generators, just pick one. We
switched from callbacks to promises and it was a great move. Error handling
greatly improved and the code looks a lot nicer. No more callbacks hell. Ever.

We switched our backend from Python to Node almost 2 years ago now and it was
a great decision for us. If you handle a code base that deals with a lot of
async requests Node is definitely a top contender.

------
cyberpanther
I think by reading the comments here and the article, its apparent that
Node.js just isn't as mature yet. If you know what you're doing, it can be
great, but for the noobs the right way to do things is not easily apparent.
Couple this with the huge choice in libraries and frameworks, makes Node.js
harder for now. I think the base is good though and given more time it will
become more easy to wield. This is typical of any new tool. And yes Node.js
has been around the block for a while, but it is still newish compared to
Python, Ruby, PHP, etc. So you're going to pay a new adopter tax still.

------
jrapdx3
Can't fully agree with the article re: using nodejs in production. A couple of
years ago I decided to use nodejs for a rewrite of a web/database app that had
gotten to be complex and hard to maintain.

As so often said, it was true for me that the abundance of modules and choices
in node was at first very confusing.

I eventually figured out that keeping things as simple as possible was my best
approach. What I came up was a server relying on very few module dependencies
and written using consistent if not so elegant components. Sure it's kind of
verbose and far from totally DRY but fairly easy to understand, modify and
extend.

Key issue was node's "callback hell" style of async programming. Of course,
it's not just node, other languages (Scheme, FP, etc.) can be mind-bending in
a similar way.

The callback "inside-out" locality inversion was initially hard to grasp, but
once I caught on it was possible to get the server working the way I needed it
to. The more recent development of promises, etc., certainly provides
reasonable ways to reduce the high barriers implicated in using the nodejs
style of async programming.

~~~
zyxley
Callbacks definitely become much, much less of a problem once you can turn
everything into promises.

------
EdSharkey
In my opinion, JavaScript is a toy language. Looking at it, and the Node.js
ecosystem by-extension, that way has really helped me be effective with it.

Tooling has never been more important to my productivity with a language as it
has been with JS. I constantly search for tools to paper over the warts and
potholes.

------
gedrap
The only clear, objective advantage of using nodejs is that if your
application is I/O heavy (e.g. tons of sql queries which can be executed in
parallel), nodejs event system is helpful and everything you need is pretty
much out of the box. Other thing... it largely depends on personal taste and a
matter of convention.

Reading his "Why I’m switching from Python to Node.js", doesn't seem like he
was having an issue with that. And I don't really buy into the "same language
everywhere" argument because come on, how hard is it to learn python, ruby,
etc enough so that you can be productive? Not hard at all, unless you have
hundreds of cubicles filled with drones.

Anyway, it's good to see that he made some reasonable conclusions after the
experiment. That's a good sign :)

~~~
MichaelGG
Same language, in theory, is great. Reuse structure definitions. Reuse
rendering logic or even validation logic (perform checks on both, but make it
easy to get into client-side). In general, keeping things "in sync".

Also can make it easier to write in SPA style but offload rendering to the
server when you need it (particularly first-page or reloads).

Whether or not tooling is good enough to allow this (either with JS or
compilers) is another issue.

------
Clobbersmith
We use NodeJS pretty extensively at Yahoo for both front end and back end
services and it works well. While some of the complaints are valid, it's not
worth flipping tables over.

Promises are standard in ES6 and it is "the way" to handle errors. At least if
you want to stay sane.

------
btomar
Though I agree with what you all explained with the big issues with NodeJS,
you have to understand its not all of Javascript. Its only server side JS. The
creators have clarified, for heavy CPU intensive services, go away from
NodeJS. As far as frontend is concerned, AngularJS and React are just sugar
candy for user interaction and structure. Node filled the gap with an async
network application in pure JS without the heaviness of Python or traditional
languages. It is a hack as in every day people are finding new ways to use
NodeJS but I agree, there has to be best practices and less boilerplate (plus
less silly npm packages for trivial JS tasks).

------
nodesocket
I prefer to just use async
([https://github.com/caolan/async](https://github.com/caolan/async)) for all
control and error flow. Namely async.auto() can do almost any crazy flow.

------
dustinlakin
I think the switch to an async back-end can be more initial work than many
expect. It may take some time to feel as productive, but promises become
powerful and became a game changer for me over my previous work with
callbacks. Error handling also becomes manageable.

What I really enjoy is jumping into new community and getting to work with
tools that have built. Choosing the right ones can make or break an
experience. I personally enjoyed working with Express and Bookshelf.js/Knex.

I appreciate the authors perspective, but I also don't think this should deter
anyone from trying out Node. I personally have no overwhelming preference to
using a Python or Javascript stack.

~~~
xentronium
> Bookshelf.js/Knex

After ruby orms, Bookshelf felt very, very underdeveloped. Anything I tried to
do beyond "hello world" only brought me pain, especially dealing with
associations, but honestly just about everything. I guess I've been spoiled,
but getting anything done in express/bookshelf combo seemed like a chore.

------
billmalarky
Just FYI, the Koa framework makes node sane again.

Callback hell and error handling are no longer issues in node if you just
embrace generators or async/await.

We use Koa in production and serve billions of requests just fine.

If I had to go back to Express I'd say no.

------
velox_io
There's a very fine line between between removing too much essential
complexity, and leaving programmers with too many limitations. Or the other
end where the language overhead overshadows the original task at hand.

For instance multithreading should be handled by languages and frameworks
99.9% of the time. Take reading a file (something that should be handled by
the language/ framework). Read it asynchronously, structure any dependant code
clearly (which JavaScript does pretty well), if any problems are detected they
display/ log the appropriate error. You shouldn't be kneck-deep in callbacks.

------
spriggan3
The biggest problem is dealing with callbacks (and yes even promises use
callbacks , and generators need to be wrapped in a cor-routine framework in
order to work as cor-routines ).

I want to write a quick script doing some busy work , I now have to think
about synchronicity even though the script does not need to be non blocking.
Of course in these circumstances, I want to move back to Ruby or Python, which
actually let me code the thing I want to code without forcing callbacks on me.

So when you have to do 20 i/o operations in sequence, using nodejs becomes
really tedious.

------
jtchang
Node is one of those platforms that makes me shudder every time I go looking
for solid best practices. It seems to change every 3 months. It's scary (and
cool) how fast things are changing.

------
peterashford
I think the basic problem is that JS is not the right solution for every task
but for the web, it's often the only tool available.

I had similar experiences to the OP. I had lots of code written in JS that I
was happy with to some extent, but all of it would have been easier / cleaner
/ more maintainable in a less crap language.

------
arisAlexis
Using babel without async await is a mistake IMO should solve almost all your
problems and errors. Also the main argument for using js in the back end is
that you have the same team working in the front-end too and in any case in
the same langage.

------
throwanem
tl;dr: "I really miss Python's bondage and discipline, so I'm going back to
it, and I'm going to hate on Node on my way out because I genuinely can't wrap
my head around the idea of a paradigm other than the one with which I'm
familiar and comfortable."

It's not even about Node. It's about anything that isn't Python, and doesn't
have the Python community's strong "there is exactly one way to do it"
tradition. I'm glad OP has realized that's what works for him. It's a shame he
lacks the perspective to understand that it's _about_ him.

------
igl
Async-functions are the answer to all his problems. I generally agree on his
conclusion though: Do small things, don't build big systems.

I hate that JS trys to be this OO-FP hybrid. Jack of all trades, master of
none.

------
swivelmaster
This articulates my fears around switching to node very clearly. I've played
with it in the past and felt like it would become too difficult to manage with
a large project and lots of contributors.

------
paulftw
A year ago one of the reasons to leave Python was poor MongoDB & JSON support,
12 months later the same author complains about the lack of a decent SQL ORM
library in js <scratching my head/>

while JS is far from perfect, his problem was he was a little bit ahead of
time- babel, standard promises & sequelize solve most of the problems. I think
Python is still superior for serverside, but JS isn't as bad as portrayed in
this post, if you slowdown for a couple of weeks to learn how to use it
properly (just like any other popular language or framework).

------
sb8244
I mused on similar things after getting a _very_ small project shipped. It is
based on my experience with Node, Ruby, and Node as of 4 years ago (when I
first learned it).

[https://medium.com/@yoooodaaaa/reflections-on-
node-698abecce...](https://medium.com/@yoooodaaaa/reflections-on-
node-698abecce1b3)

------
z3t4
I think the problem is they chased the latest and greatest.

tips: Always throw errors! Use named functions!

------
jv22222
Uber has done pretty well using node as their core dispatch architecture.

------
tempodox
I find this a valid assessment of Node and JS.

------
co_dh
welcome back :)

------
vacri
Small company ops guy here - a bit over a year ago, I used to joke with my
devs, asking them "So, what's this month's recommended way of installing
node?". More recently we've been experiencing dependency hell, which is
exacerbated by our small team not having enough time to upgrade to the latest
LTS release. Node is definitely a language that you have to _manage_. It
doesn't sit in the background and let you get on with writing stuff.

Is it the right tool for X or Y? I can't say, I'm not a dev. But it does
require a lot of hand-holding and keeping current with the zeitgeist.

------
hasenj
Everyone and their aunt wants to publish an npm module. That's why you get a
ton of badly written poorly thought-out packages.

------
wizard_class
doesnt node support modules? thats a way to avoid callback hell

~~~
fredrb
How so?

------
JabavuAdams
Thanks for this. The Node / Javascript ecosystem just seems like one I don't
want to be a part of.

I feel so lucky to have avoided the whole disgusting web stack.

~~~
bdcravens
Like the author said, Node isn't a great fit for certain apps. It sounds like
yours is one of them.

------
bricss
Author plz, uninstall Node.js, use your so lovely Python and don't make people
concerned.

~~~
tobltobs
Because being concerned is a bad thing?

------
santoshalper
Node.js, meteor, et al. is a great example of what happens when you let
inexperienced developers design a platform and run an ecosystem. Almost every
ounce of focus in this community goes to increasing developer productivity.
Operational concerns like scalability, security, monitoring, are given the
bare minimum of focus. In many years of programming in many languages on many
platforms I have never seen a worse platform and ecosystem than Node.js in a
very popular language (obviously some obscure languages hardly have anything
built around them at all).

I really think it is setting the programming world back a lot. Not to mention
what a thoroughly shitty language JavaScript is. Being able to code your web
app in one language is a neat trick, and the ability to talk back and forth
between client and server so seamlessly does kind of feel like magic, but
otherwise, this is a meaningfully worse language/platform that Visual Basic.

------
jondubois
\- The dependency instability can be avoided by specifying specific versions
of your dependencies inside your package.json.

\- The fact that the ecosystem is evolving quickly is a good thing. Node.js is
still one of the fastest growing software development platforms according to
Google trends so you should expect it to change faster than other ecosystems.

\- ORMs suck (in every language) - They always sucked; ORMs are a massive hack
intended to fix the impedence mismatch between relational DBs and RESTful
APIs. If you used a NoSQL DB with Node.js (such as RethinkDB), your life would
be much easier. Nobody in the Node.js community except your grandma cares
about ORMs because they're considered legacy technology. If you don't like it,
then you can stick to your COBOL and Oracle database.

\- Node.js lets you choose how you want to handle errors. JavaScript offers an
Error class which exposes a name property (which you can overwrite for each
error type) and you can also attach custom properties to Error objects (to
carry back more detailed info specific to each Error type). JavaScript is
really easy to serialize/deserialize so you can even design your error
handling system to be isomorphic (same error handling on the client/browser
and server). I really enjoy error handling in Node.js/JavaScript - You just
have to put some thought into it.

\- The way of writing async logic is changing. The fact that Node.js is
keeping up is a good thing. There is no single right way to handle async
logic. Most well-maintained libraries will keep slowly evolving to use the
newer features of the language but it's mostly backwards compatible (many
libraries support both callbacks and promises).

\- The standards are not bad; they're evolving and you can choose your own
styleguides for your projects. Most JS developers will adapt to new
styleguides as they move between companies/projects.

~~~
flamethroeaway
Is package.json webscale?

