A new team inherits a codebase, finds it unpleasant, and proposes a rewrite within a fortnight. Sometimes that is correct. More often the code is merely unfamiliar, and the rewrite trades a system with known problems for one with unknown problems and none of the accumulated business rules.
What the audit covers
Before recommending anything we spend two weeks producing a written audit. It is deliberately boring and deliberately specific.
- Architecture: actual boundaries and data flow, not the diagram in the wiki
- Dependency health: what is unmaintained, unpatched, or pinned to a dead version
- Test coverage: where it exists, where it is theatre, and what is untestable
- Change velocity: which files churn, which break, and where the fear lives
- Security posture: secrets, authentication, injection surface, and access control
- Operational reality: deploy frequency, rollback path, incident history
The question that usually settles it
Can a new feature of average size be shipped safely in a normal sprint? If yes, the system does not need replacing; it needs targeted refactoring where the pain concentrates. If every change requires a specific person and a held breath, that is genuine architectural debt.
Strangle, do not rewrite
When replacement is warranted, we almost never do it in one cut. Functionality moves across in slices behind a routing layer, both systems run in parallel, and the old one is retired only when it is genuinely idle. It is slower on paper and dramatically faster in practice, because value ships throughout.
The rewrite that only delivers value at the end is the rewrite that gets cancelled at 70%.
Write it down
The audit is a document with names, files and line numbers, not a presentation. It survives the meeting, it can be argued with, and twelve months later it explains why the decisions were made. That last property is worth more than most of the recommendations in it.
- Architecture
- Legacy
- Process