Inheriting a Codebase Nobody Documented
Last updated:
The instinct to rewrite is usually wrong
Inheriting an undocumented codebase is unpleasant and the instinct is to start again. Resist it for at least a quarter. The existing system, whatever its faults, encodes years of business rules that nobody wrote down anywhere else.
A rewrite discards that knowledge and rediscovers it painfully, in production, one edge case at a time.
Week one: can you deploy it?
Before understanding anything, establish that you can build and deploy the system reliably from source. If you cannot, nothing else matters — you have a system you can look at but not change.
- Get the source into a repository you control, with full history if it exists
- Stand up a local or staging environment from scratch, documenting every step
- Deploy an inconsequential change end to end — a text label — to prove the pipeline
- Confirm backups exist and restore one somewhere safe
Weeks two to four: see what it does
Add monitoring and logging before changing behaviour. Error tracking, request logging, and basic metrics tell you which parts of the system are actually used, which is frequently surprising.
In most inherited systems, a meaningful share of the code serves features nobody uses any more. Knowing which is which changes what you bother to understand and what you can simply leave alone.
Weeks four to eight: build a map
Document as you explore, in whatever form you will actually maintain. A one-page architecture sketch, a list of external dependencies, the deployment process, and the five business rules that are least obvious from the code.
- What talks to what, including anything scheduled
- Which third-party services it depends on and who holds the credentials
- Where the data lives and what the important tables mean
- The bits that look wrong but are load-bearing — ask before touching
Change safely: tests around the edges
You will not retrofit comprehensive tests, and you do not need to. Write tests around the specific area you are about to change, so you can tell whether you broke it. Over time this builds coverage where change actually happens.
Every bug you fix should get a test first. That way the areas that break most become the areas best protected, which is exactly the right distribution of effort.
When a rewrite is genuinely justified
The platform is unsupported and cannot be updated. The system cannot be deployed at all. It is written in something nobody can hire for. Or the data model genuinely cannot express what the business now does.
Even then, prefer replacing piece by piece behind stable interfaces rather than a big-bang rewrite. It takes longer and it means you are never six months into something with nothing shippable.
Frequently asked questions
How long before a new team is productive on an inherited system?
Should we ask the original developer for help?
What if the code is genuinely terrible?
How do we avoid this situation next time?
Inherited software nobody understands?
We take these on regularly. A short review tells you what you have, what it would cost to maintain, and whether replacing it is genuinely justified.
Related services
What we build for problems like this one