A technical due diligence checklist you can run yourself
The questions we ask when assessing an unfamiliar codebase, in the order we ask them, with what each answer actually tells you.
This is the sequence we work through when assessing a system we have not seen before — before an acquisition, before taking over maintenance, or when a team has inherited something and needs to know what they are holding.
It is written so you can run it without us. Most of it needs no more access than a read-only clone and an hour with whoever maintains the thing.
Work top to bottom. The early sections are cheap and frequently decisive; there is no point profiling query plans in a repository that cannot be built.
1. Can you build and run it?
Start here, always. Clone the repository onto a clean machine and follow the README.
- Does the documented setup work, unmodified, on a machine that has never run it?
- How long from clone to a running local instance?
- Are there steps that require credentials only one person has?
- Does the test suite pass on a fresh checkout?
What it tells you. A project that cannot be built from its own instructions has a knowledge concentration problem, and knowledge concentration is the risk that turns into cost fastest. If onboarding takes three days of pairing, every future hire costs three days of two people’s time — and if the person holding that knowledge leaves before you find out, you are reconstructing it from the code alone.
2. What does the commit history say?
# Contributors by volume over the last two years
git shortlog -sne --since="2 years ago"
# Change frequency — the files most likely to be a problem
git log --since="1 year ago" --name-only --pretty=format:
| sort | uniq -c | sort -rn | head -30 - How many people have committed in the last year? In the last month?
- Is there one author with the overwhelming majority of commits?
- Do the highest-churn files correspond to the areas people complain about?
What it tells you. Contributor concentration is bus-factor risk stated as a number. High-churn files are where the design does not fit the problem — something is repeatedly being adjusted because it is in the wrong shape. That list is usually a good predictor of where the next six months of work goes.
3. What is the dependency position?
npm audit --production # or: pip-audit / bundle audit / cargo audit
npm outdated - How many dependencies are more than one major version behind?
- Is anything unmaintained, deprecated, or now a different project?
- Is the runtime itself in support? Check the vendor’s end-of-life date.
- Is there a lock file, and is it committed?
What it tells you. Dependency debt compounds quietly and then bills all at once. A framework two majors behind is not two upgrades; it is two upgrades plus every ecosystem package that moved with them. An out-of-support runtime is a different category — it is a deadline someone else set for you, and it is worth finding out what that date is before you agree to anything.
4. What happens on deploy?
- Is deployment automated, or a documented sequence someone performs?
- How long does it take, and how often does it happen?
- Can a deploy be rolled back? Has anyone rolled one back recently?
- How are database migrations applied, and are they reversible?
- Are there environments, and does staging resemble production?
What it tells you. Deploy frequency is the best single proxy for how quickly an organisation can respond to anything. Teams that deploy daily have implicitly solved a large set of problems — tests they trust, small changes, a rollback path. Teams deploying monthly have not, and every change they make carries the accumulated risk of everything else in that release.
The rollback question is worth pressing. “We could roll back” and “we rolled back last Tuesday” are very different answers.
5. What do the tests actually cover?
Coverage percentage on its own is close to meaningless. Look at shape.
- Are there tests around the money, the permissions, and the integrations?
- Are they unit tests over trivial code, or do they exercise real paths?
- Do they run in CI on every change, or only when someone remembers?
- How long does the suite take? Anything past ten minutes gets skipped.
What it tells you. Tests exist to make change safe. A suite with 85% coverage that avoids the billing logic provides no safety where it matters. Ask which part of the system people most avoid changing, then check whether it has tests. The answer is usually no, and that is your first piece of work.
6. What can you see in production?
- Are there dashboards, and does anyone look at them?
- Do alerts correspond to user-visible problems, or to resource thresholds?
- Are logs structured and searchable, or plain text on a box?
- When something broke last, how was it diagnosed?
What it tells you. That last question is the one that matters. Ask about a specific recent incident and listen to how they found the cause. “We saw the error rate, traced it to the checkout service, found the bad deploy” describes a team with observability. “We restarted things until it stopped” describes a team without it — and every future incident with them will be resolved the same way, which means slowly.
7. Where does the data live?
- What is the schema, and does it have documented constraints and foreign keys?
- Are backups taken, and has a restore ever been tested?
- Is there personal data, and is its handling documented?
- Are there manual data-fixing scripts people run? How often?
What it tells you. Untested backups are not backups. Ask when a restore was last performed as a drill; if the answer is never, treat the backup as unproven.
Regular manual data repair is a strong signal: it means the application permits invalid states and someone is compensating by hand. That is both an ongoing cost and a defect the schema should be preventing.
8. What do the maintainers say?
Interview whoever knows the system best. Three questions do most of the work.
- What would you fix if you had a free month? You will get the real problem list, ranked, from the person best placed to rank it.
- What do you avoid touching? This maps the areas without tests, documentation, or comprehension — usually all three.
- What has broken more than once? Recurring incidents indicate a cause that was never addressed, only mitigated.
What it tells you. More than any tool will. Maintainers generally know exactly what is wrong; they have often been saying so for years without being resourced to fix it. Ask early, and take the answers seriously.
Writing it up
Rank findings by risk against remediation effort — a two-by-two is enough. The useful output is not a list of everything imperfect; it is a short list of what would actually hurt, and what it costs to remove.
Three categories are enough:
- Blocking. Would you refuse to proceed until this is fixed? Unsupported runtimes, untested backups, single points of knowledge on critical systems.
- Priced in. Real work, but known and quantifiable. Dependency upgrades, missing test coverage, manual deploys.
- Noted. Imperfect, not urgent. Style, structure, things you would do differently.
If a finding does not change a decision or a number, it belongs in “noted” or nowhere. The value of an audit is in what it makes actionable, not in its length.
Related reading
Next step
Working on something like this?
We are happy to talk it through, whether or not it turns into an engagement.