Skip to content
Back to Insights
2026-09-15 10 min read Tanuj Garg Last reviewed 2026-10-13

Rewrite vs Refactor: A Scoring Model for Founders

Share

Your engineers say the codebase is a mess and the only fix is a rewrite. Features take three times longer than they did a year ago. You are being asked to approve months of work that will ship nothing a customer can see.

That is a big bet, and the person asking for it is usually the person who stands to be happiest about it. This post gives you a way to decide that does not depend on who argues best in the meeting.

My position: most rewrites should not happen. A few should. The model below helps you tell which is which.

Why rewrites usually go wrong

The old system looks ugly because it contains years of decisions. Every odd if statement is probably a customer who needed something, a payment edge case, or a bug someone paid for in an outage.

A rewrite throws that knowledge away and asks the team to rediscover it. Meanwhile:

  • Your roadmap freezes, or you run two systems and your best people split their time.
  • The old system still needs fixes, so the new one is always chasing a moving target.
  • The "done" date slides, because the last 20% (reports, imports, odd customers) takes as long as the first 80%.
  • You carry the risk of one big cutover instead of many small ones.

The usual cause of the mess is also not the language or framework. It is unclear boundaries, missing tests, and a data model that no longer matches the business. A rewrite by the same team under the same pressure tends to recreate the same mess.

The eight-question scoring model

Answer each question with a score from 0 to 3. Multiply by the weight. Add it all up. Higher scores point toward a rewrite. Be honest; if you are unsure, ask two engineers separately and take the lower number.

#Question03Weight
1Can you ship a small feature today in under two weeks?Yes, easilyNo, almost neverx3
2Is the data model itself the problem (not just the code on top)?Data is fineCore tables cannot represent the businessx3
3Does anyone on the team understand the system?Several people doNobody does, and no docsx2
4Is the stack end-of-life or impossible to hire for?Mainstream and supportedUnsupported, no security patchesx2
5Customer-facing risk of a big change (revenue, compliance, uptime)LowHigh, one bad cutover loses customersx-2 (subtract)
6Runway and ability to pause the roadmapUnder 12 months, cannot pause24+ months, can pausex2
7Do you have tests or any way to check the new system matches the old?Good coverage or a parallel run is possibleNothingx-2 (subtract)
8Has the same team done a similar rewrite successfully before?NoYes, recentlyx1

Questions 5 and 7 count against a rewrite. High risk and no safety net should lower the score.

The maximum is 3x3 + 3x3 + 3x2 + 3x2 + 3x2 + 3x1 = 39 before the two subtractions, and the subtractions can take off up to 12. Most honest scores land between 5 and 25.

Reading the score

Under 12: refactor in place. Your problem is discipline and focus, not architecture. Pick the two or three worst areas, add tests around them, and fix them while shipping features. Boring and effective.

12 to 20: strangler path. Something structural is wrong, but you cannot afford a stop. Replace the system piece by piece (explained below).

Over 20: a rewrite is worth a serious look. Even here, scope it to the part that is truly broken. A full rewrite should still be the exception.

The score is a conversation tool, not a verdict. If your total is 18 but question 2 scored a 3, the data model is your real project, and no amount of cleaning code on top will fix it.

The strangler middle path

Named after a vine that grows around a tree and slowly replaces it. The idea:

  1. Put a thin layer in front of the old system (a gateway or routing rule).
  2. Pick one slice, for example billing or notifications. Build it new.
  3. Route a small percentage of traffic to the new slice. Compare results with the old one.
  4. When it holds, route everything, then delete the old code for that slice.
  5. Repeat for the next slice.

Every step ships something. If money or patience runs out at slice three, you still have a better system than you started with, not a half-built replacement. That is the main reason I prefer it.

It has a catch. Done carelessly, you end up with two half-systems that call each other over the network, which is worse than either. I wrote about that failure in the distributed monolith trap, and the microservices scaling roadmap covers when splitting things up is actually warranted. Slices should follow business boundaries, and the data for each slice must move with it.

For your CTO or engineers

  • Start with the slice that has the clearest boundary and the highest pain, not the easiest one. Easy wins teach you nothing about the hard parts.
  • Share the database carefully at first. A read-only view or an anti-corruption layer keeps the new code from inheriting the old schema's quirks.
  • Run old and new in shadow mode (new receives a copy of traffic, results are compared but not returned) before any cutover.
  • Write characterization tests against the old behaviour first. They define "correct" better than any spec.
  • Keep a kill switch per slice so rollback is a config change, not a deploy.

