
Ward Cunningham coined the phrase "technical debt" in a 1992 experience report about a portfolio management system he'd worked on. His version was short: "Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite." Then the warning: "The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt."
More than thirty years later, the metaphor still works, though the debt itself has spread well beyond first-draft code. In practice, technical debt is anything that makes the next change slower or riskier than it should be. Some of it lives in the code. A lot of it lives in the process around the code, or in one person's head.
Definitions only get you so far. Most people recognize it faster when they see it, so here are ten technical debt examples that most teams will know from their own systems.
- Technical debt is any shortcut or delay that makes the next change slower or riskier than it should be.
- Most of it isn't bad code. It's postponed upgrades, missing tests, manual steps and knowledge held by one person.
- Debt costs you most where you keep making changes. Stable code with debt in it can often wait.
- Write each item down with what it costs, so the business can weigh it against new features.
1. The upgrade that keeps getting postponed
The framework, database or runtime is several versions behind. Every year the upgrade gets pushed back for something more urgent, and every year the jump gets bigger. Eventually a vendor support date forces it, at a time you didn't choose. The interest you're paying is the growing size of that jump, plus everything you can't use in the meantime.
2. The report only one person can fix
When the month-end report breaks, everyone waits for the same person. The logic lives in their head and in a query nobody else has opened. The interest is the waiting, and the risk is what happens when that person leaves. We wrote about that in the one person who understands your legacy system.
3. The manual step in every release
Every deployment includes someone running a script by hand, editing a config file on the server, or restarting services in a particular order that's written down nowhere. Releases happen less often because they're painful, and changes pile up into bigger, riskier batches.
4. Tests nobody trusts
Either there are no automated tests, or there are tests that fail randomly and get ignored. Every change then needs days of manual checking, or it goes out with crossed fingers. Teams in this position stop making small improvements, because even small changes feel dangerous.
5. The same rule in three places
A business rule, such as how a discount is calculated or when an account counts as overdue, is coded in three different places. Someone updates one of them. Now two systems disagree, and finance spends a week working out why the numbers don't match.
6. The integration that's really a person
Data moves between two systems because someone exports a file from one, tidies it in a spreadsheet and imports it into the other. It works until that person is on holiday, or makes one copy-paste mistake that nobody notices for a month.
7. The hard-coded value
A tax rate, a fee, a server address or a customer ID is written directly into the code. Changing it needs a developer and a release, so a five-minute business change becomes a two-week ticket.
8. The temporary workaround from years ago
Someone fixed an urgent problem with a quick patch and a comment saying it would be cleaned up later. It never was. Now there's code nobody understands, and nobody dares remove it, because nobody remembers what it was protecting against.
9. The database everything writes to
Several applications read and write the same tables directly. Nobody can change a column without risking a break somewhere else, and nobody has a full list of what "somewhere else" includes. Every schema change becomes an investigation, which is why knowing what depends on a system matters so much before anyone changes it.
10. Features nobody uses but everyone maintains
Old screens, reports and options that nobody has opened in years still get patched, tested and carried through every upgrade. It's pure interest: work spent on code that delivers nothing.
Not all debt is a mistake
Cunningham's original point was that a little debt is fine, even useful, if you pay it back. Shipping something simple to learn faster is a reasonable trade. Martin Fowler made the same distinction with his technical debt quadrant, which separates debt taken on deliberately from debt taken on by accident, and prudent debt from reckless debt.
The debt that hurts is the debt nobody recorded. If nobody wrote it down, nobody can weigh it against new features, and it only becomes visible when it causes an incident.
Which debt to pay down first
You can't pay it all down, and you shouldn't try. Three questions sort it quickly.
How often do you change this code? Debt in code you change every week costs you every week. Debt in code nobody has touched in five years costs almost nothing until you need to touch it. Version control history will tell you where the changes cluster.
Is there a date attached? A runtime with a support end date, or a person with a retirement date, turns slow-moving debt into a deadline.
Is it a risk, or just friction? Security gaps and single points of failure go to the front of the queue, even in code that rarely changes.
Then write each item down in terms the business can weigh, such as "every release takes an extra day because of this," and put it in the same backlog as the features.
Where the 30-day assessment fits
Most teams know where some of their debt is. Few have the whole picture, because the people who'd find it are busy working around it.
The 30-day assessment finds and sizes it for you. It's fixed in scope, at a price agreed before we start. Over 30 days we go through your codebase and architecture, map how the system fits together, find the hidden architectural debt, and flag the security and compliance gaps. The report says in plain language what is broken and what it would take to fix it. Your team can pay the debt down themselves, or we can do the work as a separate project with its own scope and price.