The Tolerance Of Maturity

Walking around the Ferry Building on a sunny San Francisco day Tim Caswell told me about his idea for a better middleware system. He was experimenting with a continuation passing style that would become connect and I told him it was a worthy experiment, as did many other node developers. These were the unstable days of node, the 0.1.x “Ryan breaks all our modules every other release” days.

When Promises were removed from core in favor of the error-first callback pattern nobody thought it would define compatibility in node's ecosystem the way the Promise API had. The idea was that a base callback API would be a better opportunity for the ecosystem to do a better Promise than core had or that some alternative continuation passing system would emerge and that might be where a standard would form and people would build bigger ecosystems on top. That didn't happen.

Looking at connect you can see what a fork in compatibility looks like. connect was released early enough in node's history and express had such a big user base that people wrote, and even continue to write, a lot of modules in this pattern which conflicts with node's standard callback pattern. For people who don't use connect these modules are worthless. A search for connect on npmjs shows where most of the effort in a compatibility fork goes; tying together modules written for the dominant pattern (in this case for node's callback pattern and sometimes streams) in to a style compatible with connect which wouldn't be necessary if it were using the dominant pattern.

When Tim announced connect the community didn't take a big shit on him the way they treat people who fork compatibility now. Node was immature and it had attracted the kind of people who solve problems like this through experimentation and iteration, and so we all applauded the effort and even those of us who didn't invest in the experiment were eager to see its results.

Nobody thought node could mature as fast as it did. This had a lot to do with its popularity, which attracted contributors, and with limiting the scope of the platform, which encourages people to invest more in the ecosystem. The decisions that were made that enforce compatibility were locked earlier than anyone anticipated by the weight of a giant module ecosystem built on their API. Attempts to change even superficial parts of node core, like the names of standard libraries, were quickly reversed because the cost of breaking compatibility became too high.

One day, long before anyone imagined, node.js became a bad place for experiments like the one Tim had done just a year or so earlier. The greater the module ecosystem the less accepting the community was of ideas that conflicted with the patterns they had already invested in.

Today, node is a phenomenal place for innovation outside of its core patterns: error-first callbacks, streams and the node module system. As embracing as the community is of new ideas on top of the patterns established in core it is hostile to ideas that conflict with established patterns of compatibility. Mature communities don't usually tolerate forks in compatibility, this is true across many platforms and the less academic a community is the less tolerant it will be of ideas of for ideas sake and the node community is anything but academic.

As advantageous as it is for someone to build value in the node ecosystem by leveraging its community and modules it is just as disadvantaged for those that wish to conflict with established patterns that describe compatibility. You cant really have one without the other, the pressure of the ecosystem can propel a project forward when it is compatible as hard as it crushes competing ideas.

If your preferred problem to solve is one that node is done solving then node is not a good place for your experiment. Your ideas would be much better served by distancing them from node. Good luck with your experiment but the time for some experiments are over for us, we've moved on to new problems, new ideas, new experiments in new places, and don't have the capacity as a community to uproot or destroy the immense value that has been created in the ecosystem.