Tech debt is like duct tape. It’s patchwork that gets the job done in a pinch, when you’re operating under tight timelines or budget constraints.
More formally, technical debt is the use of outdated or bulky technologies that aren’t feasible in the long term because they create bottlenecks in a system, consume more resources than necessary, and impede development efforts by adding unnecessary complexity and instilling poor programming patterns.
Only, if left unchecked, tech debt compounds over time, growing organically day by day, snowballing out of control. This is especially true when a team lacks a field-tested standard to prevent tech debt and isn’t well-aligned on shared programming patterns, best practices and architectural decisions.
Something that, if dealt with immediately, may have taken an hour to fix, might take a full week to fix a year later. Imagine sticking duct tape on duct tape on duct tape, until you reach a point where you don’t even know which strip is okay to remove and adding more just makes it worse.
Sometimes tech debt occurs as a result of trying to build an initial release quickly. But this shortsighted approach tends to leave the team scrambling to pick up and patch the pieces together for all future releases.
Other times tech debt occurs simply because managing infrastructure at scale is tremendously difficult when dealing with on-premise technology. Leveraging cloud computing, and serverless infrastructure in particular, helps companies greatly offload DevOps efforts, allows them to focus solely on maintaining and developing software, and relieves most future issues with technical debt. This is why large enterprises are moving to cloud services like AWS in droves.
This does, however, leave large enterprises with the unique challenge of retiring their old tech debt during migration. More generally, as a result of more traditional phase-based approaches to development, it’s still quite common to inherit code that’s full of tech debt.
In these scenarios, it’s important to document all the issues, prioritize the most critical for fixing, and then distribute those fixes into sprints over time. Moving forward, it’s always best to take a proactive approach to tech debt, refactoring bad code as you encounter it when developing features and minimizing costs in the process.
Breaking the cycle can be tricky though, and some tech debt may never be relieved. If the tech debt you’re encountering seems insurmountable, it’s essential to take a step back and reflect on the technology used, how the platform is built, and if the original spec can handle new additions. Sometimes tough decisions must be made and losses must be cut.
In a perfect world, tech debt would never be incurred in the first place. This often requires a greater time investment upfront to map out and design a system architecture against short and long-term requirements, but that investment pays dividends long into the future by reducing development time and improving scalability.
Because technology moves quickly, there’s always a danger of getting into tech debt, which is why taking an iterative approach to adopting new technologies is useful for mitigating risk.
Creating multiple small services instead of one large service, for instance, can greatly help with maintenance as these services can be individually improved over time and/or swapped out entirely in the future without the need for a major refactor. Keeping tech debt challenges in mind generally leans one in the direction of trying to create decoupled systems where possible.
In the end, companies always have to pay the debt that’s owed if they want to move forward at a high velocity and at scale. Refactoring code and integrating outdated technology can eat up considerable time and resources, often doubling the original build time. But leaving it longer only makes matters worse.