Skip to main content
Menu
Back to Writing
ModernizationRefactorPerformance

How I'd untangle a brittle codebase in 30 days

A step-by-step playbook for turning a codebase that slows down every change into one that ships reliably without a ground-up rewrite.

By ··4 min read

Every company I've modernized has the same story: "the original team moved fast, we shipped the thing, and now every change takes three times longer than it used to." By the time I'm brought in, the team has usually been asking for a rewrite for six months and leadership has been refusing for six months, and both sides are right.

A rewrite is almost always the wrong answer. What you actually need is a plan sequenced by risk, where the most painful parts of the codebase become the most decoupled parts in that order, not the other way around.

Here's the plan I follow. Times quoted are for a team of 3–5 engineers on a codebase that's been around 2–4 years.

Week one measure, don't guess

The first mistake everyone makes is refactoring the parts of the codebase the engineers complain about, rather than the parts that are actually slowing things down. These overlap surprisingly little.

Spend the first week instrumenting:

  • Change failure rate per directory. git log --name-only + deploy failure data. The directories that appear in the most post-mortems are your real hotspots.
  • Build + test timing. Split the test suite into groups and measure each. Almost always, 10% of the tests take 80% of the time, and they cluster around one subsystem usually the one nobody wants to touch.
  • Lead time to change. From PR opened to PR merged. A single heatmap grouped by file path tells you where review gets stuck.

You're looking for overlap. The directory that's in the most post-mortems AND has the slowest tests AND the longest PR cycle times is the one you fix first. Not the one the loudest engineer keeps filing bugs against.

Week two stop the bleeding

Before refactoring anything, you cap the damage. This means:

  • A linting + formatting baseline enforced in CI. Not what the team should use what they actually use today, codified so new commits can't drift further.
  • A "boy scout" rule for the hotspot directory. Every PR that touches it must leave it a notch cleaner. Add a test. Rename a variable. Extract one helper. The only firm rule is: no PR increases complexity.
  • One integration test covering the critical path. Not unit tests, not a full suite just one end-to-end test that exercises the happy path of whatever business flow the company lives on. This test is your safety net for everything that follows.

Week two is boring. It's also the week that determines whether the refactor succeeds, because from here on you're making structural changes and you need a way to know they haven't broken anything.

Week three extract the hotspot

Now the technical work. The goal isn't to rewrite the hotspot. The goal is to put a boundary around it so the rest of the codebase stops touching its internals.

Practical moves:

  • Move the hotspot behind an interface. If it's a class, introduce a factory. If it's a service, introduce a facade. Anywhere the rest of the code reaches into its internals, redirect through the boundary.
  • Once the boundary is in place, the internals can be refactored freely. Nothing outside knows.
  • Delete dead code. Every mature codebase has 15–30% dead code; the subsystem you just put a boundary around is the easiest place to find it, because callers are now explicit.

This week usually produces a 20–30% reduction in the hotspot's cyclomatic complexity without changing any observable behavior. It's not a rewrite it's a dam.

Week four ship a user-visible win

The last week is the most important, and it's the one technical leaders most often skip. Turn the refactor into a product win.

Pick one thing a page load time, an API latency, a flaky feature, a slow background job and make it measurably better as a direct consequence of the refactor. Announce it internally. Show the graph.

Two things happen:

  1. The business stops seeing refactoring as a cost center. They now have evidence that this work produces customer-visible outcomes.
  2. The team stops seeing refactoring as risky. They now have a template instrument, boundary, extract, ship that they can apply to the next hotspot on their own.

By day 30 you don't have a rewritten codebase. You have a codebase with one meaningfully better subsystem, a working safety net, a measurement baseline, and a team that believes change is possible. That's worth more than any rewrite you could have started.

The next 60 days

Most engagements like this run past the first month, but they run differently. Weeks 5–12 look like a series of repeats of the same playbook on the next-worst hotspot, the next-worst, the next-worst each one costing less than the last because the boundaries from previous rounds compound.

By month three, the codebase hasn't been rewritten. It's just become a codebase where change is cheap again. Which is what leadership actually wanted all along.

If this sounds like the codebase you're currently stuck in, my Modernization & Tech Audit engagement is the packaged version of the above. Or start a conversation if you'd rather talk through the specifics first.

Working through this yourself?

This is the kind of work I help founders and product teams run. Book a discovery call if it's not a fit, I'll point you to someone it is.

Start a Conversation