Inherited and abandoned apps are the norm, not the exception

If you have just taken over a half-built product from another agency, a departed developer or a founder who ran out of runway, you are not in an edge case. The Standish Group's CHAOS Report 2024 found 19% of software projects are cancelled outright and a further 52% land late, over budget or missing key features. Harvard Business Review's analysis of large IT projects puts the average overrun at 27%, with a long tail running past 200%.

The market makes this inevitable. Focus Digital's 2025 Agency Churn Report puts average client lifespan on project-based agency work at 24 months, with 42% annual churn. Hyve Managed Hosting's 2024 skills gap survey found 81% of UK businesses report being negatively affected by IT and tech skills shortages. Developers move on, agencies rotate, founders pivot. The codebase stays.

The useful question is not "how did this happen to us" but "what do we do on Monday". The answer, in almost every case, is the same: audit first, code second. Everything in this piece flows from that.

Secure everything before you touch a line of code

The most common way a rescue stalls is not technical. It is that the incoming team cannot get into the system. Before anyone opens an editor, protect the assets and access the business still controls.

Confirm ownership and working access to:

  • Source repositories, including any private forks and CI configuration.
  • Cloud accounts (AWS, GCP, Azure), hosting, container registries.
  • Domains, DNS, TLS certificates and email records.
  • Databases, object storage, backups and their retention policies.
  • Payment, analytics, error tracking and third-party integrations.
  • Production logs, incident history, invoices, contracts, design files and exports.
  • The latest known working build, tagged and stored somewhere the new team controls.

Chase the paperwork too. Who owns the code under the previous contract? Which third-party libraries are commercial and whose licence key is in the .env? A rescue that skips this step tends to discover, three weeks in, that the previous vendor still holds the DNS and is not returning emails.

Working from a stable snapshot

Give reviewers a stable snapshot: a tagged release or the current staging branch, with read-only access. Keep environment configuration separate. Audit systems should never carry live production credentials, and the audit itself should not require a deploy. If the only way to run the app is on the original developer's laptop, that is the first finding.

Do not let anyone push a fix yet

The temptation to "just deploy a small patch" during handover is strong and almost always regretted. Until the audit is done, you do not know what a small patch touches. Freeze non-urgent changes and record any hotfixes in the incident log.

What a proper audit actually covers

Magnifying glass examining code layers with security locks and highlighted vulnerabilities

An audit is not a README and a vibes-based summary. It is a written, risk-ranked report on the state of the codebase, with evidence. If you cannot point at the specific file, query or dependency behind a claim, that claim does not belong in the report.

Code quality, architecture and duplication

Reviewers assess whether another developer could step in without days of reverse engineering. Consistent naming, sensible module boundaries, business logic separated from the UI. When business rules live inside React components or Blade templates, they cannot be tested properly or reused in an API, and every future change carries more risk than it should.

Duplication is one of the few things worth benchmarking. KPI Depot's guidance for legacy codebases is below 5% duplication optimal, 5 to 10% acceptable, above 10% requires attention. Above 15% and you are looking at a refactor rather than a tidy-up.

Security, dependencies and test coverage

Auditors look for hard-coded secrets, missing input validation, weak session handling and outdated libraries. OWASP and CERT are the usual reference points. Security-critical areas (auth, encryption, access control, anything touching personal data) get manual review, not just a scanner pass.

Dependencies are where most real-world risk hides. Sonatype's 10th Annual State of the Software Supply Chain (2024) found 80% of application dependencies stay un-upgraded for over a year, and 95% of the time a vulnerable component is consumed, a fixed version already exists. The gap between "a patch is available" and "a patch is applied" is the exposure. npm audit checks JavaScript dependencies against the GitHub Advisory Database; Composer covers PHP; Mend.io works across ecosystems.

Test coverage gets measured, not estimated. Real numbers, flakiness analysis, CI duration baseline, and a plan to stabilise the suite. Stack Overflow's developer surveys have consistently shown developers spend roughly 13.5 hours a week on technical debt, and that figure rises sharply when there are no tests to catch regressions.

Performance profiling

P95 and P99 latency, memory profile, slow query log, named bottlenecks worth fixing. AnyforSoft's published case study on an inherited front end reported PageSpeed Insights hitting the top performance band after unused JavaScript was removed. That kind of specific before-and-after is what a performance section should produce, not "the site feels quicker".

The tooling: what scanners find and what they miss

We use scanners because they catch the boring stuff cheaply. We do not rely on them because they miss the interesting stuff entirely.

