How to Take Over an Existing Codebase: An Audit Checklist

TQ
Tran Quang
October 30, 2026 · 7 min read
#Code Audit#Legacy Code#Hand-over#Best Practices

At some point you will inherit software you did not write: a previous vendor's app, a founder's prototype that became the product or a legacy system nobody wants to touch. The first week decides whether the take-over goes smoothly. This guide is a practical checklist for auditing an existing codebase, finding the real risks and agreeing a plan before you change anything.

Principles for the first week

  1. Do not start by rewriting. You do not yet know what the code does that nobody documented.
  2. Make it run first. If you cannot build and run it, you cannot safely change it.
  3. Separate facts from opinions. Write down what you observe, with evidence, before judging the previous team's choices.
  4. Stabilise before you improve. Backups, access and monitoring come before refactoring.

Step 1: Secure access and ownership

Before reading a line of code, confirm that you can actually operate the product:

  • Source repositories and every branch that matters
  • Cloud subscriptions and resource groups (Azure, AWS, Firebase and so on)
  • Domains, DNS and certificates
  • App Store Connect and Google Play Console, including signing keys and upload keys
  • CI/CD pipelines and their secrets
  • Third-party services: payments, email, analytics, push notifications
  • Production databases and a way to restore them

If the previous vendor still owns an account, arrange a transfer now. Losing a signing key or domain later is far more expensive than a short conversation today.

Step 2: Get it running locally

Time how long it takes a new developer to run the system. The result is an audit finding in itself.

  • Clone, install and run the app from a clean machine.
  • Note every undocumented step, missing environment variable and hardcoded path.
  • Write or fix the README as you go; this is your first deliverable.
  • Create a local or staging environment with fake data so you never experiment on production.

Containerising the setup with Docker Compose is often the fastest way to make the project reproducible.

Step 3: Map the architecture

Draw the system as it actually exists, not as someone remembers it:

  • Components: clients, APIs, background jobs, databases, queues and storage
  • Data flow: where user data enters, where it is stored and who can read it
  • External dependencies: every third-party API and SDK
  • Environments: what exists in development, staging and production, and how they differ
  • Deployment: how a change gets from a commit to users

A one-page diagram and a list of dependencies are enough. Compare the production cloud resources with the code; unused or untracked resources are common and often cost money.

Step 4: Measure code health with evidence

Use tools to produce numbers you can show the owner:

Area What to check Example tools
Dependencies Outdated or vulnerable packages dotnet list package --vulnerable --outdated, npm audit, flutter pub outdated
Static analysis Warnings, complexity, dead code Roslyn analysers, ESLint, dart analyze, SonarQube
Tests Count, pass rate, coverage of critical paths Test runners and coverage reports
Build Time and reliability of CI Pipeline history
Repository Commit history, bus factor, large files git shortlog -sn, git log --stat
Secrets Keys committed to history gitleaks, trufflehog

For .NET projects, unit testing in .NET explains how to add tests around the riskiest behaviour before you change it.

Step 5: Review security and data protection

Focus on issues with real consequences:

  • Secrets in the repository or in client apps. Rotate anything that leaked.
  • Authentication and authorisation. Can one user read another user's data by changing an ID?
  • Input handling. SQL injection, file upload paths, unvalidated deep links.
  • Transport and storage. HTTPS everywhere, encrypted backups, sensible retention.
  • Personal data. What is collected, where it goes and whether the privacy policy matches reality.
  • Admin surfaces. Default credentials, open dashboards, public storage containers.

Record severity and a concrete fix for each issue. Fix critical exposures immediately; schedule the rest.

Step 6: Check production health

Code quality means little if production is quietly failing:

  • Error rates and crash-free sessions from existing monitoring, or add monitoring if none exists. Application Insights is a good start on Azure.
  • Performance hot spots: slow queries, large payloads, startup time.
  • Backups: confirm they exist and restore one to prove they work.
  • Cost: compare cloud spend to usage and look for idle resources.
  • Store status: rating trends, recent reviews, pending policy warnings.

Step 7: Identify the knowledge that exists only in people's heads

Interview the previous developers or the owner if you can. Ask:

  • Which parts are fragile or were rushed?
  • What manual steps happen on every release?
  • What customer promises are not written down?
  • What would they refactor first and why?

Capture the answers in the repository, not in chat history.

Step 8: Decide: fix, refactor or rebuild

Most rewrites fail because they underestimate hidden behaviour. A rewrite is justified only when several of these are true:

  • The code cannot be understood or tested even with effort
  • The platform or framework is end-of-life with no upgrade path
  • Security or data problems are structural
  • Every change causes regressions
  • The product is small enough that rebuilding is cheap

Otherwise, prefer incremental improvement: add tests around critical flows, upgrade dependencies, extract modules and remove dead code in small steps. Principles from Clean Code and Clean Architecture help decide where boundaries should go.

Step 9: Write the audit report and a 30-60-90 day plan

A useful report is short and ordered by risk. Include:

  1. Summary: overall health and the top five risks in plain language
  2. Findings: each with evidence, impact, severity and a proposed fix
  3. Quick wins: low-effort changes that reduce risk this week
  4. Roadmap: 30, 60 and 90 day plan with priorities and estimates
  5. Open questions: things you could not verify

Example priority order:

  • Days 1 to 30: access, backups, monitoring, secret rotation, reproducible build, critical security fixes
  • Days 31 to 60: dependency upgrades, tests on core flows, CI/CD improvement, documentation
  • Days 61 to 90: targeted refactoring, performance work, planned feature development

Take-over checklist

  • All accounts, domains and signing keys transferred
  • App builds and runs from a clean machine
  • Architecture diagram and dependency list written
  • Dependency, security and secret scans completed
  • Backups restored successfully once
  • Monitoring and crash reporting in place
  • Audit report delivered with a 30-60-90 plan

Conclusion

A good take-over starts with access, a reproducible build and an honest picture of risk, not with a rewrite. Audit the architecture, dependencies, security and production health, write down what you find with evidence and agree a staged plan with the owner. If you have inherited a codebase and want an independent review or a hand-over, the services page describes how I handle maintenance and rescue work.

References

Found this useful?

Share it with someone who might need it.

Related articles All articles