Choosing a partner
Switching development agencies without losing your codebase
Secure the accounts before you give notice.Repository ownership, the domain registrar, the cloud root account, App Store Connect and Play Console, CI secrets, the payment provider dashboard, analytics, and the domain email that receives every password reset. Leverage evaporates the moment your outgoing agency learns you’re leaving. Then commission a written audit before anyone changes a line of code, one to two weeks, specified as deliverables rather than adjectives. Budget two to four weeks to operational takeover if the outgoing team cooperates, and treat that cooperation as the variable it is.
The order is the entire argument. Most handover advice opens with the code, which is the part nobody can take away from you. By the time you’re reading code, you’ve already spent whatever leverage you had.
Secure the assets before you say a word
The uncomfortable premise: some of what you paid for sits in accounts registered to an email address you don’t control. Rarely malice. It’s the fastest path on day one, nobody revisits it, and three years later the registrar login belongs to a developer who left in 2024.
The ownership inventory
One row per account: owner of record, billing email, who holds the MFA device, and what your own role is. Access is not ownership. A collaborator can be removed in one click.
- Source control.Is the repository in an organisation your company owns and pays for, or in the agency’s org with you added as a member? Check the billing owner, not the members.
- Domain registrar.The registrant contact and the account login, not just the ability to edit DNS, plus the authorisation code. ICANN’s transfer policy imposes a 60-day lock after registration and after a previous transfer, and the one that catches people is the lock that can follow a change of registrant. Start that clock early.
- Cloud root.The AWS root email and its MFA device, the GCP organisation owner, the Azure tenant, plus team ownership on Vercel or Netlify. “It runs in our account” means you own the bill and none of the infrastructure.
- App stores.The app belongs under an Organization enrolment in your entity’s name, with your person as Account Holder. Apple transfers are conditional, and Apple Pay merchant IDs, iCloud containers and shared App Groups have historically blocked them, so check the current criteria first. On Play you can’t republish the same package name from another account, so “we will re-upload it” costs every install, rating and review.
- CI secrets. Write-only by design. You cannot read them back out of GitHub Actions or GitLab, so ask for the values in a password manager, not for pipeline access.
- Payment providers. The Stripe, Adyen or PayPal account itself, the live keys, and the webhook endpoints with their signing secrets. In payments or regulated financial software, add the merchant of record and the PCI scope questionnaire.
- Measurement. Analytics ownership, tag manager, Search Console, ads, and the error tracker.
- Email. The mailbox that receives password resets. If admin@yourdomain forwards to the agency, they hold the recovery path to everything above and the rest of this list stops mattering.
What “we host it for you” usually means
Resold hosting on the agency’s own account, with your site as a line item on their invoice. You cannot migrate without their cooperation, and a billing dispute of theirs can take your site down for reasons unconnected to you. Our position here is absolute: a production dependency that can be switched off by an organisation you’re about to stop paying is an incident that already has everything except a date.
The order of operations in the week before notice
- Build the inventory above, one row per account.
- Create the accounts you don’t have yet. A transfer needs somewhere to land.
- Take a full clone with history:
git clone --mirroron every repository, not a zip of the working tree. History is evidence, and the artefact most easily lost in a rushed export. - Export the data properly. A dump you restore locally and open, plus the storage buckets. A backup nobody has restored is a rumour.
- Rotate what can be rotated safely and identify what cannot. Webhook secrets, push certificates and signing keys break production when rotated carelessly.
- Then give notice.
The obvious objection is that this reads as bad faith, which is why it belongs in the days before the conversation rather than performed over months. In practice the common failure is not a vengeful agency. It’s that whoever held the credentials left eighteen months ago and nobody noticed.
What your contract actually assigns
“Work for hire” is narrower than people assume
Under US copyright law the work-made-for-hire doctrine covers employees acting within the scope of employment, plus a short enumerated list of commissioned work types. Custom software generally is not on it, so for a contractor ownership moves by express written assignment or not at all. Other jurisdictions differ, and several don’t recognise the doctrine for contractors.
We’re engineers rather than lawyers, so take advice in the jurisdiction named on the contract. What we can tell you is which clauses to put in front of that lawyer.
- Present assignment versus a promise.“Hereby assigns” transfers title now. “Agrees to assign” needs a further act that may never happen.
- Assignment conditioned on payment in full. Reasonable until there is a disputed final invoice. Settle it, or you may not own what you are auditing.
- Background IP carve-outs.The clause reserving the agency’s “reusable frameworks”. You want a perpetual, irrevocable, sublicensable licence to everything carved out, with each item named rather than described.
- Infrastructure and configuration. Usually unmentioned in the assignment clause, and increasingly the part that encodes how the system actually runs.
- Data processing. The DPA and sub-processor list, for GDPR and your next enterprise security review.
The third-party licence audit that surfaces two years later
Free to run now, ruinous during diligence, and precisely what an acquirer or an enterprise customer checks.
- Purchased themes and templates.Marketplace licences are granted per end product, and the standard tier usually doesn’t cover an end product that is itself sold. Find the invoice, read the tier.
- Fonts. A desktop licence deployed as a webfont, or a webfont licence with a pageview cap you passed a year ago.
- Copyleft and source-available terms.Scan the lockfile; don’t eyeball the package list. AGPL inside a hosted product is the one that genuinely bites, because network use triggers the source obligation. BUSL, SSPL and anything carrying a Commons Clause aren’t open source whatever the README implies.
license-checker,pip-licensesand ScanCode all do this in an afternoon. - Model and dataset licences. For AI features, check whether the checkpoint in use is licensed for commercial deployment at all.
- The git history tell. Run
git log --diff-filter=Aand the contributor statistics. A single initial commit of forty thousand lines means the starting point was bought or copied under terms nobody recorded.
Specify the audit as deliverables, not adjectives
“Code review” and “health check” are adjectives. Six artefacts a one-to-two-week audit should hand back, before anyone opens a pull request.
1. A build from a clean checkout
Clone into an empty directory on a machine that has never built the project. No environment file borrowed from a laptop. Time it. Under an hour with the README is healthy. Four hours of two engineers guessing at missing values is a warning you should price in. If it can’t be done without the outgoing team on a call, you don’t have a codebase. You have a person.
2. A dependency and CVE inventory
Not a vulnerability count. Direct versus transitive totals, how many majors behind each direct dependency sits, the runtime version and its end-of-life date, and which advisories are reachable from your code rather than merely present in the tree.
npm audit overreports dev-only transitive advisories, so use osv-scanner against the lockfile or trivy fsas the tie-breaker, and take an SBOM as the artefact. What predicts pain isn’t the CVE count. It’s how far behind the framework is, and whether an unmaintained package sits at the centre of the data layer.
3. Tests, described by what they assert
Coverage is trivially gamed by tests that call a function and assert it returned something. Ask for five numbers: coverage, the share of tests asserting a specific outcome, whether integration tests hit a real database, suite runtime, and skipped-test count.
Then run mutation testing on the two most business-critical modules, using Stryker for TypeScript, mutmut for Python, or PIT for the JVM. If a large share of mutants survive, the suite watches the code execute without checking what it did.
4. Migration and seed reproducibility
From an empty database, run every migration to head, seed it, start the app. If the production schema can’t be rebuilt from the repository, the repository isn’t the source of truth and every environment is bespoke. Look for migrations edited after they were applied, which a checksum failure in Flyway or Alembic gives away, and for schema changes that only ever existed as hand-run SQL.
5. A secrets inventory reconstructed from code
Don’t accept the example env file. It’s the most reliably stale file in any repository. Reconstruct the real set from source, then diff:
# what the code actually reads
grep -rhoE "process\.env\.[A-Z0-9_]+" src | sort -u # node
grep -rhoE "environ\.get\(.[A-Z0-9_]+" . | sort -u # python
# what the repo claims it needs
grep -oE "^[A-Z0-9_]+" .env.example | sort -u
# the difference between the two is the real inventoryThen classify every row by who issues it, who can rotate it, and what breaks when it rotates. Signing keys and push certificates need a window, and a period accepting both old and new values.
6. An architecture decision record, written after the fact
Nobody wrote one at the time. Write eight to twelve now, one page each, in a format such as MADR: the decision, the context as it stood then, the alternatives, and the consequence you live with today. Most get reconstructed from git history and from reading the code, and that’s the point, because the decisions the new team can’t justify are the change list. This is what turns an audit into a plan.
The handover meeting worth paying for
One recorded session, ninety minutes, with the engineers who wrote the code rather than the account manager who sold it.
- What breaks at three in the morning, and what do you do about it?
- What did you want to fix and never got budget for?
- Which part would you refuse to touch without a rewrite?
- Where is the manual step: the spreadsheet, the cron job that patches something, the thing one person runs on Mondays?
- What do you know that is written down nowhere?
Pay for it. A funded two-week transition with a named engineer and an agreed response time beats a free one you spend a month chasing. Money turns a breakup into a contract, and a contract has deliverables. The same principle drives the access rules in working with a distributed development team, which is where most handover problems are quietly created.
Takeover, partial rewrite, or full rebuild
The audit produces one of three verdicts, separated by evidence rather than impressions.
| Evidence from the audit | Verdict | What you are buying |
|---|---|---|
| Clean checkout builds, tests assert, migrations replay | Straight takeover | Two to four weeks of onboarding, then normal delivery |
| Builds only with undocumented values, thin tests, schema drift | Takeover after stabilisation | Two to six weeks paying down operability first |
| Auth, payments or the data model unsound, untested boundaries | Partial rewrite behind the current interface | Module-by-module replacement while the system stays up |
| No valid IP assignment, or a template licence that does not permit your commercial use | Rebuild, regardless of code quality | A clean-room build, because the legal defect is not fixable |
The last row is the one people argue with, and the one we won’t move on. Good code you don’t own is worse than mediocre code you do. Once the verdict is takeover or partial rewrite, the question becomes what to do with the code, a different decision with different signals, worked through in how to judge whether to rewrite or refactor an inherited codebase.
Where our own approach costs you something
Two admissions. The first is that sequencing accounts before the conversation is adversarial in tone, and if the relationship was recoverable, this can be what ends it. A project stalled by unclear scope and thin communication isn’t fixed by changing vendors. It’s restarted, and you pay for the ramp twice.
The second is about the audit. Two weeks of reading tells you about structure, dependencies and reproducibility. It tells you nothing about the two production behaviours nobody wrote down, which you meet in week five. Our takeover estimates have been wrong optimistically more often than pessimistically, which is why we scope this in stages with a decision point between them.
And the case where you should hire nobody: if what’s driving the switch is a content site that’s slow and awkward to edit, a takeover may be the wrong purchase. A hosted platform you own outright removes the dependency instead of transferring it. Custom code is a liability you take on because the product requires it. Where it doesn’t, stop carrying it, which is a version of the trade-off in the in-house, agency and freelancer comparison.
What a takeover realistically costs and how long it takes
The written audit is one to two weeks with no code changes, which is where the better pages on this topic have converged and we think they’re right. Operational takeover, meaning your team deploys, holds every credential, restores from backup unaided, and has shipped one real change, runs two to four weeks with a cooperative outgoing team. Add two to six when that team is unreachable, because rediscovering undocumented infrastructure doesn’t parallelise.
An illustration of how the number moves, not a case study: the same feature set in a repository that builds cleanly in forty minutes, versus one needing three days of archaeology, is the difference between a takeover and a stabilisation.
On our own published rate card: the minimum for a build is $7,500, with a written audit below that at $3,500 to $6,000 and credited against the build; platform work starts at $28,000; most projects land between $18,000 and $45,000. Those are estimates in US dollars, not quotations; the quote that follows scoping is fixed in writing before kickoff. What moves a takeover quote most is that clean-checkout result, which is why we don’t price delivery work until the audit is done. To scope it against real web application development work, send us the repository and the contractand we’ll tell you which of the three verdicts it is.
The compressed sequence
- Inventory every account and record who actually owns it.
- Create the destinations, mirror the repos, restore a dump.
- Read the assignment clause and the third-party licences.
- Give notice.
- Commission the audit as six named deliverables, not a review.
- Take the verdict the evidence supports, including rebuild.
- Ship one small change before planning a roadmap.
In most cases the outgoing agency is not the risk. Entropy is. The checklist works because it converts a relationship you were relying on into artefacts you hold.