Passive Change Communication with the Node Stability Index

This is part 4 of many in my “Open-source as a project model for internal work” series and the third part of “Empathetic Infrastructure Code Management”.

Introducing new functionality to your infrastructure is tricky. On the one hand, you’re excited to get your hard work out there. On the other hand, you know that it’s never been tested in the real world, and there are bound to be bugs that you couldn’t have planned for.

How do you balance the need to continually deliver new features with the fact that consumers are expecting them to be fully tested and validated?

You don’t.

You can’t balance that act. Continuous delivery of new features requires accepting that you don’t have all the time in the world to test. Besides, it’s difficult to predict what features are going to be heavily used, and which ones won’t ever catch on. Better to release early and validate usefulness before investing a lot of time in development.

So you focus on delivering functionality and fixing it as you go. That’s why you set up a “push” system of releases and why you semantically version your code.

Those systems help you deal with the inevitable changes that new components require. Yet they don’t help your consumer accept that inevitable change, especially if they were expecting something solid (it is infrastructure code after all).

The issue lies in differing assumptions. You have the assumption that new components aren’t stable and require work. Your consumer however has the assumption that infrastructure code has already gone through rigor. How can you clarify that while most of the code has been fully developed, some of it hasn’t?

Looking to the open-source world, Node.js has tried to address this situation. They realized that they needed a system for people to quickly understand where a component is in its lifecycle. So they introduced the Node Stability Index, and I really think it’s a nifty idea.

The basic concept is this: Assign every component a unique number based on its stability. Update that number regularly based on usage and maturity.

0 - Deprecated
1 - Experimental
2 - Unstable
3 - Stable
4 - API Frozen
5 - Locked

Generally, components should start as experimental and then move towards stable as they’re polished. Unless your migrating an already existing component, there’s little reason to aim for ‘unstable’ or ‘stable’ right away.

Give yourself a few months in ‘experimental’ before upgrading to ‘unstable’ (or downgrading to ‘deprecated’ if it turned out to be a bad idea, which is okay). This times allows you the chance to follow the Rule of Three, which is important to follow with brand new code.

After about three separate uses, you can feel pretty confident moving the component to ‘unstable’, where it will sit for a while maturing and being use in real-world applications.

The main benefit of this index is that it allows you the ability to introduce new components with a disclaimer. Now users know what to expect out of code over time. A project that’s in a rush to get something out the door probably doesn’t want to use an ‘experimental’ or ‘unstable’ component, as they want something they know won’t change under their feet.

There’s some worry that this means new components will never be used, but there are always projects interested in trying out the latest and greatest. Going down this route allows them to knowingly plan for the unavoidable regression or backwards incompatibility.

So where to store this index information? You best bet is with the component documentation (preferably in a file in the same directory as the source code itself). This increases the likelihood of people finding it, and will help remind you to update it.

And it’s important you update it regularly, otherwise it’s meaningless and not worth it. Set a reminder to go through once a month and review all your components. It doesn’t take long and won’t need to be done all that often. Just enough to stay relevant.

Remember, the more you communicate, they happier everyone’s lives will be. Be open and honest about the current lifecycle of a piece of code and you’ll spend less time putting out fires. Be patient with functionality and let it grow up in its own time.

Plus, it’s a really satisfying experience to move something from a 1 to a 2.

Interested in more? Subscribe to the newsletter to receive update when a new part in this series is published and for other related information.