Your new engineering hire spent their first week reading the codebase. Then they came to you with a list. No tests. No documentation. Hardcoded credentials. Business logic tangled into the UI layer. Copy-pasted functions with different variable names. “This is going to be a problem,” they said.
You spent $200K. The product works — mostly. Customers are using it. But now you’re looking at the system you just paid for and wondering if you bought an asset or a liability.
Here’s the first thing you need to hear: this is more common than you think. The second thing: “bad code” exists on a spectrum, and your response needs to match where on that spectrum you actually are. Don’t make a $200K decision based on a one-week impression from someone who hasn’t shipped anything in your codebase yet.
Step One: Get an Honest Assessment
Your new hire’s first impression is a signal, not a verdict. You need a structured technical audit before you decide anything.
What you’re trying to answer:
Is it bad, or is it bad-but-workable? Every codebase has rough edges. Dev shops under budget pressure make shortcuts. The question is whether the shortcuts are cosmetic (no tests, messy naming, some duplication) or structural (architecture decisions that fundamentally limit what you can do next).
Can you add features without it getting worse? This is the practical question. If every new feature requires reworking existing code, you’re paying compound interest on the debt forever. If the structure is awkward but self-contained, you can work around it.
Is it secure? Hardcoded credentials, exposed API keys, no input validation, SQL injection vulnerabilities — these are not tech debt. These are active risks. Separate the security assessment from the code quality assessment and treat security findings with urgency.
What does the test coverage look like? No tests doesn’t mean the code is wrong. It means you have no safety net when you change it. That’s different from broken — but it significantly increases the cost of everything you do next.
Get an independent technical audit if you can. Your new hire is not independent — they have incentives to justify a rewrite they can own. An external assessor will give you a more honest read.
Your Actual Options
Fix it incrementally. This is the right answer more often than people think. You don’t need a perfect codebase. You need a codebase that can evolve. If the foundation is structurally sound, you add tests as you modify code, you refactor the worst sections as you touch them, and you improve the system from the inside without stopping new development.
This works when: the architecture is workable, the business logic is mostly correct, and you have engineers who can discipline themselves to leave code better than they found it.
Rewrite specific modules. You rarely need to rewrite everything. You usually need to rewrite one or two critical modules that are genuinely blocking you — the authentication system, the billing integration, the data model at the core. Identify the specific components that are causing the most pain and rewrite those surgically while keeping the rest.
This works when: the codebase has clear module boundaries, some parts are fine, and one or two specific areas are genuinely blocking forward progress.
Full rewrite. This is almost always slower and more expensive than it sounds. “We’ll just rewrite it in six months” is one of the most dangerous sentences in software. Budget 2x the estimate, expect to maintain both systems in parallel longer than you planned, and know that the new system will have its own problems.
That said, sometimes it’s the right answer. If the data model is fundamentally wrong, if the technology stack is obsolete and blocking talent acquisition, or if security issues are too deeply embedded to excise — a rewrite may be the only viable path.
Legal action against the dev shop. Rarely worth it. Unless you have a contract with very specific acceptance criteria they demonstrably failed to meet, “the code is messy” is not a legal claim. You’ll spend $50K–$100K in legal fees and years of distraction. I’ve seen this go badly for the client more often than not. Your energy is better spent on the technical problem.
What to Do Right Now
Regardless of which direction you go, do these things immediately.
Rotate any credentials or secrets that were hardcoded. Don’t wait for the full audit. If there are exposed API keys, database passwords, or access tokens in the code, those are compromised — treat them that way.
Freeze major new feature development until you understand what you have. Adding more code to a codebase you don’t understand is how technical debt compounds into a genuine crisis.
Document what the system actually does. Before you fix anything, understand what it’s supposed to do. The dev shop may have implemented business logic you’ve forgotten you asked for.
Have an honest conversation with your engineering hire about timeline and cost. “Cleaning this up” takes as long as it takes. Get a realistic estimate, not an optimistic one.
The $200K Question
You’re probably wondering whether you made a mistake. Maybe. But here’s the more useful frame: you have a product with real customers that exists. An imperfect product that ships is worth more than a perfect product that doesn’t exist yet. The question is whether the foundation is solid enough to build on — and that’s what the audit tells you.
If you’ve just received a codebase from a vendor and you’re not sure what you’re looking at, this is one of the most common situations I step into. In a 15-minute call, I can help you understand what a good technical audit should cover and how to think through your options without making a panic decision. Book a free 15-min call — let’s figure out what you actually have.
Related: How Much Technical Debt Is Too Much | Inherited a Codebase — What to Do First | Offshore Team Not Delivering
