In Vinland Saga, Thorfinn spends the first part of the story wanting to destroy. Then he understands that revenge builds nothing, and the rest of the tale shows him clearing land, sowing, building. Same character, energy turned around.
Taking over an existing project demands exactly that reversal. The first reflex, faced with someone else's code, is to want to raze it. That's almost always the wrong decision.
A good half of my engagements consist of taking over a product started by someone else — developer gone, agency at contract end, contractor no longer answering. Here's the method I eventually settled on.
Day 1: make it run, judge nothing
The first objective is singular: get the project starting locally, without changing one line of logic.
It sounds trivial. It often takes the whole day. Undocumented environment variables, incompatible Node version, a database to seed, a third-party service nobody has the key for.
I note everything that blocks in a file as I go. That file becomes the future README, and it's already a delivery of value: the next developer will take twenty minutes where I took eight hours.
Absolute rule for that day: no judgement. No "this is badly done", no opportunistic refactoring. You don't understand anything yet. What you take for incompetence is sometimes a constraint you don't know about.
Day 2: map it, don't read it
You don't read a project line by line. You draw its map.
What I look for, in this order:
The entry points. HTTP routes, screens, scheduled tasks, webhooks. That's the surface through which the outside world touches the system.
The data model. The database schema says more than the code. Table names, foreign keys, columns added in a hurry tell the story of the product and its pivots.
External dependencies. Which third-party services? What happens when they go down? That's where the future outages hide.
The money path. If there's payment, I trace it end to end. It's always the most sensitive and worst-tested area.
I produce a diagram — often by hand, photographed. It supports the first real discussion with the client.
Day 3: find the thread of the story
git log is the most underrated document of an inherited project.
What I look at:
- The rhythm. Regular commits, then a six-month hole, then a frantic restart: the product was abandoned then relaunched under pressure. That explains a lot of inconsistency.
- Panic messages.
fix,fix2,urgent fix,revert urgent fix. Those sequences mark the areas that hurt in production. They're the areas to understand first. - The authors. Three different styles in the same folder explains why conventions diverge.
A project has a history, and the code is its sediment. Reading it without its history is judging a choice without knowing the constraint that produced it.
Day 4: measure instead of opining
This is the day that changes the conversation with the client.
As long as you say "the code quality is poor", you're issuing an opinion that can be argued with. When you show numbers, the discussion becomes factual:
- Test coverage — often near zero, but you need the figure.
- Outdated dependencies and vulnerabilities —
npm audit,go list -m -u, whatever the stack's equivalent is. - Build and startup time — direct impact on future delivery speed.
- Bundle size — direct impact on users.
- The most-modified files, crossed with the longest. The intersection gives the hot spots: large and frequently touched, therefore risky.
That last crossing is the most useful. It objectively designates where to invest, with no debate about taste.
Day 5: propose a plan, not a rewrite
This is where most handovers fail.
The developer, after four uncomfortable days of discovery, announces: "it all needs redoing". The client hears: "the six months and the money invested are lost". The relationship starts in conflict.
And the worst part is that a full rewrite is nearly always a mistake. The existing code, however ugly, encodes years of edge cases discovered in production. Every strange if corresponds to an unhappy client on a Thursday evening. Rewriting means paying full price for all those lessons again.
What I propose instead, in order:
- Stabilise. Whatever prevents calm delivery: reproducible environment, automated deployment, backups. No features, only foundations.
- Secure. Vulnerabilities, secrets in plain text, unprotected endpoints. Non-negotiable, before everything else.
- Test the core. Not 80% coverage: the journey that makes money, tested end to end. It becomes the safety net for everything after.
- Refactor opportunistically. You improve what you touch for another reason. Never an isolated refactoring project — it's unsellable and it drifts.
- Rewrite in pieces, only if a module genuinely deserves it, and behind a stable interface.
That plan has a decisive advantage: the client sees value from week two. A rewrite requires six months before the first visible benefit, and often fails before then.
The signals that make me decline
Not every handover is healthy. What makes me say no:
No access to anyone who knows the business. If the previous developer has gone and nobody in the company knows why the system behaves as it does, every decision becomes a guess.
A client who wants a rewrite before the audit. If they've already decided, they're not looking for an opinion, they're looking for execution. That ends badly.
No access to production. Impossible to know what's actually running. The main branch isn't always what's deployed — I've verified that the hard way.
"It's urgent, let's skip the audit." Five days of audit against a six-month engagement is 4% of the budget. Refusing them guarantees discovering the problems at the worst moment.
The underlying problem
Our profession values creation enormously and taking over very little. Conferences talk about new frameworks, not about how to inherit an Angular 8 project in production.
Yet the majority of code written in the world is maintenance code. The majority of real engagements consist of evolving what exists.
That asymmetry has a cultural cost. We train developers who know how to start and not how to continue. Who confuse "I don't understand this code" with "this code is bad". Who propose a rewrite because it's more fun, justifying it with technical debt.
There's a specific skill in reconstituting the intent behind code you didn't write. It's learnable, it pays well, and almost nobody teaches it.
The best test
A question I now ask in engagement interviews, and it reveals a lot:
"Tell me about a time you kept code you thought was bad, and why."
Someone who's never lived that hasn't yet met the real constraint. Someone who answers precisely has understood that code doesn't exist to be beautiful, but to serve someone.
This is the method I apply on engagements. If you have a project started by someone else and don't know where to pick it up, write to me — an audit fits in five days.
