Start a project

The state a stalled codebase is usually in

A codebase gets handed to a new team for a fairly narrow set of reasons: the previous team ran out of runway, delivery had stalled, or the client lost confidence before the system was in a state anyone could safely build on. Whatever the reason, the technical state on arrival tends to rhyme: patchy or absent tests, undocumented decisions that made sense to whoever made them and to nobody since, dependencies that haven’t been touched in a long time, and no clear owner for the parts that matter most. The instinct to start rewriting immediately is strong and almost always wrong.

Week one: read before you touch anything

The first week isn’t spent writing code. It’s spent building an honest picture of what’s actually there, because every decision after this point depends on getting that picture right.

Map what exists against what’s supposed to exist. Compare the codebase against whatever specification, ticket history, or client conversation describes what the system is meant to do, and find the gap between the two — not to assign blame, but because that gap is the actual scope of the remaining work, and it’s rarely the same as what the client believes it is.

Find out what’s actually running in production, as distinct from what’s in the repository. It’s common for a stalled project to have code that was never deployed, feature flags left permanently off, or a production environment that’s drifted from what the codebase would produce if you built it today. You cannot safely change a system you don’t correctly believe is running.

Run whatever tests exist and read what they actually assert. A test suite in a stalled codebase often has tests that pass without checking anything meaningful — asserting that a function didn’t throw, not that it did the right thing. Counting passing tests without reading them tells you nothing about coverage of the parts that matter.

Talk to whoever is still around, on the client side and, if possible, anyone reachable from the previous team. Institutional knowledge that never made it into a commit message or a doc is real, and it’s cheaper to ask for it now than to rediscover it the hard way three weeks in.

Week two: stabilize before you build

The second week’s job is to get the system to a state where changes can be made safely, which is a different goal from making the changes the client actually wants yet.

Get a real CI pipeline running if one doesn’t already exist — build, whatever tests are trustworthy, and a deploy path that doesn’t depend on someone’s local machine. This is unglamorous and it’s also the single highest-leverage thing to do before touching business logic, because without it, every subsequent change is a guess about whether it broke something.

Write characterization tests for the parts you’re about to touch. Where the existing test suite doesn’t cover a piece of logic you need to change, write a test that pins down its current behavior before changing anything — not because the current behavior is necessarily correct, but because a codebase in this state usually has undocumented behavior somebody downstream depends on, and “we changed it because it looked wrong” is how takeovers create new incidents on top of old ones.

Fix the smallest, highest-confidence issues first, visibly, and report them. Early, small, correct fixes rebuild trust with a client who has reason to be skeptical of a new team’s promises — trust that a takeover runs on for the first several weeks, before there’s been time to prove anything larger.

What we refuse to do

We don’t rewrite from scratch as a default. A full rewrite is occasionally the right call, but it’s the conclusion of an assessment, not the starting assumption — and it’s the option most likely to be reached for by a team that hasn’t actually read the existing system closely enough to know what it would be throwing away.

We don’t promise a timeline before week one is done. Any estimate given before the codebase has actually been read is a guess dressed as a commitment, and a stalled project is usually stalled partly because of exactly that kind of guess made earlier by someone else.

We don’t silently accept undocumented behavior as intentional. If something in the system looks like a decision nobody can explain, it gets flagged and confirmed with the client rather than assumed correct and built on top of.

We don’t skip the characterization step to move faster. It’s tempting, under pressure to show progress quickly, to start changing code before pinning down what it currently does. That’s exactly the shortcut that turns a takeover into a second stalled project.

What this means for you

If you’re evaluating a team to take over a stalled codebase, the first question worth asking isn’t how fast they can start writing new code — it’s whether their plan includes two weeks of reading, mapping, and stabilizing before that starts. A team that skips straight to a rewrite proposal, or straight to a delivery estimate, hasn’t yet done the work that makes either of those trustworthy.

engineering-practice · delivery

30 minutes with a senior engineer.

Tell us what you're building. You'll leave with an honest opinion, even if it's "you don't need us."

Reference calls with past clients are available under NDA during evaluation.