A job that runs at 03:40 every morning, a commit message that says "timing fix", and the person who picked the time three organizations away by now. This is about what a contractor actually is, which is an option to stop rather than a cheaper engineer, and about the cost that sits on neither side of the rate argument. The code stays and the working model of it goes home, by design and nobody's fault.
26 October 2021·8 min read·leadership
A scheduled job ran at 03:40 every morning. Not on the hour, not on the half hour, at 03:40, and it had done so for years without incident. When I finally went looking, the commit that set it said "timing fix" and nothing else, and the person who wrote it had finished their engagement long before and was three organizations away by then. So we left it. Moving it would have taken ten minutes and an unknown amount of courage.
The conversation about contractors almost never gets to that. It gets stuck on the rate, and the arithmetic on both sides of the rate argument is wrong. The contractor's number is compared against a salary rather than against a loaded cost, which quietly omits everything an employee comes with: payroll taxes, benefits, equipment, recruiting, the manager's attention, and the long tail of being committed to somebody whether or not the work still exists.
The contractor's number is understated too, just in different places. It does not include the weeks of ramp before the first useful commit, or the hours of permanent engineers' time spent explaining, reviewing and answering, or the handover, or the second ramp when the next engagement starts from zero. So the argument is conducted between two bad numbers, and whichever side you already favored, you can win it.
Here is the framing I have come to instead. A contractor is not a cheaper engineer. A contractor is a different financial instrument: you are converting a fixed cost into a variable one and paying a premium for the option to stop. Understood that way the decision is frequently correct, and the real cost moves off the quote entirely, because the code stays and the context leaves, and neither party is doing anything wrong when that happens.
The premium is not a markup on the same thing. It is the price of a decision you have deliberately not made yet.
You are buying an option to stop, priced like one. A permanent hire is a commitment with no clean end. Reversing it is slow, expensive and unpleasant for everybody, and you make it before knowing whether the work lasts. An engagement ends on a date that is written down at the start. That asymmetry is worth real money, and the extra you pay per hour is what it costs to keep the exit cheap.
Bounded work is the clean case. A migration with an end. A certification exercise. A platform move that happens once and will not happen again for years. If the work genuinely finishes, the permanent version of it means finding something else for that person to do afterward, which is a real cost that never appears in the comparison because it arrives disguised as a headcount you already had.
You need this skill once, from somebody who has done it twelve times. Depth in a system is built in-house and cannot be bought. Breadth across twenty instances of the same problem is the opposite: it is built by moving, and no amount of tenure produces it. Somebody who has run the same migration a dozen times knows the four things that go wrong, and knowing them in advance is the entire value of the engagement.
And the arrangement is a legal construct, with rules that move. On 6 April 2021 the UK's off-payroll working rules extended to medium and large private sector clients, moving the job of deciding whether an engagement counts as employment for tax onto the client. That is one jurisdiction's version of worker classification and other countries answer it differently, which is the point: what you think you bought is partly defined by somebody else's rules.
Peter Naur described this in 1985, in an essay called Programming as Theory Building, and I have not read a better account of it since. His argument is that the valuable thing a programmer builds is not the text but a theory: a working model of how the code maps onto the world it serves and why it is arranged as it is. The text is the residue. The theory lives in people, and most of it is not the kind of thing writing captures.
Naur's uncomfortable conclusion follows immediately. A program whose theory has died can still be run and can still be modified, but only by guesswork, and the modifications degrade it, because the people making them are pattern-matching on the text rather than reasoning from the model. Anyone who has inherited a system and made a change that was technically correct and quietly wrong has met this personally.
The theory does not only die at the end, either; ordinarily it leaks first. An employee's model spreads into the people around them over years, through pairing and argument and being overheard in the wrong meeting, so when they leave some fraction of it has already been copied. An engagement compresses those years into months and spends most of the months delivering, which leaves far fewer of the hours in which leaking happens. The difference is exposure time, not loyalty.
The half that never survives is the negative record: the approaches that were tried and rejected. Nobody documents what they did not build. So the next person arrives, sees an obvious improvement, spends three weeks on it, and rediscovers the reason it was abandoned, which was known and cheap and is now expensive. That is the same three weeks, paid again, and it will be paid a third time later.
It is a missing feedback loop, not bad faith. The thing that teaches an engineer to write maintainable code is having maintained their own, repeatedly, and hating themselves for a decision made two years earlier. Remove that loop and the lesson has nothing to attach to. Character does not substitute for it. Some of the most conscientious people I have worked with wrote code that was hard to keep, because nothing ever told them so.
You get code that works and resists change. The deliverable passes its tests and does what the specification said. It is also fitted tightly to assumptions that were true in that quarter and were never written anywhere. That is not bad code. It is code shaped by a deadline it met, which is what it was asked to be, and the bill for the shape arrives when somebody first needs it to be different.
The trap is not the arrangement. It is the arrangement quietly outliving the reason anyone chose it.
It starts correctly. Bounded work, a real end date, a skill nobody has. Then the work runs long, so the engagement extends. Then a second piece of work is adjacent and it would be silly to bring in someone new for it, so it extends again. Two years later there are people who know the system better than most of the permanent staff and whose relationship with it terminates on ninety days' notice.
What you end up holding is staff augmentation nobody chose: de facto permanent people, with worse continuity, no career investment in either direction, and a standing premium on every hour. Worst of all, the premium is buying an option you have already decided never to exercise. Paying for the freedom to stop, while having no intention of stopping, is the one version of this arrangement that is simply a loss.
The fix is a calendar entry rather than a policy. At each renewal, somebody has to answer out loud whether the work is still bounded, and if the honest answer is no, the choice is to hire or to keep paying knowingly. Either is defensible. What is not defensible is arriving at year three having never made the decision, because each individual renewal was too small to require one.
Knowledge moves by working alongside somebody over time, in small unremarkable exchanges that nobody schedules: a question asked over a shoulder, a review comment that explains rather than corrects, being in the room during an incident. If that did not happen during the engagement, it does not happen in the final week. The handover document is not the transfer. It is the receipt.
I do not think they are worthless, and I have written and been glad of several. A document carries facts well: where things are, how to run it, which credentials matter, what the deploy sequence is. Write those down and keep them current. Just be precise about what you have captured, because facts are the cheap half, and the theory is not in there.
Pair from day one, not at handover. Attach a permanent engineer to the work from the first week, not the last. It looks like it halves your capacity and to some extent it does, and it is still the only thing I have seen reliably work, because it converts the transfer from an event at the end into a byproduct of the work itself.
Keep the decisions in-house even when the implementation is not. The build can be bought. The reasoning behind the shape of it should not leave the building. Write the decision record yourself, in your own words, including the options rejected and why, and have the contractor argue with your draft. What you own afterward is then the part that stays useful when the code is replaced.
Ask for the negative record weekly. A short note each week on what was tried and did not work costs minutes and is the only form in which abandoned approaches ever survive. Asked at the end it produces nothing, because by then it is a memory exercise. Asked on Fridays it produces the single most useful document anybody leaves behind.
Good contractors are frequently the strongest engineer in the room on the thing they were hired for, and it is not close. Somebody who has done this particular migration across many organizations carries a pattern library that nobody inside can develop, because developing it requires leaving. Treating that person as a resource to be scheduled, rather than as the expert you deliberately went and found, wastes the main thing you bought.
The second-class treatment is worse than unkind, it is self-defeating. Excluded from planning, told what to build rather than why, left off the invitation, handed a specification instead of a problem. People notice this within a fortnight and adjust to it, and the work settles at precisely the level the treatment implies. It also guarantees the knowledge will not transfer, because transfer happens in the conversations they were not invited to.
And permanent staff leave, sometimes with two weeks' notice, which is shorter than most engagements and considerably less predictable. A badge is not continuity. Continuity is a property of how a team works, not of anyone's employment status, and a team that pairs, reviews and writes decisions down survives a departure of either kind, while a team that does none of those things loses the theory when its most senior employee takes a better offer.
Which shrinks what I have been arguing, and it should. "Just hire permanent" is often not on the table at all: the role does not exist, the skill is needed for four months, the hire takes longer than the deadline. In those cases a contractor is not the compromise, they are the right answer, and the permanent hire would have been the mistake. My complaint is narrower than the piece may have sounded: it is against pretending the arrangement is only about rate.
I should concede that the cost I keep pointing at is not always worth avoiding. Plenty of systems do not deserve an heir. A tool that runs for one campaign, a component being retired next year, an integration deliberately bought so that nobody internal ever has to hold it: for those, losing the context is the arrangement working, not failing. The mistake is not letting context leave. It is letting it leave from the places you cannot afford to lose it, without noticing that is what you decided.
What stays with me is the crontab. Somebody knew why that job ran at 03:40. It was a small, correct, well-reasoned piece of knowledge that took a second to hold and would have taken a sentence to record, and the engagement ended, and the code kept running, and the reason went home. Every system I have inherited has a version of that line in it, and the honest question is never who wrote it. It is who was standing next to them at the time.