The focus of Node.js over the last year has been to increase the number of contributors working on the project. Node.js has seen sustained 100% year-over-year user growth for several years, but the number of contributors was, at one point, actually on the decline.
After a year+ of community building and iteration we’re now healthier than ever. The project has reorganized itself divided into many components and sits at 400 members. Across most repos, which now make up the project as a whole, we’re seeing that ~50% of the contributors in a given month are new to that repository. That means our conversion of users into contributors is six times higher than the growth of our user community. Contributors are essential to the health and longevity of an open source project.
There’s a lot that we’ve learned and are ready to share that encompasses not only tools to help scale human infrastructure, but culture and core values: transparency, participation, and efficacy. We believe these ideas and practices will end up shaping the future of open source in the years to come.
First, let’s begin with the vocabulary and how we are defining the people that make up our community.
Who are your community?
- People using the software: users.
- People contributing to the project: contributors.
- People making decisions: leaders.
How do people become users, contributors, and leaders?
- People try to use your software and locate resources as they go to help them learn more.
- Users seek to make a change, work through the process of contributing, and choose to contribute again.
- Contributors invest enough in contributing to the project that they are valued as a decision maker and given shared ownership of those decisions.
How do you convert people into users, users into contributors, and contributors into leaders?
- Create more users through education.
- Encourage users to contribute through Liberal Contribution Policies.
- Enable more leaders through participatory governance.
In order for these programs to work and sustain themselves they need to have a balance of:
Education cannot be treated as a technical problem. You cannot create a single resource that solves this problem the way you solve problems with code. We often think others will learn how to use a particular technology by taking the exact same path that we followed. Unfortunately, this is the worst way to approach educating more users. People come from a variety of backgrounds and are at various points in their life and career. In order for them to choose to learn how to use your software, and continue to grow and improve their usage, they need resources that they are comfortable with and that resonate with them. Rather than try to route them through the path we used to learn, we need to look at how they learned technologies they are comfortable with and provide them comparable resources. This means you need a diaspora of educational resources, from API documentation, blog posts, and workshops to and traditional training programs.
These resources aren’t in competition with each other, they are complimentary so long as they are done in an open and community-oriented way. This is something we’re still working on because it literally never ends but you can see the effect that NodeSchool has had on the Node.js community. With NodeSchool you can download a workshop and do it at home, and there is a repository where you can log an issue for help if you need it. Simultaneously the NodeSchool community has hundreds of local chapters across the world that run small local hands-on workshops. Many people can’t get over that initial learning curve without some in-person assistance. Each local chapter also onboards participants in each workshop with a repo just for their local chapter where they can continue to ask questions of in the future. NodeSchool ends up attracting two drastically different kinds of entry-level users this way and has been a tremendous resource for growing our community.
The number of users who become contributors, and contributors who become leaders, depends on converting them from one level to the next. While most projects describe their lack of contributors or leaders as “pipeline problems” these are almost always “conversion problems.” In open source your users are usually developers. They either already have the technical competency needed to contribute in some way or they easily could with a little more education. Converting them is a just a matter of lowering the barriers to entry; learning the tools and processes necessary to contribute and designing a review and release process that encourages and retains contributors.
GitHub has done a lot to lower these barriers. There is now a single toolchain to go from modifying software, to sending it to that project, to being accepted across virtually all modern open source projects. Thanks to GitHub these skills are also highly portable from one project to the next. However, a number of major differences still exist between projects like how code is merged, what metadata (if any) is required, the acquisition of commit rights and the release process of the software as a whole after the contribution is made. When it comes to the conversion of users to contributors, these policies account for some of the largest disparities between projects.
In the Node.js project, new contributors account for ~50% of all contributors per month. That is staggering considering that Node.js user growth is about 8% per month. Our contribution rate is much more than just a product of Node.js’s growth in general and is actual a triumph for what we’re calling Liberal Contribution Policies.
Liberal Contribution Policies
- Every contribution, even from a committer, must be a pull request and must have adequate time for review by other committers.
- Every successful contribution greater than a few lines will result in commit rights being granted to the contributor.
This is a wild departure from the traditional practice within many open source projects to guard commit rights to only a few developers. These now outdated policies originated in projects with version control systems far less tolerant to mistakes than git. In git it’s very difficult to make a mistake so grand that it can’t be fixed by another contributor. This means that granting commit rights can be much more liberalized in the GitHub era. Receiving commit rights also acts as a commitment device, especially for contributors newer to open source, as it gives the participants tangible evidence that they have a shared ownership of the project.
Adding more committers means adding more code reviewers, which in turn eases the process of dealing with more contributors. Of course every project is different. The exact process that works for levelup wouldn’t work for every project and, in fact, wouldn’t work for Node.js Core, but the values that motivated it lead to the creation of several liberal contribution policies across the Node.js project in various working groups and repositories. In designing these processes we identified that all successful policies were a balance between three values: participation, transparency, and efficacy. These values are not absolutes, you often can’t be 100% participatory and simultaneously 100% effective, but by balancing the tradeoffs on a case-by-case basis you end up with amazing conversion rates that will continue to grow your project and keep it healthy.
As an illustration, the contribution policies to the Node.js website and to Node.js Core are widely different. In Node.js Core commits land on master, which is a future as-of-yet unreleased version of Node.js. Contributions are then cherry picked to branches for the current, LTS, and maintenance versions on a commit-by-commit basis. This wouldn’t be possible without clean squashed commits and clear commit message metadata. As a result committers can’t use the GitHub merge button and often have to take on additional work by hand. This is certainly a barrier to participation but one that is necessary in order for the project to be effective. But these technical requirements don’t exist on the website where each merge results in a new deploy of master. As a result, the contribution policy for the website allows committers to use the merge button and does not require squash commits or added metadata to the commit messages, which results in a lower barrier to entry for new contributions. More often than not, processes in open source act as a barrier to entry for new developers and there’s some fundamental approaches we’ve taken to ensure that these policies encourage contributions rather than act as a deterrent.
- Whenever possible, design a process for the smallest casual contributor rather than the most active contributors.
- The default path of every contribution should be to land. The discussion, review, and merge process should be designed as corrections that move the contribution into the path to land. Once there are no more corrections, (dissent) changes should land without further process.
- Enable the broadest possible set of contributors to merge patches that reach an easy consensus. Leadership should employ a governance process that facilitates and escalates contributions and becomes a stamp required for every contribution.
- Always seek a consensus, but if you reach an impasse escalate to leadership for a decision in order to move on.
Hidden cultural barriers to entry
As various Node.js repositories operate under different policies you might think that the differences would be a barrier to contributing and being involved across repos, but we’ve found the opposite to be true. It turns out that the hidden cultural barriers to entry are usually much larger than any technical barriers. As a result, many contributors start out in working groups closer to or even below their existing skill-set and overtime we see many of these contributors taking on deeper technical tasks in other WGs or even in Node.js Core.
Contributing to open source is easier for some than others. There’s a lot of fear of being yelled at for not doing something right or just not fitting in. Those emotional needs are some of the hardest things for projects to address, but by giving contributors a place to contribute with very low technical proficiency (documentation, web content markdown, etc) you can greatly reduce those concerns, and, at the very least, remove concerns related to their self-perceived technical aptitude. Once people are comfortable in one working group their fears about other WGs or even Core are significantly lower and, as a result, we see migration from localization WGs and the website to Core.
The success we’ve seen with Liberal Contribution Policies breaks apart the false narrative we see in many open source projects that there simply aren’t enough “qualified” or “proficient” developers for a project to adopt a more participatory structure. It’s not that there’s aren’t enough potential contributors, it’s that potential contributors don’t want to spend their time in projects that lack proper incentives for participation and leave in place large barriers to entry that some established committers may not fear.
Contributors share responsibility for the project, and within that set of people you’ll find a group of leaders who the contributors trust with decision making. The goal of participatory governance is to ensure that the people contributors trust with decision making are in-fact granted ownership over that decision making and also that responsibilities are distributed rather than centralized whenever possible. Across the Node.js project we have Top Level Projects (TLPs) governed by TCs (Technical Committees). Node.js Core is a Top Level Project governed by the CTC (Core Technical Committee).
As we discussed earlier this group is an escalation mechanism for contributors when consensus can’t be reached which means that most decision-making is actually shared by the contributors and never reaches the CTC. Only in the rare case that a consensus can’t be reached it will be sent to the CTC. The CTC also delegates many responsibilities to sub-groups called Working Groups. Those Working Groups have their own governance structures and set of contributors. They do not report to the CTC, and CTC members are not entitled to decision-making authority over anything they have delegated to those Working Groups. This more anarchistic approach distributes authority rather than centralizing it in a traditional hierarchy. Top Level Project TCs, like the CTC, also have some base governance rules that protect the project from undue influence.
- Consensus seeking is used for decision-making with a majority vote as a tiebreaker when consensus can’t be reached.
- No more than 25% of the TC can be affiliated with the same company.
- The TC must have representatives from at least four timezones.
Consensus seeking has been a very effective tool for the project. It encourages people to work together and reach an agreement, and it doesn’t reward stalwarts or favor inaction the way that pure consensus does. Pure consensus is like giving everyone a veto over any change, there’s little incentive for a participant to convince their peers when they don’t want something to happen. With a fallback to voting when consensus can’t be reached it means that anyone favored against a change has to convince their peers just as much as someone who does favor the change.
The results have been incredible in that we’ve never actually been forced to a vote due to lack of consensus. That is not to say that we haven’t had disagreement, but we’ve always been able to find a creative compromise. Last but not least, all decisions are made on GitHub. This transparency is fundamental to converting contributors into leaders (future TC members) because they can see the process taking place. The CTC has a weekly call so that everyone is forced to make decisions on any contentious issues so that the contributors can move forward. Only after a lengthy contributor discussion takes place on GitHub can these be escalated to the CTC. The meeting calls are also recorded and published along with detailed meeting notes and this is true of most, if not all, Working Group meetings as well.
Values > Process
Most established projects like to dictate a specific and preferred process to new projects. When we started thinking about admitting more projects into the Node.js Foundation we found that many other foundations dictate a process for all projects that enter. We couldn’t bring ourselves to do this. We’re a young project, and we are just figuring out policies that work for us this year, so nobody really felt comfortable being this prescriptive.
Instead we started thinking harder about why these policies work and what some of our assumed values are that lead us to create them. The result of that is an incubation process that seeks to mentor and ensure a process that adopts the values of participation, transparency, and efficacy rather than drilling a specific foreign process into their project.
Now we’re sharing those values and best practices with the rest of the open source world in the hopes that this can be as effective for you as it has been for us, and that we can have more thought and discussion in the open source world about how we bring people deeper into our communities.