The First Hack Has a Cost. The Second One Is Expensive.

Early in my career I was scoping a client integration against a delivery date that had already been agreed before anyone asked whether it was realistic. Somewhere in the codebase I found a piece of configuration that someone else had bent out of shape to solve a similar problem once before. It wasn't the right way to do it. It was, however, fast. I copied the pattern, hit the date and moved on, genuinely believing that hitting the date was the whole job.
A year later I found out what it had actually cost. Other work had grown up around that configuration in the meantime, iteratively, the way real systems do. Unwinding it meant touching everything that had since come to depend on it being there. What had looked like a shortcut had quietly become the shape of the system.
Why the second time is the dangerous one
There's a name for the mechanism that makes this happen, and it comes from a much higher-stakes place than software. Sociologist Diane Vaughan coined while studying the Challenger disaster, describing how engineers at NASA kept flying the shuttle despite known O-ring erosion because each previous flight had "worked". Every launch that didn't fail made the next launch under the same conditions look a little more acceptable, until the accumulated gap between the original safety margin and actual practice caught up with the vehicle. Seventeen years later, the Columbia Accident Investigation Board found the same organisational pattern behind that disaster too.
The mechanism isn't really about the first deviation. A single exception is legible as an exception. Everyone who sees it, including the person who wrote it, knows it's a one-off born of a specific set of pressures. The second occurrence is where the character of the thing changes, because now there are two data points instead of one, and two data points look like a pattern rather than an accident. Someone doing similar work later finds the shortcut in two places and reasonably, if wrongly, concludes that this is simply how the system works here.
Software engineering has its own version of this instinct, framed the opposite way round. Martin Fowler's , attributed to Don Roberts, holds that copying something once is fine and copying it a second time earns you a wince but no action. It's only the third occurrence that justifies refactoring. As a rule for managing duplicate code, that's sound. As a rule for managing precedent, it's exactly backwards. By the time a bad pattern has been copied a third time, it isn't a candidate for cleanup any more. It's infrastructure.
What a colleague on the platform team taught me
The person who eventually confronted me about it wasn't gentle about it, and I don't think gentle would have landed. He asked, directly, why I'd taken that approach and whether I understood what it meant for the team that now had to live downstream of it.
My first instinct was to justify myself. The client had got what they needed, on time, which felt at the time like the entire brief. The more he walked me through the actual downstream cost though, the harder that justification became to hold onto. The speed hadn't been free. It had simply been paid by someone else, later, off my books and onto theirs.
What stuck with me wasn't the telling-off. It was realising that I'd had no task, in the formal sense, to consider that cost at all. Nobody had asked me to weigh it, so I hadn't, and the absence of a prompt had felt indistinguishable from permission.
Building the check in before you commit
The change I made afterwards was small in mechanics and large in effect. Infrastructure came into the conversation before I committed to an approach, not after, framed as a direct question rather than a courtesy. Before I commit to this, what does it cost you.
It can slow you down at first, while you're building up that understanding. Every scoping conversation now had one more voice in it, and that voice didn't always say yes. But it pays for itself quickly. Once you understand the infrastructure you're building on and have a clearer sense of what's likely to surface later, you stop losing whole weeks to unwinding decisions nobody flagged in time. The call is still mine to make. I'm just making it with better information, rather than finding out what it cost a year later. The relationship with the platform team changed too, from one where they found out about my choices once they were already live, to one where they trusted I'd flag the expensive ones before they were locked in. Later projects moved faster overall for having that input built in from the start rather than bolted on after something had already broken.
There's a second habit that came out of it, and it's the one I'm most direct about now. When I see someone reaching for the same kind of shortcut under the same kind of pressure, I tell them plainly, and I've learned that the closer the deadline sits, the more important it is to say it rather than let it slide. The time to fix this properly will never magically appear once it's live. It gets harder to touch the longer other work grows up around it, not easier. If you take this path, watch your back, because nobody downstream is going to know why it's fragile unless you tell them now. My advice is not to take it.
That's the part the word "debt" undersells. The cost isn't only doing the same piece of work twice. It's the unhappy paths that only surface once someone finally tries to refactor or reengineer around the thing, the edge case nobody accounted for in the original hack, the erroneous state some unrelated feature has quietly come to depend on and the integration that looks correct right up until it hits the one branch nobody had reason to test at the time. None of that shows up on the day you ship. It shows up on the day someone else has to touch it.
A few habits followed from that, and they're worth naming explicitly for anyone scoping under similar pressure.
1. Treat the second use of a shortcut as the real decision point, not the first
The first instance is a judgement call under pressure. The second is the moment the shortcut becomes precedent for everyone who finds it afterwards. That's the point to stop and ask whether this is actually now "how we do it", intentionally or not.
2. Separate "it worked" from "it was free"
A shortcut that ships on time and doesn't visibly break anything has not been validated as a good decision. It has only been validated as a decision that didn't fail immediately, which is a much lower bar and tells you nothing about who is paying for it later.
3. Ask the team downstream before you commit, not after they find out
The cost of a fast path is usually invisible to the person making the call and very visible to whoever inherits it. Asking "what does this cost you" before committing is a five-minute conversation. Finding out a year later is a much longer one.
- [ ] If a shortcut is about to be used a second time, treat that as the decision moment
- [ ] Ask the team downstream what it costs them, before you ship, not after
I'd still rather be told bluntly and early than politely and late, and I try now to be the person who says the blunt thing to someone else before their second shortcut turns into everyone else's permanent infrastructure. The uncomfortable part isn't that hacks happen under deadline pressure. They always will. It's that nobody ever decides, out loud, that the second one is allowed to become the standard. It just quietly does.


