Within Flow we run a bi-weekly development process which we call Dependence Day. It is part of our tech culture to keep all of our applications up to date with their dependencies, both internal and external.
We do this to avoid issues many of us have previously experienced in maintaining large and complex codebases, including:
The broad goal of Dependence Day is to make sure we can make changes throughout our technology stack, deploy quickly and safely where and when needed. This also means that if we make breaking changes, we detect them quickly as we have to upgrade, and so can change our mind about the breaking change.
We have created an open source service to track, in real time, our scala projects and their declared dependencies. This becomes the source of information for what we need to upgrade - and is used in our tooling to drive the upgrade process.
On a regular basis (approximately bi-weekly), a developer is assigned to run a single script across our entire codebase. The script automatically upgrades libraries and our API Builder models. Changes are automatically committed, pushed and Pull Requests created. Once all builds are “green”, code is merged to the main branch which triggers a direct deployment to production.
Due to the regular cadence of running our Dependence Day process, breaking changes are likely to be small and require minimal engineering effort to fix. Internal breaking changes are also likely to be easy to fix as they are still within the recent context of the developer who introduced the code.
Our Dependence Day process turns a major, unpredictable, all-hands hassle into a moderate, predictable one that a single engineer can complete.
A recent example where this has yielded huge benefits is the Log4Shell security vulnerability. We were able to easily identify and upgrade our services and then redeploy the entire fleet within hours of the public notification.