Example (illustrative)

A 20-person B2B SaaS startup. Seven engineers. 14 months of runway. The founder is told the Rails monolith "cannot scale" and a rewrite in a new stack will take 6 months.

Scoring:

QuestionScoreWeightTotal
1. Ship small features2 (slow, 4-6 weeks)36
2. Data model is the problem1 (mostly fine, one messy table)33
3. Anyone understands it1 (two people do)22
4. Stack end-of-life020
5. Customer risk3-2-6
6. Runway/pause ability020
7. Safety net2 (thin tests)-2-4
8. Team has done it before010

Total: 1. Clear refactor.

The slow features trace back to one overloaded orders module and a deploy that takes 50 minutes. The plan: spend six weeks on tests around orders and a faster deploy pipeline, then split out that one module if it still hurts. The roadmap keeps moving. The 6-month rewrite would have eaten nearly half of the remaining runway.

Now change three things: the stack is unsupported (question 4 = 3), the core tables cannot represent the new pricing model (question 2 = 3), and the company has 30 months of cash (question 6 = 3). The total jumps to 19. That is strangler territory, starting with the pricing and billing slice. Still not a full rewrite.

When a rewrite is justified

Rare, but it happens. Usually all of these are true:

  • The data model fundamentally cannot represent what the business now does, and migrating it in place is more work than starting fresh.
  • The platform is unsupported, has known unpatched security holes, and you cannot hire for it.
  • The system is small enough to rebuild in a few months, not years.
  • You can run both in parallel and compare results.
  • Leadership has accepted a frozen or reduced roadmap in writing.

If one of those is missing, I would not approve it.

When NOT to do this

Do not use this scoring model, or consider any rewrite, when:

  • You are fighting an outage right now. Stabilise first. A scoring exercise during a fire is a distraction.
  • Nobody can describe the problem in business terms ("deploys take an hour", "reports time out"). "The code is ugly" is not a problem statement.
  • The team asking for the rewrite is mostly new and has not yet read the old code. Give it 60 days.
  • The goal is to adopt a new technology. Hiring appeal is a weak reason to rebuild a working product.
  • You are under 12 months of runway and have no clear route to the next round. Ship revenue instead.

Common mistakes

  • Letting the loudest engineer decide. Score it, and have two people score independently.
  • Rewriting to fix a people problem. Unclear ownership and no code review survive a rewrite untouched.
  • No definition of done. "Feature parity" is a trap. List the features you will actually carry over, and drop the rest on purpose.
  • Estimating from the happy path. Multiply the engineers' rewrite estimate by two before comparing it to the cost of fixing in place.
  • Moving the data last. Migration is the riskiest step. Plan it first.
  • Ignoring the cost of doing nothing. Refactor is not free either. Put a number on slow delivery before arguing about the fix.

Checklist

  • Write the problem in business terms (cost, delay, risk), not code terms
  • Score the eight questions, two people separately
  • Check question 2: is it the data model?
  • Decide the band: refactor, strangler or rewrite
  • If strangler or rewrite, name the first slice and its success test
  • Add tests around the area before you touch it
  • Agree what stops on the roadmap, in writing
  • Set a review date at 6 weeks with a go/no-go

Get a second opinion before you commit

If you are close to approving a rewrite, a review from someone outside the team is cheap insurance. I work with startups on exactly this through fixing and scaling existing systems. You can see how a modernization played out in the legacy modernization case study, and the wider material on stability is in the scaling and reliability guide.

Book a free 30-minute technical review and bring your scores. We will check them against what is actually in your code.

FAQ

How long does a typical rewrite take compared with the estimate?

Longer, almost always, and the gap is largest in the final stretch: imports, reports, edge-case customers. Treat any single-number estimate as a best case and plan the runway for double.

Can we do a rewrite and keep shipping features?

Only by splitting the team, which slows both efforts. The strangler approach is better here because new features can land in the new slices while old ones are retired.

Is it ever right to rewrite in a new language?

Sometimes, if the old stack is unsupported or you cannot hire for it. A change of language alone, without a structural problem, is not enough reason.

What if my engineers disagree with the score?

Good, that is the point. Ask them to point to the specific question they disagree on and what evidence would change their mind. The answer usually shows what the real issue is.