Kueri.me All articles
Developer Culture

Cleaning Code Instead of Shipping It: The Refactoring Escape Hatch We All Use

Kueri.me
Cleaning Code Instead of Shipping It: The Refactoring Escape Hatch We All Use

Photo: Rico Shen, CC BY-SA 3.0, via Wikimedia Commons

The Most Respectable Form of Avoidance in Tech

There's a particular kind of procrastination that never shows up on a performance review. It doesn't look like scrolling Twitter or reorganizing your desk for the fourth time. It looks like discipline. It looks like craft. It looks like a beautifully refactored service layer that nobody asked for, delivered three days before a feature was supposed to ship.

Welcome to the refactoring escape hatch — one of the most socially acceptable ways to avoid doing the thing you're actually supposed to do.

This isn't about whether clean code matters. It does. Readability, maintainability, reducing cognitive load — all real, all valuable. The problem surfaces when the drive to clean things up conveniently peaks right when requirements get fuzzy, a new domain feels intimidating, or stakeholder feedback starts getting uncomfortable. Suddenly that 600-line controller class becomes the most urgent thing in the codebase.

Why Our Brains Love This Particular Trap

Refactoring scratches a specific itch. It's concrete. You open a file, you see a mess, you make it better. The before-and-after is right there. Pull request approved, dopamine delivered.

Compare that to the actual hard stuff: figuring out what a feature should even do when the product manager's requirements are three Slack threads and a vague Figma prototype. Or learning a new domain — say, payment processing or healthcare data — where every answer you find just surfaces five more questions. Or, maybe worst of all, sitting with the discomfort of not knowing where to start.

Refactoring sidesteps all of that. It's progress you can see and measure, in a space where you already feel competent. Psychologists call this kind of thing "structured procrastination" — staying busy with lower-stakes tasks to avoid higher-stakes ones. Developers just happen to dress it up in pull request descriptions.

The kicker is that nobody calls it out. If you spend two days reorganizing a module instead of tackling the ambiguous auth feature, your standup still sounds fine. "Working on some cleanup in the user service" lands very differently than "I've been avoiding the OAuth implementation because I'm not sure where to start."

How to Spot It In Yourself (and Your Team)

The timing is usually the tell. Ask yourself: when did the urge to refactor show up? Was it already on the roadmap, or did it materialize right around the time something harder landed in the queue?

A few patterns worth watching for:

The scope creep refactor. You're fixing a bug, and suddenly you're restructuring three adjacent files because they "could really use some love." The bug is fixed in twenty minutes. The cleanup takes two days.

The prerequisite that isn't. "I can't build this feature until I clean up the data layer first." Sometimes that's true. Often it's a story you're telling yourself to delay the uncertain part.

The perfectionism loop. You refactor the same module twice in a sprint because the first pass "wasn't quite right." Meanwhile the feature it supports hasn't moved.

The learning detour. You're supposed to be building something in an unfamiliar framework, but you keep finding reasons to go back and clean up code in the parts of the stack you already know well.

None of these are inherently bad behaviors. They become a problem when they're a pattern — when they consistently appear as a response to discomfort rather than as a response to actual technical need.

When Optimization Is Genuinely the Right Call

To be fair, sometimes refactoring really is the job. If you're about to build on top of a genuinely brittle foundation, cleaning it up first is legitimate risk management, not avoidance. If a module is so tangled that onboarding a new teammate would take twice as long, that's real cost.

The distinction usually comes down to whether the work is serving the product or serving your anxiety. Good refactoring has a clear beneficiary — the next feature, the next developer, the system's reliability. Avoidance refactoring has a clear beneficiary too: your sense of forward momentum without the risk of failure.

A useful gut-check question: if someone asked you to skip the cleanup and ship the feature anyway, would you have a real technical argument for why that's risky, or would you mostly feel uncomfortable? Discomfort isn't nothing, but it's not the same as a dependency.

Redirecting the Energy Without Losing the Habit

The goal isn't to stop refactoring. The goal is to refactor intentionally instead of reflexively.

One approach that works: timebox the cleanup explicitly. If you know a module needs love, put it on the board as its own task with its own estimate. That separation forces you to make a conscious choice about priority rather than letting cleanup expand to fill whatever space the scary work leaves behind.

Another move is to name the thing you're avoiding. This sounds almost embarrassingly simple, but it works. Write it down: "I'm avoiding the payment integration because I don't know the Stripe API and I'm worried I'll get it wrong." Once it's named, it's a problem you can solve — read the docs, pair with someone, spike a prototype. It's much harder to avoid something you've made explicit.

Teams can help here too. If your sprint retrospectives never surface "we refactored instead of shipped" as a pattern, you might not have the psychological safety to name it. That's worth fixing. Not to shame anyone, but because the team deserves to understand where its energy is actually going.

Finally, lean into the discomfort deliberately. The feeling that makes you want to go clean something up — that low-grade anxiety about the ambiguous or unfamiliar task — is actually a pretty reliable signal that you're at the edge of your current capability. That's where growth happens. Refactoring the same familiar code doesn't put you there. Shipping the weird, uncertain, slightly-over-your-head feature does.

Ship the Messy Thing

Clean code is worth caring about. But it's not worth using as a psychological bunker.

The developers who consistently ship value aren't the ones with the prettiest codebases — they're the ones who've learned to sit with uncertainty long enough to move through it. They refactor when it matters and ship when it counts, and they've developed enough self-awareness to know the difference in the moment.

So the next time you feel that familiar pull toward "just a bit of cleanup first," take thirty seconds to ask what you're actually trying to avoid. The answer might surprise you — and it's probably the thing you should be working on.

All Articles

Related Articles

Sprint Points Don't Ship Products: The Velocity Trap Quietly Killing Your Team

Sprint Points Don't Ship Products: The Velocity Trap Quietly Killing Your Team

Green Dashboards, Red Reality: When Your Engineering Metrics Are Just Cosplay

Green Dashboards, Red Reality: When Your Engineering Metrics Are Just Cosplay

Your Side Project Isn't Dead — It Was Never Designed to Live