Short answer: Taking over a codebase from a previous agency requires a disciplined sequence: secure access first, understand what you have second, stabilise third, improve fourth. Skipping stages — particularly the stabilise phase — is the most common reason post-takeover projects fail or drag on for months beyond their planned timeline.
Before you touch anything: secure all access
The first priority is to get every credential and account into your control before the previous relationship formally closes. Once an agency knows they are being replaced, there is no guarantee of continued cooperation or good faith. Get access before they know they are leaving, if the relationship allows it. If that is not possible, get access as part of the formal handover process, not after.
The access transfer checklist should include:
- Source code repository — transfer the repository to your own GitHub/GitLab/Bitbucket organisation, not just add you as a collaborator. You want ownership of the repository, not a permission that can be revoked.
- Cloud infrastructure accounts — AWS, GCP, Azure, DigitalOcean, Vercel, Render — every account where the application runs. Change root/owner email addresses to one you control.
- Domain registrar and DNS — domains and DNS records are frequently overlooked and are among the most damaging to lose control of. Transfer domain registrar accounts or confirm registrar lock settings.
- SSL/TLS certificates — note expiry dates and confirm you can renew independently.
- Third-party API credentials — Stripe, Razorpay, SendGrid, Twilio, Google APIs, any other integration. Get the API keys themselves; rotating them is the next step.
- Database access — production database credentials, backup access, and confirmation that backups exist and are restorable.
- CI/CD pipeline — GitHub Actions, CircleCI, Jenkins, or whatever the agency used. Get the pipeline configuration files and any secrets stored in the pipeline environment.
- Monitoring and alerting — Sentry, Datadog, Grafana, or equivalent. Transfer ownership or create new accounts and migrate configurations.
See our software handover checklist for a complete version of this list.
Rotate every credential immediately
Once you have access, rotate everything. Not eventually — immediately, before you do anything else.
The previous agency's team members had access to production credentials. Those team members may have left the agency. Their laptops may have been compromised. The credentials may have been stored in their shared password manager, their Slack, their code (it happens more than anyone admits). You cannot know. Assume they are compromised and rotate them.
The rotation order matters. Rotate database passwords first, update application environment variables to match, then deploy. Rotate API keys for each third-party service, updating environment variables each time. Change all cloud infrastructure account passwords and enable MFA on every account if it is not already on.
Document each rotation with a timestamp. You will want this record for security audit purposes and because you will inevitably forget which services were updated.
Understand the repository: what you actually have
Once access is secured and credentials are rotated, the assessment phase begins. This is diagnostic work — resist the urge to start making changes.
Clone and build it locally. The first test of a codebase is whether you can run it on a fresh machine. If you cannot — if the README is missing, the environment variables are undocumented, or the build fails on a clean checkout — that is important information about the state of the system. Note every step you had to improvise.
Read the dependency manifest. package.json, requirements.txt, Gemfile, go.mod, pom.xml — whatever the language uses. Note the versions of major dependencies. Flag anything that is significantly out of date, no longer maintained, or known to have security vulnerabilities. Tools like npm audit, pip-audit, and Dependabot can automate part of this.
Run a licence audit. Every open-source dependency carries a licence. Check for GPL or AGPL licences if the software is proprietary — their copyleft requirements may create obligations you do not want to inherit. FOSSA, Snyk, and similar tools can produce a licence inventory automatically.
Look at the git history. The commit log is the archaeology record of the codebase. Look for: how frequently was it committed, were there long gaps, are commit messages meaningful, are there commits from many contributors or just one. A single-author codebase with infrequent commits and poor messages is harder to maintain than it might appear from the outside.
Assess test coverage. Run the test suite. Does one exist? Does it pass? What percentage of the code does it cover? A codebase with no tests is not inherently a disaster, but it means every change you make carries higher risk. You will need to write tests before you can confidently refactor.
Build the risk register
Every codebase has risks. The risk register is your structured list of them, each scored for likelihood and impact. It is not a document for its own sake — it is the input to your stabilise plan.
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Critical dependency unmaintained | High | High | Schedule upgrade sprint within 30 days |
| No automated tests | High | High | Write smoke tests before any changes |
| Hard-coded secrets in codebase | Medium | Critical | Rotate and move to env variables immediately |
| No documentation of architecture | High | Medium | Document from code and interviews before agency contact ends |
| Single developer knew the system | High | High | Pair on every change for first 60 days |
| Backups untested | Medium | Critical | Restore test within first week |
Walk through the codebase with this lens. Flag every hardcoded credential, every undocumented environment variable, every TODO that appears to be load-bearing, every place where a comment says "don't touch this or everything breaks."
Documentation gaps: filling them before memory fades
The window for institutional knowledge transfer from the previous agency is short. If any cooperation is possible, use it immediately — even a 2-hour call with the lead developer is worth more than weeks of reading code.
What you need to understand:
- What are the non-obvious architectural decisions, and why were they made?
- Are there any known issues or workarounds in production that are not documented?
- What does the deployment process actually do, step by step?
- Which parts of the codebase are fragile and should not be touched without care?
- Are there any integrations with undocumented behaviour from third-party services?
If no knowledge transfer is possible, code-reading is slower but sufficient. Start with the entry points — the route handlers, the main function, the event loop — and trace outward. Write down everything you learn as you learn it, even if the writing is rough. You can organise it later.
Stabilise before you improve
This is the principle most new teams violate. They inherit a working — if imperfect — production system and immediately begin making improvements. The improvements introduce bugs. The bugs hit production. The client loses confidence in the new team before they have had a chance to demonstrate competence.
The stabilise phase has one goal: ensure the system is reliably observable and deployable before you change its behaviour. That means:
- Confirm backups are working and tested. Restore to a staging environment.
- Get monitoring in place. Error tracking (Sentry or equivalent), uptime monitoring, and basic performance metrics (response times, error rates) should be active before any changes.
- Reproduce the environment exactly. Your staging environment should match production. If you cannot reproduce an issue locally, you cannot fix it reliably.
- Document the deployment process. Every step, including the manual ones. Automate whatever is not already automated.
- Write smoke tests for critical paths. User login, payment processing, whatever the core transaction of the product is. These tests run before every deployment.
Only once these five conditions are met should you begin improving the codebase. See our legacy software modernisation guide for what comes after stabilisation.
The staged improvement plan
After stabilisation, improvements follow a priority sequence:
Sprint 1–2 (Weeks 1–4): Security fixes only. Rotate remaining credentials, patch known vulnerabilities, move hardcoded secrets to a secrets manager. Nothing that changes application behaviour.
Sprint 3–4 (Weeks 5–8): Test coverage for critical paths. Aim for 60–70% coverage on core business logic before touching it. This is the insurance policy for everything that follows.
Sprint 5–8 (Weeks 9–16): Targeted refactoring of the highest-risk areas identified in the risk register. One area at a time. Small, reviewable pull requests. No big-bang rewrites.
Sprint 9 onwards: Feature work and planned modernisation, from a codebase you understand and can confidently change.
The temptation to rewrite from scratch is real, especially when the inherited code is poor quality. Resist it unless the assessment genuinely shows the codebase is not salvageable. Rewrites take longer than expected, recreate bugs that were quietly fixed in the original, and leave you with no production track record on the new system. Strangler-fig migration — replacing components incrementally — is almost always safer.
| Phase | Goal | Timebox |
|---|---|---|
| Access and credential rotation | Secure the system | Days 1–3 |
| Assessment | Understand what you have | Week 1–2 |
| Stabilise | Make it observable and deployable | Weeks 2–4 |
| Security sprint | Fix critical vulnerabilities | Weeks 4–6 |
| Test coverage | Enable confident changes | Weeks 6–10 |
| Refactor | Reduce risk in core areas | Weeks 10–20 |
| Feature development | Build new value | Week 20+ |
If you are planning a takeover, the software development contract guide includes the clauses that should govern what the outgoing agency is required to hand over.
NexaEx takes on codebase recoveries and stabilisation projects. If you have inherited a system you are not sure about, let us look at it.
Frequently asked questions
What is the first thing I should do when taking over a codebase from a previous agency?
Secure all access before the agency knows they are being replaced, or as the first formal step of the handover. Transfer repository ownership to your own organisation, change root account emails on all cloud infrastructure, transfer domain registrar control, and collect every API key and database credential. Once you have them, rotate all credentials immediately — assume they may have been shared, stored insecurely, or compromised. Do not begin assessment work until credentials are rotated.
How do I assess the quality of code I am inheriting?
Start by cloning the repository and attempting a fresh build on a clean machine — the friction you encounter is itself diagnostic. Then read the dependency manifest and flag outdated or unmaintained packages using tools like npm audit or pip-audit. Run a licence audit with FOSSA or Snyk. Check the git history for commit frequency and message quality. Run the test suite and check coverage. Build a risk register that scores each finding by likelihood and impact, and use that to prioritise your stabilisation work.
Should I rewrite the codebase from scratch or improve it incrementally?
Incrementally, in almost every case. Rewrites take longer than planned, recreate bugs that were quietly fixed in the original system, and leave you with no production track record on the new code. The exception is when the assessment genuinely shows the codebase is not salvageable — for example, it has critical security vulnerabilities throughout, uses frameworks with no upgrade path, or is so poorly structured that incremental change is impossible. Strangler-fig migration, replacing components one at a time, is the safer default.
What institutional knowledge should I extract from the previous agency before they leave?
The window is short, so prioritise: non-obvious architectural decisions and why they were made, known production workarounds not in the documentation, a step-by-step walkthrough of the deployment process, which parts of the codebase are fragile, and any undocumented behaviour in third-party integrations. Even a two-hour call with the lead developer is worth weeks of code reading. If no knowledge transfer is possible, start from the entry points — route handlers, the main function — and trace outward, documenting as you go.