The secret to maintaining applications and avoiding or at least delaying legacy status lies in how organizations and teams manage technical debt Credit: Getty Images A big challenge for any development organization managing technical debt, the pile of work created from past decisions in software development efforts. Addressing technical debt often gets short shrift, because doing so rarely addresses an urgent business need and, especially for nonurgent cases, the ROI is unclear and thus perceived as deferrable. It’s a classic issue for anything involving maintenance, whether code or houses. But there are ways to measure and manage technical debt that will help you keep control of that technical debt. How do the applications that you are developing today evolve into tomorrow’s legacy applications? You and the development team are sprinting and releasing application improvements on a regular release schedule, so it might be hard to imagine these applications dissolving to legacy status in the future. You might also be wondering what you can do today as you are developing the application to reduce the risk of it becoming a legacy application. Applications don’t become legacy overnight, and they become that way because of two primary factors: As the application gets older, an organization may assign fewer people to maintain it , instead shifting people to more strategic projects. The amount of time the team dedicates to address technical improvements to the application may get smaller over time, given then focus on new activities. Technical debt defined A backlog of these technical improvements is called technical debt. Technical debt is something development teams have to do to maintain the application’s architecture, underlying platforms, and code. Examples of technical debt include: Small things like a to-do around a piece of code that should be refactored when there is more time to implement a stronger solution. The maintenance left behind after implementing a complex feature. The team may have estimated the feature with a high number of story points, but the product owner still prioritized its development. It was then developed with the best of intentions, but in hindsight, there are likely more efficient and stronger implementations. This creates another source of technical debt. A module of code that was developed for a simple use case, but over time its refactoring means the code is used for a wider range of use cases. Sometimes, code is released without the proper “scaffolding,” the things that make the code strong in a production environment. Scaffolding includes application logging, error checking, exception handling, documentation, and other artifacts. Sometimes, a code module may be better managed as a standalone microservice. This type of transition may be considered by some as an architecture upgrade, but I still label it as technical debt because it is a technology-driven improvement. Sometimes, a team deploys new code using a new version of a library or service and leaves the upgrading of older code to a later time. This delay creates technical debt. Upgrading and patching platforms, third-party services, development tools, and connections to new API versions are also forms of technical debt. Measuring this debt demonstrates how much work the development team believes is needed to best support the application. Applications that have large and increasing technical debt are strong indicators that they are marching toward legacy status. The secret to maintaining applications and avoiding or at least delaying legacy status lies in how organizations and teams manage technical debt. With all these sources of technical debt, how do technical organizations of different sizes manage these issues? One of the toughest issues CIOs face is in managing legacy system and modernizing technologies, so we have a vested interest in managing technical debt. Every Thursday at 2pm ET, I participate in a Twitter chat under the hashtag #CIOChat. I asked that group about their technical-debt strategies and included some of their thoughts on how best to measure and manage technical debt in the five best practices that follow. 1. Managing technical debt starts by measuring it You can’t manage a growing problem without some way of capturing the details and managing it. As Ed Featherston, vice president and principal architect at Cloud Technology Partners, says: Everything is a trade-off. Technical debt is a direct result of that. Decisions are made for expediency that leave a debt that must be repaid. One of the best ways I have seen this dealt with is having a specific tech-debt backlog separate from the product one. This gives visibility/transparency on the accumulated debt, and each spring should include product and tech-debt stories. Itemizing technical debt in the backlog is an important discipline for agile teams. It can be done in sprint as technical debt is recognized, and it can be captured at sprint retrospectives. Featherston and I differ here: I prefer capturing both product enhancements and technical debt in the same backlog but have the technical debt user stories and tasks tagged with a label or under one or more epics. But either approach works as long as the team and product owner have visibility on what technical debt is being added and addressed in every sprint. 2. Use release planning strategies to manage technical debt Most development organizations have an approach to managing application releases where decisions are made on the target scope and timing of a release. Even teams practicing more-continuous release cycles conduct meetings to review short- and longer-term priorities. It’s during these sessions that architects and developers can voice what functionality priorities are complex and may drive new forms of technical debt. In other words, says Wayne Sadin, CDO & CTO at Affinitas Life: Stop adding to technical debt by ensuring project budgets/plans explicitly address ongoing maintenance costs and include retirement (dates/costs/processes) for systems being replaced. The first step in filling in a hole: stop digging! Sadin is alluding to several strong management principles at planning sessions: Discuss complex features at the time of planning and look for more simplified solutions that are easier to implement and introduce less technical debt. Ensure that a percent of the team’s priorities is applied to addressing technical debt. My rule of thumb is that 30 percent of a release’s velocity should be applied to addressing debt and release planning sessions are a good place to discuss and debate priorities. While we all enjoy building new applications and working on innovation, development organizations also need to focus on retiring old platforms, applications, libraries, and code modules. This also can be factored into release plans. Last, and possibly most important, is how the technology organization manages the selection and adoption of new technologies including development platforms and libraries. If you’re selecting a technology because it’s the “next best thing” and that “next best thing” overlaps with technologies already being used, you are creating new technical debt! 3. Devops CI/CD makes it easier to address technical debt One of the key devops practices is in implementing a continuous integration, continuous testing, and continuous delivery pipeline or CI/CD pipeline. This automation takes code checked into a version-control system, packages the application, delivers the code to development or testing environments, and runs though a series of regression tests. With this automation, teams have a lot more confidence in making small, incremental changes to the code base because deployments are scripted, and regression tests identify application issues. Contrast that to legacy applications that don’t have this automation or testing in place. Development teams grow a fear in making changes to these applications because they don’t know what will break and whether deployments can be performed reliably. This fear slows down teams in addressing technical debt and accelerates applications to legacy status. 4. Planning release cycles to address patching and upgrades Smaller technical debt items such as fixing and refactoring code can be done in the scope of a release. But when it comes to larger upgrades, a dedicated “systems upgrade” release to perform and test the upgrades is often needed. System upgrades are best performed without introducing new functionality and capabilities so that the team can validate the upgrade against established tests and known behaviors. Disciplined organizations perform cyclical planning to schedule these upgrade periods when it’s least impactful to business and user needs. As Theresa Rowe, CIO of Oakland University, suggests: We manage technical debt by careful cyclical planning for existing technology investment; investment needs preservation or planned forklifts that match strategic initiatives. For example, if your application runs on Java with a MySQL back end, the development team may look to schedule one major upgrade per year to account for the major release cycles of these platforms. It then should look for periods of relatively low usage to schedule these upgrades. 5. Communicating the state of legacy applications and technical debt It is important to recognize that the state of application maintenance is invisible to most business leaders. They sense a legacy application only when it has poor reliability or when needed functionality upgrades take too long or are too expensive to implement. In other words, they can sense when an application achieves legacy status, but they have poor understanding and visibility on measuring and managing the technical debt that leads to it. It’s a collective responsibility of the technology organization to address this gap. First, by measuring it. Second, by proactively prioritizing and addressing it. Third, by creating reports or communication tools that provide visibility into it. Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos