The Most Dangerous Phrase in Engineering Is “We’ll Clean It Up Later”
Most technical debt doesn’t begin as a technical problem. It begins as a reasonable shortcut taken under pressure. Over time, deferred testing, manual processes, and neglected architecture turn yesterday’s velocity into tomorrow’s constraint.
I've worked in startups, scale-ups, and large enterprises, and one thing I've learned is that technical debt rarely starts as a technical problem.
The technology changes. The company names change. The org charts change. Yet after more than twenty years in software, I've watched the same pattern emerge again and again. Teams make a reasonable decision under pressure, the immediate problem gets solved, and everyone agrees they'll come back later to clean things up.
Technical debt is what we call the result.
Most discussions about technical debt focus on code. Engineers talk about architecture, complexity, code smells, outdated frameworks, and aging dependencies. Those things certainly matter, but I've become increasingly convinced that they are usually symptoms rather than root causes. When I look back at the most expensive technical debt I've encountered, very little of it originated as a technology problem.
Most of it started as a perfectly reasonable decision made under pressure.
A customer needed a feature. A release date was approaching. A production issue demanded immediate attention. The team understood that the solution wasn't ideal, but it solved the problem in front of them. Somebody acknowledged that the shortcut would need to be revisited eventually, everybody agreed, and the work moved forward.
That final step is where the trouble starts.
"We'll clean it up later" sounds responsible. It acknowledges the compromise without forcing anyone to deal with it immediately. It creates the comforting illusion that the debt has already been accounted for simply because it has been acknowledged. In reality, most organizations are remarkably good at remembering the benefits of shortcuts and remarkably bad at tracking their costs.
The feature ships. The outage ends. The customer signs the contract. The roadmap moves forward. The immediate problem disappears, which means the cleanup immediately starts competing with a hundred other priorities. Weeks become months. Teams change. Context fades. Before long, nobody remembers enough about the original decision to confidently revisit it.
The debt remains.
I've seen this happen most visibly with automated testing, which is why I think about it differently than most engineers do.
Almost every engineering team claims to value tests. Almost every engineering team under pressure is tempted to postpone them. The logic is understandable. The feature needs to work before it can be tested. The customer doesn't pay for tests. The business wants outcomes, not coverage reports. Teams convince themselves they're borrowing a little time from the future and that they'll repay the loan once the urgency subsides.
The problem is that automated testing does much more than catch bugs.
A system that is difficult to test is often trying to tell you something important. Hidden dependencies, excessive coupling, unclear boundaries, and components that have accumulated too many responsibilities tend to reveal themselves the moment someone attempts to write meaningful tests around them. Engineers who postpone testing are often postponing the feedback that would have exposed those design problems while they were still relatively cheap to fix.
By the time the team finally returns to add the tests, the architecture has usually solidified around the original decisions. What could have been a small correction early in the lifecycle becomes a migration project. Product managers wonder why the work is taking so long. Engineers become reluctant to touch the code because they can no longer predict the consequences of changing it. The organization begins spending more energy managing risk than creating value.
Years ago I read about a manufacturing executive who took over an aluminum company. Investors expected him to focus on production output, operating costs, and margins. Instead, he focused relentlessly on worker safety. At first glance, it seemed like an odd priority.
What those investors eventually learned was that safety wasn't separate from operational performance. Unsafe processes created injuries. Injuries caused downtime. Downtime created inefficiency. Improving safety required improving communication, training, equipment maintenance, and accountability across the business. Safety mattered because it sat at the center of everything else.
Automated testing works the same way. Organizations that maintain strong testing cultures tend to have cleaner interfaces, safer deployments, and more confidence when the system needs to change. Architectural boundaries stay clearer because those boundaries are exercised continuously. The tests catch bugs, but the deeper value is what the discipline of writing them forces the system — and the team — to become.
One reason technical debt remains so difficult to address is that it disguises itself as productivity. Teams that skip testing often appear faster than teams that write them. The benefits arrive immediately. The costs arrive later, often after the people who made the original decision have moved on to other projects, other teams, or other companies.
From the perspective of a quarterly roadmap, the shortcut looks like a success. From the perspective of a multi-year engineering organization, it may become a constraint that slows everything built on top of it.
The goal isn't to eliminate shortcuts. Every meaningful engineering effort involves tradeoffs. Startups should move quickly. Deadlines matter. Business realities matter. The goal is to stop pretending shortcuts are free.
Every shortcut is a loan against the future. Sometimes that loan is absolutely worth taking. The mistake is believing the loan disappears simply because nobody is currently collecting payments.
The most dangerous phrase in engineering isn't dangerous because it encourages compromise. Engineering is compromise. The danger is in the assumption embedded inside it. Every time we say we'll clean it up later, we're making a bet that future us will have more time, more context, and more organizational support than we do today.
Code is just where the consequences become visible. The debt usually started somewhere else entirely — and that's what I want to explore in the next piece.