🏗️ Managing Technical Debt
Technical debt is unavoidable — the question is whether it is intentional or accidental. Intentional debt is a deliberate trade-off: we ship a simpler solution now and plan to revisit it when we have more information or capacity. Accidental debt is the result of ignorance, time pressure, or poor decisions made without awareness. My job as a technical leader is to make debt visible, distinguish between the two types, and ensure the team is paying it down steadily rather than letting it compound.
The first step is inventory. I work with teams to catalog debt in a shared backlog — not buried in code comments or tribal knowledge. Each item is described in terms of its business impact: what will happen if we leave this unaddressed? Some debt is cosmetic and can wait; some is load-bearing and will cause production failures or block a key feature. Prioritizing by business risk rather than engineering preference makes the conversation with product stakeholders much easier.
I advocate for a "20% rule" on engineering capacity — reserving a meaningful slice of every sprint for debt reduction, refactoring, and tooling improvements. This keeps debt manageable without requiring big-bang rewrites that stall product work. When a refactor is needed, I prefer the strangler fig pattern: incrementally replacing the old system from the edges inward, so the new and old coexist during the transition and rollback is always possible.
Preventing new debt is as important as paying down existing debt. Strong code review standards, architecture decision records (ADRs), and explicit "definition of done" criteria that include test coverage and documentation are the best defenses. Teams that talk openly about trade-offs and document why shortcuts were taken accumulate far less accidental debt. The goal is a codebase that moves faster over time, not slower.