Waiting for a Green Light That's Never Coming: The Real Reason Developers Don't Fix What's Broken
Here's a scene that probably feels familiar. You're deep in a feature branch, touching a module you haven't visited in a while, and you notice it — the kind of code that makes you wince. Maybe it's a function doing five different jobs at once. Maybe it's a naming convention that made sense to someone in 2019 but actively misleads anyone reading it today. You know exactly how to fix it. You could probably knock it out in an afternoon.
And then you close the file and move on.
This isn't laziness. It isn't incompetence. What's happening is something a lot of engineering teams don't talk about honestly: developers have quietly learned that improving code they weren't explicitly asked to improve is risky. Not technically risky — culturally risky. And that distinction matters more than most engineering leads want to admit.
How Teams Accidentally Train Developers to Look the Other Way
No manager ever holds a meeting and announces, "From now on, don't fix anything unless we schedule it." It doesn't happen that way. Instead, the message gets delivered in subtler ways over time.
Maybe someone refactored a utility class a few months back, and the pull request sat in review purgatory for two weeks before getting closed with a comment about "scope creep." Maybe a developer cleaned up some dead code and got asked, half-jokingly, why they were touching things that weren't on the sprint board. Maybe the team has a strict "if it ain't broke" culture baked in from a previous incident where a well-intentioned cleanup introduced a regression.
Individually, none of these moments seem like a big deal. Collectively, they train engineers to self-censor. They learn to spot problems and file them away mentally rather than acting on them. The codebase gets messier. The cognitive overhead of working in it grows. And everyone quietly agrees that someone else will deal with it eventually — at some mythical future point when there's "bandwidth for refactoring."
Spoiler: that bandwidth never materializes on its own.
The Real Cost of the Permission Loop
When developers hesitate to make small, incremental improvements, the work doesn't disappear. It compounds. A function that needed a light cleanup six months ago now needs a full rewrite. A confusing variable name that could've been updated in five minutes is now woven into forty files. The longer teams wait, the more expensive the fix becomes — not just in hours, but in the mental load it places on everyone who has to work around the problem in the meantime.
There's also a subtler cost that's harder to measure: morale. Developers who care about their craft — and most of them do — find it genuinely demoralizing to work in a codebase they know is deteriorating. When they don't feel empowered to address problems they can clearly see, it creates a kind of learned helplessness. They stop investing emotionally in the quality of the system because the system has taught them that investment doesn't pay off.
At CHTree, we talk a lot about the environments where developers actually grow. And the honest truth is that you can't grow in a codebase you're not allowed to improve.
Why "Ask First" Culture Backfires
Some teams have formalized the permission loop into their process. Refactoring requires a ticket. The ticket requires approval. Approval requires justification. Justification requires metrics that are nearly impossible to gather for work that prevents future problems rather than solving current ones.
The logic behind this isn't completely wrong — you do want visibility into what's changing and why. But when the bureaucratic overhead of making a small improvement exceeds the effort of the improvement itself, rational developers stop making improvements. They optimize for getting their assigned work done and shipping features, because that's what the system rewards.
The result is a team that's technically productive by the metrics being measured and quietly drowning by every metric that isn't.
What a Healthier Refactoring Culture Actually Looks Like
Building a culture where incremental improvement is normal doesn't require a big process overhaul. It mostly requires a few deliberate shifts in how teams talk about and reward the work.
Make the boy scout rule explicit. The old idea — leave the code a little cleaner than you found it — works really well when it's a stated team norm rather than an unspoken hope. When developers know that small cleanups within the scope of their current work are not just tolerated but expected, they stop treating every improvement as a special request.
Separate refactoring from features in review conversations. When a PR mixes a new feature with a handful of cleanup changes, reviewers sometimes push back on the cleanup simply because it adds surface area. Teaching teams to recognize and appreciate scoped improvements — rather than flagging them as scope creep — changes what developers feel safe submitting.
Let developers own their technical environment. The teams with the healthiest codebases tend to be the ones where engineers have genuine agency over how the system is maintained. That doesn't mean zero oversight — it means trusting developers to make judgment calls about small improvements without needing sign-off every time.
Talk openly about technical debt in planning. When tech debt is a standing agenda item rather than a shameful secret, it becomes something the team manages together. Developers are far more likely to address problems incrementally when those problems are acknowledged as real work rather than treated as distractions from "real" work.
The Permission You're Actually Waiting For
Here's the uncomfortable part of this conversation: sometimes the permission problem isn't coming from management. Sometimes it's internal.
A lot of developers hesitate to refactor because they're not fully confident in their own judgment. They know something is wrong but aren't sure their fix is the right one. They worry about introducing a regression. They're uncertain whether the change is worth the disruption. In those cases, the solution isn't organizational — it's about building the habits and relationships that make it easier to act on good instincts.
Pair with someone on the change. Write a test before you touch anything. Make the improvement small enough that it's easy to review and easy to revert if needed. The goal isn't to be reckless — it's to stop treating every improvement as a high-stakes decision requiring external validation.
Good code doesn't maintain itself. It gets maintained by developers who feel empowered to care for it, consistently, in small ways, without waiting for a meeting to be scheduled about it. The teams that understand this ship better software, burn out less, and actually enjoy working in their own codebases.
The green light you're waiting for? You've probably had the authority to flip it yourself the whole time.