How to rescue a stalled software project in the first two weeks
Rescue a stalled project in a fixed order: get it building from a clean machine and reclaim the accounts in days 1–3, map what exists in days 4–10, and hold the work to a written plan you can check on staging from day 14.
In short
- Start a rescue by getting the project to build and deploy from a clean machine and listing every account it depends on. Bug fixes and features wait, apart from urgent ones with a rollback ready.
- Four security checks belong in days 1–3: rotate exposed secrets, scan dependencies for known vulnerabilities, restore a backup and query it (an AWS Well-Architected best practice), and list who has admin access.
- Days 4–10 map what works, what half-works and what is missing, list the versions that no longer get security updates, and sort the code into keep, repair, rewrite and remove.
- Decide rescue or rewrite part by part, after the map. Sound foundations lean towards rescue. A full rewrite is the exception, and its clearest case is one job split across several systems that a single system can replace.
- The two weeks end with a written plan of weekly milestones, each one something you try for yourself on a staging link.
Every rescue we take on starts with the same rule: no bug fixes and no new features until the project builds and deploys from a clean machine, urgent fixes aside. When a launch is already late, that rule can look like one more delay, but until the project builds, no one can say how far from done it is.
To rescue a stalled software project, establish the facts before you touch bugs or features. Days 1–3 get it building and deploying from a clean machine and list every account it depends on. Days 4–10 map what works and where the data lives. By day 14 you have a written plan with weekly milestones you can try on a staging link. Our software project rescue service runs in that order.
1. A stalled project needs a rescue when pushing harder stops moving it
Several of the signs below together mean it’s time to stop adding features and take stock. One sign alone can happen on a healthy project. Each sign, and what tends to sit behind it:
- Demos keep slipping: the team reports work as nearly done but rarely shows it running, so problems surface late.
- Estimates keep moving: scope kept growing and nothing came out; a minimum lovable product cuts scope back to one job done completely.
- There’s no staging environment: every change goes straight to production, and users meet the mistakes first.
- One person holds the setup knowledge: when that person is away nothing deploys, because no one wrote the steps down.
- Accounts are in the vendor’s name: an account the vendor opened to get started stays in its name until someone moves it, so the vendor still controls access and renewals.
- Bugs reappear after fixes: without automated tests, nothing catches a fix that breaks something else.
Most of these signs are about how the project is run, from demos to accounts, so the two weeks below spend as much time on accounts, backups and demos as on code.
2. Quick fixes and full rewrites both skip the facts
When a project is late, the pressure is to start fixing at once. Pick the most visible bug and ship a fix, so there’s something to show. On an unfamiliar codebase a fix in one place can break something elsewhere, and confidence drops further. If the live system is failing now, fix only what’s urgent, one change at a time, each with a rollback ready (a tested way to undo it).
Throwing everything away backfires for a different reason. Old code holds business rules and bug fixes that no one wrote down, and a rewrite has to rediscover each one. A rewrite is sometimes still right, and the rescue-or-rewrite signals in section 6 show when.
So the first two weeks go on finding out what’s there, in three stages:
3. Days 1–3 get it running and reclaim the accounts
Before any bug fix or feature, get the project building and deploying from a clean machine, one that has never had the project on it. Apart from urgent fixes, the only changes in these three days are the ones needed to build, deploy and secure it. If setup takes all three days, that time isn’t wasted: any new team would have spent it too.
Setup comes before bugs because it shows what the code alone can’t: which secrets are hard-coded (passwords and keys written into the code itself), which steps live only in the previous developer’s head, and which services the product depends on that no one listed.
What “running” means
“Running” has a fixed meaning here, and all five parts count:
- Builds: the code builds from the repository with no manual edits.
- Database: a script creates a fresh database and fills it with test data.
- Runs: the app runs locally and connects to the services it needs.
- Deploys: it deploys to a staging environment.
- Written down: someone has written every step down, so another developer can repeat it.
Accounts and access
At the same time, list every account the product relies on: code hosting, cloud hosting, the database, domain and DNS, email sending, the payment gateway, app store accounts, maps and analytics. For each one, ask two questions: is it registered to your company, and who holds the two-factor codes? When the answer is a vendor or someone who has left, the fix depends on the service:
| Service | What to check | What to do |
|---|---|---|
| Domain and DNS | The registrant and the registrar account | Transfer it to the company if a vendor or former staff member holds it |
| Cloud hosting | The account owner and the card that pays | Move ownership and billing to a company account |
| Database | The account it runs under, and who holds the backups | It moves with the hosting; take a fresh backup before any move |
| App store | The account holder and the admin roles | Remove admins who have left, or transfer the app to the company |
| Payment gateway | The merchant account holder and the API keys | Rotate the API keys once the company holds the account |
| Email sending | The sender account and the domain verification | Open a company account if needed, and verify the domain again |
Any account that belongs to the previous vendor or to someone who has left is a risk. When the cloud account sits in a former developer’s name, the invoices go to that person’s card and the two-factor codes go to their phone, so the first sign of a failed payment can be the site going down. Moving that account can be the most urgent job of the first week, though it involves no code.
What to ask the previous developer for
Taking over a software project from another developer is far easier with their help. If they still reply, ask in writing for this handover checklist:
- The repository with its full history: a zip of the latest files loses every past change and who made it.
- A recent database dump: it needs the schema and the migration scripts that build and change it.
- Credentials and two-factor devices for every account: a password is little use if the codes go to a former employee’s phone.
- Ownership of the hosting, DNS and app store accounts: these transfer to your company; a shared login isn’t ownership.
- Open issues: the bug list, the backlog and anything promised but not delivered all go in.
- Deployment notes: a note of how a release goes out, what runs on a schedule and what’s done by hand.
Whatever’s missing goes on the list of risks.
Security checks that cannot wait
Four security checks belong in the first three days, before any feature work:
- Check dependencies for known vulnerabilities: on GitHub, Dependabot alerts flag a vulnerable dependency once they’re switched on for the repository. Wherever the code is hosted, OWASP Dependency-Check compares a project’s dependencies with publicly disclosed vulnerabilities from the command line or the build, and for Node projects
npm auditasks the registry for a report of known vulnerabilities, nested dependencies included. Fix anything critical now and leave the wider version check to days 4–10. - Restore a backup and query it: the AWS Well-Architected reliability guidance makes “periodic recovery of the data to verify backup integrity and processes” a best practice, and says to restore backups in a testing environment and “run tests on data content and integrity” (Reliability Pillar). Until someone has restored a backup and queried it, no one knows whether it can be used.
- List who has admin access: note who has administrator access to each account, remove anyone who no longer needs it, turn on two-factor sign-in, and stop anyone working directly on production data.
- Rotate exposed secrets: replace any key, password or token found in code, commit history, chat or tickets, and revoke the old one.
If the code is on GitHub, its secret scanning searches the entire Git history on every branch for known types of secret. On public repositories it runs automatically and reports each match to the service provider that issued the secret, which decides whether to revoke it, issue a new one or contact you. Alerts in your own repository, private ones included, need GitHub Enterprise Cloud with a GitHub Advanced Security licence. On another host, use its secret detection if it has one, or search the commit history yourself.
Rotation comes before any cleanup of the history. GitHub’s guide to removing sensitive data says that once a commit has been pushed, “you should consider any sensitive data in the commit compromised”, because removing it “doesn’t resolve its initial exposure, especially in existing clones or forks of your repository”. Once the old key is revoked, rewriting the history to remove it is optional.
4. Days 4–10 map what works, what half-works and what is missing
With the project running, or as close to running as it gets, work through it feature by feature and write down what you find. Three things to record per feature:
- State: note whether it works, half-works or is missing.
- Data: note where its data lives and who can read or change it.
- Group: put it in one of the four groups below.
How we sort the code
Four groups are enough, and they keep the plan readable for people who don’t read code:
| Category | What it means | Usual action |
|---|---|---|
| Keep | Works, readable, has a clear purpose | Leave alone, add tests where useful |
| Repair | Mostly works, with known bugs or gaps | Fix in place during the plan |
| Rewrite | Unreliable, unreadable or unsafe | Replace, in small pieces |
| Remove | Unused or abandoned code | Delete, after confirming nothing calls it |
The groups go into the plan as they are, so the summary of the current state reads as a list of parts and what happens to each.
Old or unsupported versions
List the runtime, framework and library versions, and check which still get security updates. The OWASP (Open Web Application Security Project) Top 10 for 2021 puts vulnerable and outdated components sixth. You are likely vulnerable, it says, “if the software is vulnerable, unsupported, or out of date”, from the operating system and the database down to “runtime environments, and libraries”. Its prevention list starts with removing unused dependencies and keeping an inventory of every component’s version (OWASP Top 10:2021, A06).
The same page expects fixes and upgrades “in a risk-based, timely fashion” and says to watch for components that are unmaintained or “do not create security patches for older versions”. So the question for each part is whether it still gets security fixes, and a newer release alone doesn’t put an upgrade in the plan. Most out-of-support parts go into the plan as staged upgrades, so the product keeps running. Where an upgrade would replace most of the code, the rescue-or-rewrite table in section 6 applies.
The data matters more than the code
A rewrite can replace code, but it can’t recreate data. Use the backup you restored in days 1–3 to check the database structure and look for inconsistent or duplicated records. Then find out which other systems read or write the data, because each one constrains any rewrite. The same restored backup can double as test data for the clean-machine build.
Talk to the people who use it
The code shows what the previous team built; the users show what they needed. Spend time with the people who will use the product, or who tried earlier versions, and ask where it failed them. If the spec and what people needed have drifted apart, the users are the ones who can show you the gap.
5. Days 11–14 produce a plan you can check on staging
The last four days turn everything found so far into a written plan you can hold the work to. The test for each milestone is that you can try it on staging. Anything you can only read about in a report counts as a status update.
What the plan contains
The plan has five parts, in this order:
- Current state: the summary lists each part under keep, repair, rewrite or remove.
- Risks: the list ranks every risk found so far and gives each a response.
- Weekly milestones: each one is something you can try on staging.
- Deferred work: it says what waits and why.
- What the team needs from you: it lists the decisions, access and test data needed from you, each with a date.
Each milestone names something that works and how you check it yourself. For three kinds of milestone, the wording and the check look like this:
| Kind of milestone | How it’s written | How you check it on staging |
|---|---|---|
| A broken flow works again | “Password reset works again” | Request a reset email, then sign in with the new password |
| A part moves to a supported version | “Checkout runs on a supported framework version” | Place a test order from basket to receipt |
| Data is repaired | “Duplicate customer records merged” | Find a merged customer and open their order history |
The plan stays short, because you check it against staging at the end of each week.
6. Sound foundations lean rescue; a full rewrite is the exception
Decide rescue or rewrite part by part, once you’ve tried to get the project running and mapped it. A part leans towards rescue when its foundations are sound, and towards a rewrite when the foundations are the problem:
| Signal | Leans rescue | Leans rewrite |
|---|---|---|
| Builds from a clean machine | Yes, once missing steps are written down | No: parts are lost for good |
| Data model | Sound, even if the code is messy | Doesn’t fit how the business works |
| Framework | Still supported and patched | Out of support; upgrading means replacing most of it |
| Tests | Some exist, or can be added | None, and the code is too tangled to add them |
| Business rules | Only in the code, so a rewrite risks losing them | Written down, so a rewrite can be checked against them |
Packaged systems raise a different question. When customisations to an ERP (enterprise resource planning) or CRM (customer relationship management) system have piled up until upgrades fail, the choice is which customisations to keep and which to move back to the vendor’s standard flow or its settings.
When a rewrite is the right call
The table’s signals miss one case for a rewrite, because the trouble sits in the shape of the system: a single job split across several systems, so the people doing it type the same details into each one in turn. The map from days 4 to 10 shows it as the same field entered in more than one place, or a spreadsheet or chat that carries details from one screen to the next.
When each system works and the trouble is the job split across them, there are three options:
- Repair each system: the bugs get fixed but the re-typing stays, because the split stays.
- Connect them: an integration layer passes the details between them, which removes some re-typing and adds one more thing to maintain.
- Replace them with one: a single system covers the whole job, with the data migrated across.
Only the third removes the split, so the rewrite case is clear when the problem sits between the systems. A stalled project with a sound data model and messy code on top is a different case, and it leans rescue.
Otherwise, the case against starting over holds. Joel Spolsky made it in 2000, about Netscape’s decision to rewrite its browser from scratch (Things You Should Never Do, 6 April 2000):
They did it by making the single worst strategic mistake that any software company can make: They decided to rewrite the code from scratch. […] The idea that new code is better than old is patently absurd. Old code has been used. It has been tested. Lots of bugs have been found, and they’ve been fixed.
We agree with him about code that works. But a stalled project also has code that doesn’t, and those are the parts that sorting the code marks Rewrite; the plan replaces them in small pieces while the rest keeps running.
7. A few first-week habits make a project rescue much less likely
Each sign in section 1 has a habit that makes it much less likely, and all seven below fit in a project’s first week:
- Keep the code in your company’s own repository from the first commit.
- Register every service to the company and add the developer as a user.
- Have someone other than its author test the setup guide on a clean machine.
- Agree on a staging demo every week before work starts.
- Fix the scope for each phase and list what was deferred.
- Ask for automated tests on the main flows.
- Talk directly to the person building the product.
Our 8-week build follows several of them. The accounts go under your company’s name, you talk to the technical lead who builds the product, each week of the build ends with a demo on staging, and week 8 hands over the source code and the documentation.
8. Takeaways
Get it running before you judge it. Until the project builds from a clean machine, every estimate is a guess, and the three days it takes to get there are days any new team would spend anyway.
The accounts are worth more than the first fixes. A domain, a hosting account or an app store listing in a former vendor’s name can take the product down faster than any bug, and moving them involves no code.
Four groups are enough to describe any stalled codebase to someone who doesn’t read code. Keep, repair, rewrite and remove give a finance director and a developer the same vocabulary, and the plan reads as a list of parts and what happens to each.
A milestone is something you can try on staging. We’d rather show one working password reset on a link than report that checkout is 80% done.
A full rewrite is the exception, and its clearest case is one job split across several systems. A single system for the whole job ends the re-typing, and the data still moves across from the old ones.
If your project shows several of the signs in section 1, our software project rescue service runs these two weeks and then finishes the work on the plan. Tell our technical lead where it stands and we’ll reply within 24 hours.
Frequently asked questions
How long does it take to rescue a stalled project?
The first two weeks produce a written plan: days 1–3 get the project running, days 4–10 map it, and the plan is ready by day 14. How long the fixes take depends on what those two weeks find. They’re scheduled as weekly milestones, each one shown on a staging link, so the length of the whole job is known on day 14, once the map exists. Urgent fixes don’t wait for the plan: anything failing on the live system is fixed one change at a time, each with a rollback ready.
How do you take over code another agency wrote?
With the same first two weeks as any rescue: build it from a clean machine, move the accounts into your company’s name and map what exists before changing anything. Bugs and features wait for the plan, urgent fixes aside. Anything the previous agency hands over, such as the full repository history, a database dump and deployment notes, shortens that work.
What if we only have the live server and no source code?
It depends on the stack. Code in interpreted languages such as PHP or Python is often readable on the server; a compiled app is much harder to work back from and may need parts rebuilt. Either way, moving the accounts into your name and copying the data come first, and how much code is recoverable only becomes clear once we’ve examined the server.
What if the previous vendor refuses to hand over access or code?
Go account by account, because providers generally deal only with the account holder: the domain registrant, the app store account holder, the cloud billing owner or the repository’s organisation owner. Anything registered to your company can usually be reclaimed through the provider’s own process, and we help you work through each one. For accounts or code in the vendor’s name, start from the intellectual property and handover clauses in your contract, and take legal advice if it becomes a dispute.
Can the live system keep running during the first two weeks?
Normally, yes, because the assessment works on copies: a clean machine, a restored backup and a staging environment. A few changes do touch the live system: urgent fixes with a rollback ready, rotated keys, and transfers of the domain, hosting or app store accounts. Schedule those for quiet hours rather than assume zero downtime.
Should we rescue a stalled project or rewrite it from scratch?
Decide part by part, once the project builds from a clean machine and has been mapped, because before that no one can judge it. A part leans towards rescue when its foundations are sound: it builds once the missing steps are written down, the data model fits how the business works, the framework is still supported and patched, and tests exist or can be added. It leans towards a rewrite when the foundations are the problem, such as a framework out of support or a data model that doesn’t fit the business. Code that works is worth keeping, because it has been tested by use and holds business rules no one wrote down. A full rewrite is the exception. Its clearest case is one job split across several systems: one system that replaces them all, with the data moved across, ends the re-typing the split causes.