On Rolling out Backwards-Compatible Software Upgrades
Last updated:WIP Alert This is a work in progress. Current information is correct but more content may be added in the future.
The situation
You have some piece of software that is relied on by several teams or services. It has outgrown itself and now it's messy and hard to maintain.1
You want to throughly restructure it to support further growth and fix bad design that's creeped in due to previous changes.
This will likely cause breaking changes (how people use it or how it affects the world).
At the same time, you must keep supporting users that rely on the current version, without disruption.
Problems
Other teams have their own objectives and they will probably not prioritize changing their services to adapt to the new, upgraded version
- In other words, even if you create a perfect new version of the software and the rely on client systems to be updated by other teams, you will never succeed.
- Other teams have no incentive to make an effort to switch to another version of a system they use if the current one suits them (even though it's messy behind the scenes).
You cannot possibly risk migrating it all at once so you need a piecemeal approach.
Strategies
Use Semantic versioning (SEMVER)
This may be obvious to some, but the obvious needs to be stated as well.
Using semantic versioning helps calibrate expectations; also, many dependency managers (pip/virtualenv/conda, npm, etc) rely on these to update software.
Be aware of Hyrum's Law
TODO
1: It's very important not to frame large restructuring or refactoring efforts as somehow fixing a faulty system. All systems that have been successful eventually need to be rewritten to suit changing requirements. The fact that it needs to be restructured/refactored is therefore testament to its success.