Many organizations have a lot of technical debt while migrating to the cloud. But what is technical debt, and how can DevOps tackle it? In this article, we will discuss ways of using DevOps to minimize the burden of technical debt.
What is technical debt?
Technical debt is the accumulation of sub-optimal technical decisions made throughout the application lifecycle. It can make transformations increasingly difficult and bring IT initiatives to a standstill.
For example, a poor state of an application may make it challenging to implement a horizontal scaling strategy. You need to rewrite the state management part of the codes before implementing what you want to do (scale the application horizontally to cope with the increasing flux). The "Do what needs to be done first, then do what you want to do" is technical debt.
It is worth pointing out that technical debt can occur not only in development but also in operations. For example: running outdated operating systems is no longer supported (Windows Server 2008 or Ubuntu 11.04). Not keeping your servers up to date and current with patches can leave you vulnerable to cyber-attacks and ransomware. These all are technical debts.
Why does technical debt exist?
Martin Fowler's Technical Debt quadrant states that technical debt is unintentional sometimes. What you didn't know before, you do now, and then you can fix it.
Technical debt, cautiously and deliberately, is at the heart of Eric Ries' 'build-measure-learning' cycle. Sometimes the only way to know if you have a working product is to release it and put it in the hands of your customers. It may mean that you 'cut corners' and can incur technical debt.
How does DevOps tackle the challenge of technical debt？
1. Creating a DevOps product team
One of the central tenets of DevOps is to create small, multi-disciplinary teams (i.e. Dev + Ops) who own the entire lifecycle of a product or service from 'start to finish. As these teams (including their product managers) experience the impact of technical debt daily, they are highly motivated to pay it off to make life easier.
Simple things can assist the team in tackling technical challenges.
The first step is to assess and track your product's technical debt level.
You can do this by marking work items (e.g. in Jira, Azure DevOps, or Github) as "TechDebt". Next, you need to streamline a portion of each Sprint to handle the TechDebt items. We recommend 20% as a good starting point.
Then find out the current level of technical debt. If there is too much technical debt (an unacceptable level), prioritize more debt resolution work in the following schedule. Continue working until your team is satisfied that technical debt does not impede your product goals.
Finally, try to avoid creating additional technical burdens in new product development. Employ the technical debt quadrant to evaluate design options and minimize new debt.
2. Paying off technical debt with DevOps automation
Inherent in the DevOps approach is the extensive use of automation. Many of the platforms discussed earlier can be built and managed using automation. Furthermore, the service platforms provided are often automation toolchains for product teams.
But how can DevOps automation contribute to paying off technical debt?
Let's manage the environment and consider how infrastructure-as-code and configuration-as-code can contribute to paying off technical debt while avoiding future debt.
Unstable environments are a common form of technical debt experienced by almost everyone. When your application works in Dev but not in Pre-Production, or worse, not in Production, the root cause is usually inconsistency. This can be found in the operating system configuration, application dependencies, the many configuration settings that the application relies on or the communication between the different services that make up the application. The cost of the time you spend solving such problems is technical debt.
Infrastructure-as-code and Configuration-as-code allow you to express what you want your environment to be. Then, with the power of tools like Terraform and Puppet, you can declare that you will "do this" consistently across every instance of that environment. Containerisation takes this to a new level.
"As-code" automation also has another benefit. Saving DevOps automation as code in a repository like GitHub, rather than describing configuration settings in lengthy Word documents or Visio diagrams, makes iterating and improving much simpler and more accessible. People can quickly discover code through search, submit suggested changes via pulled requests or even derived codes, modifying and extending them to meet their needs. This ability to iterate means that automated code is less likely to become 'obsolete', thus avoiding another form of technical debt.
3. Simplifying application deployment and management with containers
How can they assist you in paying off your technical debt?
In short, containers allow you to encompass your application, configuration, and operating system dependencies in a lightweight bundle that is much easier to deploy and configure.
As the environment management automation example discussed earlier, the portability of containers simplifies everything. Container orchestration tools such as Kubernetes make even further strides to automate the container lifecycle in production, allowing DevOps teams to focus on higher-value tasks (such as re-architecting applications to reduce technical debt).
Organizations building new cloud-native applications often employ containers to increase flexibility and scalability at a lower total cost of ownership (TCO). Each microservice is small, has a clear boundary context, and is managed by a long-standing team. As a result, technical debt is easier to detect and fix. It' s a win-win solution for everyone.
4. Building an API-centric model with DevOps
The microservices model discussed above is a way to implement an API-centric application strategy. Jeff Bezos challenged his team to use APIs to communicate between systems.
The organization may be less strict. Nevertheless, encouraging teams to build APIs using well-defined versioning interfaces is an excellent way to lessen the technical burden. Usually, technical debt is caused by different systems accessing services and data in ways other teams cannot expect. For example, Team A reads data directly from a desk created and managed by Team B. If Team B changes the architecture of that desk to meet their needs, they may inadvertently break Team A's application due to this hidden dependency.
The API makes these interfaces more visible and less fragile. Each product needs to follow the published API with a clear roadmap for the future and, ideally, should support " semantic version control ". If they need to make a "major change" to the API specification at some later stage, they can release a new major version of the API and support the "old" API for a predefined period of support. All this together reduces vulnerability and technical debt.
DevOps models and practices, such as using CI/CD code pipelines to build, test, package and deploy applications, allow teams to move faster with less risk and technical debt.
The code pipeline also provides end-to-end traceability of application codes: from use cases to code commits to released packages. This makes it easier to manage technical debt. If you have tracked and tagged technical debt previously discussed, you can know its impact on live systems and customers. This can be useful in deriving clear, customer-driven priorities on focusing technical debt repayment efforts.