We will say this as an outsourcing firm ourselves, because it would be dishonest coming from anyone else: most bad outsourced code is not bad because it was written far away. It is bad for specific, knowable, structural reasons — and those reasons tell you exactly how to assess what you have inherited, how to fix it, and how to buy the next round of work so it doesn't happen again. This is the practitioner's version, not the marketing one.
Fixing inherited outsourced code is a four-step job. (1) Understand why it went bad — nearly always the commercial model (a fixed-bid race to the bottom with no review, tests, docs or continuity), not the map. (2) Run a triage audit before you commit to any deadline: does it build on a clean machine, are there tests, is the dependency and security health sound, are there secrets in the code, is the framework still supported, is the data model sane, do the licences clear? (3) Stabilise first, then make the fix-vs-rewrite call on evidence — refactor incrementally where the foundations are sound, reset only where they are not. (4) Buy the next round differently: own the repository, bill on milestones, make review and tests deliverables, and keep a senior engineer on your own clock. Honest and accountable outsourcing is a real thing — it just looks nothing like the lowest bid.
"Offshore equals bad code" is a lazy explanation that lets the real culprit off the hook. Plenty of excellent software is written in Lagos, Nairobi, Kraków and Bangalore; plenty of terrible software is written in London and San Francisco. What actually predicts bad code is the commercial structure the work was bought under. Each of the drivers below is a choice about incentives, and each leaves a recognisable fingerprint in the codebase.
| Structural driver | What it produces in the code |
|---|---|
| Fixed-bid, lowest-price race | When the job is won at the floor price, every hour spent is margin lost. Tests, error handling, input validation and accessibility — everything invisible in a five-minute demo — is quietly cut, because none of it is what got the bid accepted. |
| No code review | One person's blind spots become the permanent architecture. Nothing forced a second pair of eyes over a single line, so the same misunderstanding is repeated consistently across the whole project — which can even make it look deliberate. |
| No automated tests | Nobody — including you — can change anything with confidence. Every fix risks silently breaking something else, so the codebase ossifies: cheap to write once, expensive to touch ever again. |
| No documentation | The knowledge of why anything works lives entirely in one head. The moment that person moves on, the code becomes an archaeology dig for whoever inherits it. |
| No continuity | The person who built it is not the person who maintains it. A chain of short-lived freelancers, each patching over the last, produces a codebase with no single coherent design and nobody who understands the whole. |
| No accountability | Anonymous, one-off work carries no reputational cost for shipping something that merely appears to work. There is nobody to come back to in three months, and everyone involved knew it from the start. |
Distance and timezone gaps are real, but they are amplifiers, not causes: they make a weak process harder to catch early. Fix the process — the subject of the last section — and the geography stops mattering. This is not us defending offshore; it is us being precise about what went wrong, so you fix the right thing.
The most expensive mistake with inherited code is committing to a roadmap before you know what you are standing on. Run this triage pass first. Each item is a blunt yes/no signal; together they tell you whether you have a codebase to build on or a liability to contain. Do it on a clean machine — a fresh VM or container — because that is where the undocumented steps and hidden assumptions surface.
Procedures last verified July 2026
| Check | How to run it | A bad sign |
|---|---|---|
| Does it build? | Fresh clone on a clean machine, install strictly from the committed lockfile, build and run — using only what is in the repository. | It only builds on the original developer's laptop, or needs files nobody can produce. |
| Are there tests? | Find the test suite, run it, read what it covers. The question is not just "does it pass?" but "does it test the paths that make money?" | No tests at all, or a token handful that assert 2 + 2 = 4 to make a coverage badge green. |
| Dependency & security health | Run the ecosystem audit — npm audit, pip-audit, composer audit — and triage findings by exploitability, not raw count. | Dozens of high-severity advisories, or dependencies years past their last release. |
| Secrets in the code | Scan the whole git history, not just current files, with gitleaks or trufflehog. Anything found must be rotated at source, not merely deleted. | Live API keys, database passwords or private keys committed anywhere in history. |
| Framework currency | Check the language runtime, framework and major libraries against their support timelines. | A framework or runtime already past end-of-life, receiving no security patches. |
| Data-model sanity | Inspect the schema, the migration history and the constraints. Is there a real, versioned data model, or an accretion of columns? | No migrations, no foreign keys, duplicated truth across tables, JSON blobs standing in for structure. |
| Licence check | Run a licence scanner (licence-checker, pip-licenses or an SCA tool) over the full dependency tree, and watch for large verbatim code blocks. | Copyleft (GPL/AGPL) dependencies inside proprietary code, or purchased assets under a licence tied to the old developer. |
If access itself is still contested — accounts you don't own, a developer who has gone quiet — do the transfer and rotation groundwork first. Our handover checklist for taking over another developer's code covers that stage step by step, including what to do when the handover turns hostile.
Every engineer's first instinct on opening someone else's messy code is "burn it down and start again." Resist it until you have facts. You cannot fairly judge a building while it is on fire, so stabilise before you decide: get it building on a clean machine, rotate the secrets, add tests around the handful of flows that actually earn money, and make one clean deploy under your own credentials. Only from that footing is the fix-vs-rewrite call an engineering decision rather than an emotional one.
And weight the scales honestly. A full rewrite feels clean, but it quietly throws away every edge case the old code learned the hard way — the second-system effect is where rescue projects go to die a second time. Where the foundations are sound, an incremental refactor almost always wins: a strangler-fig migration replaces the code a slice at a time while the product keeps running and earning.
If the codebase turned out to be genuinely abandoned rather than merely rough, our companion guide on how to finish an abandoned app walks through the same decision at project scale.
Everything in Step 1 was a consequence of how the work was bought. Change four things and you change the outcome — and none of them require bringing development in-house:
Here is the honest part, since we are an offshore team ourselves. "Accountable offshore" is not a slogan; it is a specific set of arrangements — the same four above — and you should hold any supplier, us included, to them. What makes it checkable in our case is that we publish our prices. Our Open Price Book is a versioned, fixed set of bands you can read before you ever speak to us, and we bill on milestones — you pay for delivered, accepted work. A price you can read and a payment tied to release are far harder to game than any promise, which is exactly why we lead with them rather than with claims about who we are.
| If you are here to… | Typical band (ex VAT) |
|---|---|
| Stabilise an inherited codebase (rescue takeover) | £8,000–£12,000 to take it over; completion priced from the project bands |
| Rebuild a validation-stage web MVP | £12,000–£20,000 |
| Build a standard SaaS MVP | £16,000–£30,000 |
Prices published from our Open Price Book (v1.0 · July 2026 · next review October 2026). All prices exclude VAT.
Book a free 30-minute call with a senior engineer — in your business hours. We'll run the triage checklist against your actual project, give you a straight fix-or-reset read, and put a published price band against whatever comes next. No obligation, and no answer dressed up to win the work.
Book a free scoping call →