Named tools in our own audit workflow:

  • SonarQube for static analysis, code smells and quality gates. Its PASS/FAIL checks slot into CI to stop regressions once you start fixing things.
  • Mend.io for dependency scanning. Their differential scanning approach only checks new changes rather than the whole repo, which keeps mean time to repair down once you are shipping again.
  • CAST Highlight for portfolio-level analysis when there are multiple applications in scope. It gives a data-driven snapshot across code quality, cloud readiness, open source risk and technical debt.
  • NDepend for .NET codebases.
  • npm audit and Composer audit for JavaScript and PHP dependency trees.
bash
# A sensible first pass on a Node codebase, before any code changesnpm cinpm audit --productionnpx sonar-scannernpx depcheck

What scanners miss: intent. A tool cannot tell you that the Order model is doing three jobs because the original developer was migrating away from a legacy schema and never finished. It cannot tell you that the "temporary" cron job is now the only thing keeping billing accurate. Those findings come from a senior engineer reading the code with the business context in hand. Tools produce noise as well as signal, and a good auditor spends real time deciding which findings are worth fixing and which are cosmetic.

Get plain-English guides like this in your inbox.

One short email a month. WordPress, Shopify, SEO, no fluff. Unsubscribe in one click.

We never share your email.

AI-generated codebases: a distinct rescue category

Since 2024 we have seen a new pattern often enough to name it: products built quickly with AI coding tools that stall the moment they meet real users. The demo worked. Then the app hit scale, or an audit, or a second developer, and nobody could explain how it worked.

The audit process is the same. The failure signatures are different:

  • No coherent architecture. Files that each look reasonable in isolation but do not agree with each other on where state lives.
  • Very low or zero test coverage, because the tests would have slowed the demo down.
  • Duplicated logic across routes, because the assistant regenerated similar code rather than extracting shared modules.
  • Silent dependency sprawl. Packages added to solve one prompt and never removed.
  • No single human who understands the whole system.

AI coding tools are genuinely fast at producing something that runs. That is why so much gets shipped without tests, without a coherent architecture, and without anyone who understands the whole. It is classic technical debt, just accrued faster than a human team could manage it.

What we tell founders in the first call

Rescue is usually possible. Expect more of the risk-ranked report to point at re-architecting core modules than at cosmetic refactoring, and expect to invest in tests early so the rebuild does not repeat the same trick.

Rescue, refactor or rebuild: using the audit to decide

Once the audit report is on the table, the decision framework we use covers seven strategies per component: rehost, replatform, refactor, re-architect, rebuild, replace, retire, retain. You do not pick one for the whole product. You pick one for each meaningful component.

A rough guide:

  • Retain the parts that work and are not blocking anything. Do not fix what is not broken.
  • Refactor modules with sound structure but messy code. Cheap, high value, low risk.
  • Re-architect anything where business logic is tangled with the UI, or where scaling is blocked by design.
  • Rebuild the pieces where the cost of understanding the existing code exceeds the cost of writing it again with tests.
  • Replace with an off-the-shelf tool where a commodity solution exists. Our take on that trade-off lives in build vs buy: when custom software beats off-the-shelf.
  • Retire anything nobody uses. You would be surprised how often this applies.
  • Rehost or replatform if the underlying infrastructure is the real problem and the code is fine.

This is where we usually plug in our custom software and SaaS development work: taking the risk-ranked report, agreeing the strategy per component with the client, and then sequencing the fixes so the product is usable throughout, not just at the end.

If the audit reveals the original scope was the real problem (the product tried to do too much before finding its users) it is worth pausing to re-plan properly. Our approach to that is in how to scope an MVP that ships in weeks, and for larger strategic resets we run how to run a two-week digital strategy sprint.

What a realistic rescue timeline looks like

For a typical stuck build, plan on roughly twelve weeks:

  • Weeks 1 to 2: stabilise production, secure access, run the audit, produce the risk-ranked report.
  • Week 3: re-plan. Agree the strategy per component, sequence the work, set weekly demos.
  • Weeks 4 to 12: execute in weekly increments. Fix the highest-risk items first, ship visibly, keep the test suite growing as you go.

Larger or more damaged products take longer, but the arc is the same. Weekly demos matter more than usual in a rescue, because everyone involved (client, engineers, previous stakeholders) needs to see progress on the actual system, not on a slide.

What good looks like at week four

By the end of week four you should have: a green CI pipeline, a merged snapshot of the audit findings, at least one production risk closed, and a written plan the whole team agrees with. If any of those is missing, stop and fix that before adding features.

The strongest argument for auditing before fixing is not technical, it is financial. McKinsey's technology transformation research and the CHAOS Report both point the same way: challenged projects that keep running without a structured intervention cost more to rectify later, even when the scope has not changed. The audit is the cheapest thing you will do in the entire rescue. Everything else depends on it.

If you have inherited something and are not sure whether it is worth saving, see how we approach rescue and rebuild projects and get in touch. We will tell you honestly whether a rescue makes sense, or whether the audit is going to point at rebuild.