Signed off, paid for, and still falling over
The agency ran a final demo, you signed the acceptance form and they sent the last invoice. Within weeks the problems started. Orders go missing now and then. A report shows different numbers from the database. The mobile app crashes for some users and not others. Every support ticket gets a fix, and each fix seems to break something else.
Now the agency is slow to respond, or wants a new contract to keep fixing things they built. Your team has stopped trusting the system and is keeping its own spreadsheet on the side, just in case.
Why broken delivery is rarely just bad coding
Poor code is usually a symptom. The causes tend to sit further back.
- The project was sold at a fixed price and the scope grew, so the last stretch was rushed to protect the margin.
- Testing meant clicking through the happy path in a demo, not checking what happens with bad data, slow networks or two people editing the same record.
- Junior developers did most of the work without anyone senior reviewing it.
- There was no staging environment, so changes were tried on the live system.
- Requirements lived in emails and calls, so nobody could say what correct behaviour was.
Knowing which of these applies matters, because it changes what the fix is. Untested edge cases need tests. A broken data model needs a redesign of one part. Missing requirements need a conversation, not code.
What it is costing you now
The direct cost is time: staff checking outputs by hand, support tickets, lost orders, customer apologies. The indirect cost is harder to see. People stop using the system for anything important, and the investment turns into another tool that runs alongside the spreadsheet rather than replacing it.
There is also a decision cost. Without an independent view you cannot tell whether you are one sprint of fixes away from a stable system or pouring money into a foundation that will never hold.
How we stabilise inherited code
- Get everything under your control: repository, hosting, database, domain and third-party accounts, all in your name, with old credentials rotated.
- Build it and run it outside production. A copy on a staging server with anonymised data lets us reproduce faults without risking live customers.
- Audit the code and architecture. We look at structure, data model, error handling, security basics, dependencies and how it is deployed. You get a written report that says what is sound, what is fragile and what is dangerous, in plain language.
- Add visibility. Error tracking (for example Sentry) and structured logs go in early, so faults show up with a stack trace instead of arriving as vague complaints.
- Write tests around what breaks. Before touching a failing area, we write tests that capture how it should behave. Fixes then stop reintroducing old bugs.
- Fix by risk, not by noise. Data loss and security problems come first, then faults that stop work, then annoyances.
- Replace only what cannot be made reliable, one piece at a time, with the rest of the system kept running.
| Audit finding | Typical response |
|---|---|
| Missing validation and error handling | Add them, with tests |
| Outdated or vulnerable dependencies | Planned upgrade with regression testing |
| Business logic copied in several places | Consolidate into one tested module |
| Data model that cannot represent real cases | Redesign that part with a migration plan |
| No deployment process | Scripted deployments with staging first |
After the dust settles
Your team gets a system that behaves the same way twice. Errors are caught and logged before a customer phones. Changes go through staging and tests before they reach users, so a fix to invoicing no longer breaks the dashboard.
You also get something you probably did not have from the original agency: documentation of how the thing works, how to deploy it and where its weak points still are. Whoever maintains it next, us or someone else, starts from that.
Is this what you are dealing with?
- The project was signed off but faults keep appearing in normal use.
- Fixing one bug regularly creates another.
- Staff keep a parallel spreadsheet because they do not trust the system.
- The original agency is unresponsive or wants a new contract to fix its own work.
- You need an independent opinion before deciding whether to rebuild.