How I Think About Technical Debt as a Contractor
by Eric Hanson, Backend Developer at Clean Systems Consulting
Technical debt means something different when you're a contractor. The time horizon is shorter, the ownership is different, and the right approach isn't always the one you'd take with your own codebase.
The Contractor's Relationship With Debt
When you work full-time on a product, technical debt is a problem you'll live with. You'll be the one who has to navigate the bad abstraction you let slide, or deal with the missing tests when the bug shows up in production six months later. The long-term cost is your problem.
When you're a contractor on a six-month engagement, the calculation is different. You might not be there when the debt matures. And the client might not care about the category of debt you care about — they might care about shipping this quarter, not what the codebase looks like in two years.
This creates a genuine tension. You have professional standards. You know what good looks like. And you're working within constraints that don't always support doing things the "right" way.
The Three Categories of Debt
I've found it useful to think about technical debt in three categories, because they require different responses.
Dangerous debt — shortcuts that introduce correctness issues, security vulnerabilities, or failure modes that will cause real harm in production. Missing input validation. Error conditions that fail silently. Authentication logic that's been hacked together under time pressure. This category doesn't get accepted regardless of the timeline or the client's preferences. The risk isn't theoretical; it's concrete and near-term.
Costly debt — structural issues that make the system harder to work with over time: poor abstractions, missing tests, an architecture that'll need to be rethought in a year. This is where the contractor's calculation gets complicated. If the client's timeline is real and the business need is legitimate, sometimes taking on costly debt is the right call — as long as it's acknowledged and documented.
Aesthetic debt — code that's inconsistent, or organized differently from how you'd do it, or uses patterns you find inelegant. This category almost never justifies the friction of raising it. The client's codebase is not a canvas for your preferences.
Making Debt Visible Is Your Job
Here's where contractors often go wrong: accepting debt silently. You take the shortcut to meet the deadline, you don't mention it, and you move on. The client has no idea what tradeoff was made.
Every debt item you accept as a contractor should be recorded. Not as a way to cover yourself — as a way to give the client useful information they couldn't otherwise have.
A short note in the code, a ticket in the backlog, a sentence in a handoff document: "This approach was chosen for speed. The tradeoff is X. If the product grows in Y direction, this will need to be revisited." This takes minutes. It changes the debt from invisible to managed.
The client might never act on it. But the next developer who touches that code, whether it's you next month or someone else in a year, has context instead of mystery.
When to Push Back
There are situations where the right response is not to accept the debt but to push back on the conditions that are creating it.
Timeline pressure is the most common source. "We need this by Friday" creates real pressure to cut corners. Sometimes the timeline is fixed for legitimate business reasons. Sometimes it's organizational habit — everything is urgent, and someone has to make the case that some things should take longer.
As a contractor, you have a particular kind of credibility here: you don't have political skin in the game. You can say "this timeline means we're taking on debt that will cost more than the time savings in about three months" without it being a self-serving argument. Clients often hear this differently from a contractor than from their own engineers.
The framing matters. "This is too fast" is a complaint. "If we do this on Friday's timeline, here's what that costs, and here's what a slightly longer timeline buys you" is useful information.
The Handoff Standard
The thing that distinguishes good contractor work from poor contractor work, in my experience, is not the code you shipped — it's the state you leave things in.
The standard I try to meet: a developer who comes after me should be able to understand what I did and why without asking me. That means:
- Comments on the non-obvious decisions
- A clear picture of what's incomplete and where the debt lives
- Documentation of the system's behavior at the point I left it
- An accurate README if there wasn't one, or an updated one if there was
This is professional courtesy. It's also good for your reputation. Clients talk to each other. "The contractor left a mess" is remembered. "The contractor left everything in good shape and documented" is remembered too.
Long-Term Thinking on Short-Term Engagements
The irony of contractor work: the shorter your engagement, the more important it is to think about what comes after you.
A full-time employee has ongoing accountability. They'll be around when the consequences arrive. A contractor is, by definition, leaving. The only accountability is reputational, and the only legacy is the state of the system you leave behind.
That's actually enough incentive to do right by it — if you care about the kind of work you're known for.
The measure of good contractor work isn't what you shipped — it's whether the team you left behind can tell the difference between your best efforts and your compromises.