Guide · Tech choices & rescues
Rewrite vs refactor: how a founder should decide when the code is slowing everything down
Rewrite vs refactor for founders: a scorecard to decide, why full rewrites stall, the strangler fig middle path, and the questions to ask your developer.
Short answer
Refactor by default: improve the code in small steps while the product keeps shipping. Replace one part at a time when a component is wrong but the rest works. Rewrite only when the data model, the platform or the core architecture is wrong for the business, and even then rebuild in slices behind the live app instead of freezing features for months.
Rewrite or refactor: what's the actual choice?
Refactoring means improving the code's structure without changing what the app does, in small steps, while you keep shipping. Rewriting means replacing the code with new code, usually starting again, while the old app keeps running until the new one can take over. There's a third option most founders aren't offered: replace one part at a time, behind the live app, until the old part can be switched off.
The choice matters because it's mostly a business decision dressed up as a technical one. A rewrite stops feature work for weeks or months. A refactor keeps you moving but may not fix a foundation that's wrong. This guide gives you a way to tell which you're facing, and the questions to ask whoever is proposing it.
My background for this: about six years building and running production software, including five years as Head of Technology at Urban Culture, an at-home salon marketplace with four apps and 500K registered users. Running the same products for years teaches you which problems go away with a cleanup and which ones are in the foundations.
Why is a full rewrite so risky?
A full rewrite is risky because you throw away knowledge you can't see. The old code holds years of small fixes: the edge case for customers with two accounts, the timezone bug that only shows up during a holiday sale, the payment retry that support asked for. None of that is in the spec. The new version has to rediscover each one, usually from angry users.
The classic warning is Joel Spolsky's essay "Things You Should Never Do, Part I". He describes Netscape's decision to rewrite its browser from scratch as "the single worst strategic mistake that any software company can make", because it left almost three years between major releases while competitors moved. The details are from 2000, but the shape repeats in startups today: the team stops shipping, the old app gets no improvements, and the new one is always "a few weeks away".
There's also a human bias. Reading code is harder than writing it, so every developer finds someone else's code worse than it is. "This code is a mess" is often true and still not a reason to start over.
When is refactoring the right call?
Refactor when the app does the right things in a messy way. Martin Fowler, who wrote the standard book on it, defines refactoring as changing a program's internal structure without changing its observable behaviour. In practice that looks like:
- Adding tests around the parts that make money or protect data, so changes can't silently break them.
- Pulling duplicated code into one place, so a fix happens once.
- Upgrading old libraries and frameworks one version at a time.
- Moving secrets and privileged logic from the browser to the server.
- Renaming and splitting the files everyone is afraid to touch.
Refactoring is cheap to start, easy to stop, and you keep shipping features alongside it. That's why it's the default. Signs it will be enough: the data model matches how your business works, users mostly get what they need, and the pain is speed of change, not capability.
When do you actually need a rewrite?
Rewrite when the foundation is wrong for the business, because everything sits on it. The clear cases:
- The data model is wrong. You sell to teams but the database only knows individual users. Bookings and payments live in separate systems with no shared ID. Everything is stored as one blob of JSON.
- The platform can't do what you need. A no-code tool can't support the permissions, the scale or the integrations your customers now require.
- The code can't be changed safely at all. No tests, no environments, and a structure so tangled that adding tests would itself be a rewrite.
- You don't own it. The code is locked in a platform or with an agency, and you can't get it out in usable form. See who owns the code.
Even then, a rewrite rarely means rewriting everything. The screens, copy, flows and lessons from real users usually carry over. Often it's the backend and data model that get rebuilt, and the old frontend becomes the specification.
The rewrite vs refactor scorecard
Score your app honestly against each row. If most of your answers are in the first column, refactor. If any answer in the last column is about data or ownership, plan a rebuild.
| Question | Refactor | Replace one part | Rewrite or rebuild |
|---|---|---|---|
| Does the data model match the business? | Yes | Yes, except one area | No, a core concept is missing or wrong |
| What's the main pain? | Changes are slow or scary | One component is costly, slow or limited | You can't build what customers need |
| Can you add tests? | Yes | Around that component, yes | Not without restructuring everything |
| Is the platform the limit? | No | One service or vendor is | Yes, the whole platform is |
| Do you own and control the code? | Yes | Yes | No, or not in usable form |
| Can the business pause features? | Not needed | Briefly, for that area | Must, unless you rebuild in slices |
The middle path: replace the app one piece at a time
The safest way to do most "rewrites" is to never do a big-bang switch. Fowler calls this the strangler fig approach, after a vine that slowly grows around a tree: you build new parts around the old system, route traffic to them one area at a time, and switch the old parts off as they're replaced. A related technique, branch by abstraction, does the same inside one codebase.
A real example from my own work: at Urban Culture we replaced Google's Distance Matrix and geocoding calls with our own geolocation service. We didn't rewrite the marketplace to do it. One component was replaced, the rest of the apps kept running, and the result was about 80% lower cost for that piece with accuracy held. The full write-up covers the techniques, including how to compare old and new results before switching. The same thinking applies to reporting: the Firestore → BigQuery pipeline gave the business SQL reporting without moving the apps off Firestore.
The rules that make this work:
- Pick the part with the clearest pain and the cleanest edges first (payments, search, notifications, reporting).
- Run the new part alongside the old one and compare results before you switch traffic.
- Keep a switch to send traffic back to the old part for a while.
- Delete the old part once nothing uses it. A replacement that leaves both running forever doubles your maintenance.
What about vibe-coded apps?
Vibe-coded apps feel like rewrite candidates more often than they are. When an app built with Lovable, Bolt or Cursor hits a wall, the usual causes are missing security rules, no tests and duplicated code, and all three can be fixed in place. The real rewrite trigger is the same as for any app: a data model that doesn't fit the business.
Before deciding, run the security checks first, because those are urgent either way. The full checklist and a scorecard for "keep prompting, rescue or rebuild" are in the vibe-coded app guide. If you're still choosing tools, Lovable vs Claude Code vs Cursor covers when each one stops being enough.
Questions to ask a developer who proposes a rewrite
A good engineer welcomes these. Vague answers are a signal to get a second opinion.
- What specifically can't we do with the current code, in business terms?
- Is the problem the data model, the platform, or the code's structure? Show me.
- What would a refactor of the worst area look like, and why isn't it enough?
- Can we replace one part first and ship it to users? Which part?
- What do we stop shipping during the work, and for how long?
- How will we know the new version handles everything the old one did?
- Will everything stay in our repository and our cloud accounts?
More questions for evaluating any developer are in how to vet a developer.
A simple decision checklist
- Data model fits, pain is speed: refactor, starting with tests around money and permissions.
- One component is the problem: replace that part, run old and new side by side, then switch.
- Data model or platform is wrong: rebuild in slices, keeping the existing app as the spec.
- You don't control the code: get ownership first, then decide.
If you'd like an outside engineer to look before you commit, I start with a written diagnosis of what's wrong, what's risky and what's fine, then a fixed quote for whichever path makes sense. Here's how I work. If the diagnosis says a refactor will do, that's the answer you'll get.
Questions founders ask
What is the difference between refactoring and rewriting code?
Refactoring changes how code is structured without changing what it does, in small steps that keep the app working. Rewriting replaces the code with new code, usually from scratch, and the old version keeps running until the new one can take over. Refactoring is lower risk; rewriting can fix deeper problems but freezes progress while it happens.
How do I know if my app needs a rewrite?
Look at the foundations, not the mess. A rewrite is justified when the data model doesn't match how the business works, the platform can't do what you need, or the code can't be tested or changed safely at all. Messy code, old libraries or a developer's dislike of the previous developer's style are reasons to refactor, not rewrite.
How long does a software rewrite take?
Longer than the estimate, almost always, because the old app holds years of small fixes nobody wrote down. A rewrite of an MVP-sized product is typically weeks to a few months of focused work; a mature product can take much longer. Rebuilding in slices behind the live app keeps you shipping and limits the damage if it runs over.
Should I rewrite my vibe-coded app?
Only if its data model is wrong for the business. Most vibe-coded apps that feel broken have fixable problems: missing security rules, no tests and duplicated code. Fix those in place first. If a core concept is missing, such as teams when you sell to teams, rebuild the backend and keep the screens and copy as the spec.
Why do developers always want to rewrite?
Reading someone else's code is harder than writing your own, so old code looks worse than it is. Joel Spolsky made this point in his well-known essay on Netscape's rewrite. A good engineer can explain, in business terms, what a rewrite fixes that refactoring can't. If they can't, ask for a second opinion.