DEV Community

Cover image for When to Rebuild vs When to Refactor: A Decision Framework for Founders
Brian Makumi
Brian Makumi

Posted on • Originally published at brianmakumi.com

When to Rebuild vs When to Refactor: A Decision Framework for Founders

At some point in the life of almost every growing product, the team has a version of the same conversation. The codebase is causing pain. Features are taking too long. Bugs are multiplying. The developers are frustrated and the founder is losing confidence in delivery. Someone suggests starting fresh. Someone else argues for fixing what exists. The conversation goes in circles and ends either in a decision made on gut feeling or a decision deferred until the pain becomes a crisis.

The refactor versus rebuild decision is one of the most consequential a technical team makes, and it is almost always made without a structured framework for evaluating it. The result is that teams with genuinely fixable codebases embark on expensive rebuilds that take twice as long as estimated and produce a new codebase that inherits half the problems of the old one. And teams with fundamentally broken architectures spend months refactoring around a structural problem that incremental improvement cannot resolve.

This post is a framework for making this decision as a business decision rather than a technical preference or an emotional reaction to a difficult codebase. It covers the criteria that actually determine which path is right, the real cost of each option with honest timeframe estimates, and the questions worth answering before committing to either.

The refactor vs rebuild decision is almost always made on gut feeling rather than structured evaluation. The gut is wrong often enough that the decision deserves a framework.

WHY THIS DECISION IS SO HARD TO MAKE CLEARLY

The difficulty is not technical. It is psychological and political.

Developers who built the original codebase have a natural resistance to rebuilding it. Acknowledging that a rebuild is necessary is acknowledging that the original decisions were insufficient, which feels like a personal failure even when the original decisions were entirely reasonable given the constraints that existed at the time.

Developers who did not build the original codebase have a natural bias toward rebuilding it. Every codebase looks worse from the outside than from the inside, and the instinct to start fresh rather than inherit someone else's decisions is strong even when the existing code is more solid than it appears.

Founders add a third dimension. A rebuild feels like a pause on progress. A refactor feels like paying a debt that should not exist. Neither feels like building the product, even though both are necessary forms of product investment at different stages.

The framework that follows is designed to remove the psychological dimension from the decision by replacing it with specific, evaluable criteria. The answer that emerges from the framework may not be the answer anyone wanted, but it will be the right one more often than a gut-driven decision will.

THE CRITERIA THAT ACTUALLY DETERMINE THE RIGHT PATH

Is the problem structural or incidental?

The most important question in the entire framework. A structural problem is one that exists in the fundamental architecture of the system: the data model does not support the product direction, the layer boundaries have collapsed and cannot be restored incrementally, the technology choices made early are now incompatible with current requirements. A structural problem cannot be fixed by refactoring. You can improve the code around it indefinitely without resolving it.

An incidental problem is one that exists in specific components or modules without being embedded in the architecture itself: duplicated logic, inconsistent naming, missing tests, poorly structured database queries, components that have grown beyond their original scope. An incidental problem is addressable incrementally. Targeted refactoring of the affected areas produces genuine improvement without requiring a full rebuild.

The diagnostic question is: if we fixed the worst areas of the codebase, would the underlying system be able to support where the product needs to go in the next twelve months? If yes, the problem is incidental. If no, it is structural.

How concentrated is the debt?

Debt that is concentrated in specific modules or layers is refactorable. You can identify the problem areas, address them in sequence, and produce a measurably better system without touching the parts that are working well.

Debt that is distributed throughout the architecture is much harder to address incrementally. When every layer of the system has been compromised, when the data model, the business logic, and the API layer are all entangled in ways that make it impossible to improve one without touching all three, targeted refactoring produces diminishing returns. Each improvement creates ripple effects that require additional changes, and the team spends more time managing the consequences of changes than delivering the improvements themselves.

A practical way to assess concentration: ask your developers to identify the three areas of the codebase they would most want to improve. If those three areas are isolated and do not heavily depend on each other, the debt is concentrated enough to address through refactoring. If improving any one of them requires changes throughout the system, the debt is distributed and the refactoring path is significantly more expensive than it appears.

Is the system currently generating revenue?

A system in production with paying users cannot be taken offline for a rebuild. Any rebuild strategy has to account for the cost of running two systems simultaneously: the existing system serving current users while the new one is built, tested, and gradually migrated to.

Running two systems in parallel typically adds 20 to 30 percent to the total rebuild cost and timeline, because some development capacity is always diverted to maintaining the existing system rather than building the new one. It also introduces the migration problem: moving users, data, and integrations from the old system to the new one is a project in itself, with its own risks and timelines.

For a system that is not yet in production, or that serves a small enough user base to migrate quickly, this constraint is less significant. For a system with significant revenue dependency and a complex data migration requirement, it is often the factor that tips the analysis toward refactoring even when a rebuild might otherwise be justified.

Does the team understand the existing system?

This question is underrated in most refactor versus rebuild analyses. A rebuild by a team that does not fully understand the existing system will reproduce a significant number of the original system's problems in the new one, because those problems are not visible until you try to build around them.

The existing system, however messy, contains years of encoded business logic: edge cases discovered in production, integrations built to accommodate third-party quirks, data handling decisions made in response to real user behaviour. Much of this logic is not documented. It lives in the code, sometimes in ways that look like mistakes but are actually intentional decisions made in response to constraints that are no longer obvious.

A team that rebuilds without understanding this encoded logic will spend the first six months of production discovering that the new system fails in all the same ways the old one used to, because the decisions that prevented those failures were not carried over. This is one of the most common reasons rebuilds take twice as long as estimated and still launch with significant defects.

The existing system contains years of encoded business logic that is not in any document. A rebuild without understanding it will reproduce the problems it was built to avoid.

THE REAL COST OF EACH PATH

What refactoring actually costs

A targeted refactor of a specific, well-understood module typically takes two to four weeks per engineer, assuming reasonable test coverage and some existing documentation. Without test coverage, add 50 to 100 percent to that estimate because the refactoring work itself generates the need for tests that should have existed before.

A broader refactor addressing multiple interconnected areas of a codebase typically runs three to six months for a team of two to three engineers, with continued product development happening in parallel at reduced velocity. Expect feature delivery to slow by 30 to 50 percent during an active refactor phase as engineering capacity is divided between improvement and new development.

The ongoing cost of not refactoring, for comparison, is typically measured in the velocity tax: a team that could ship ten features a month in the early product may be shipping three in month twelve because of accumulated complexity. At a conservative estimate of one engineer month per feature, that is seven engineer months of lost velocity per month, compounding indefinitely until the debt is addressed.

What rebuilding actually costs

A rebuild of a production system is almost always underestimated, typically by a factor of two. The most common estimate for a rebuild that takes twelve months is six months. This is not because developers are bad at estimating. It is because rebuilds surface requirements that were invisible until the team tried to implement them in a new architecture, and because the parallel system maintenance cost is consistently underestimated.

A realistic rebuild timeline for a small to medium product with one to three years of development history and a team of two to four engineers is nine to eighteen months to reach feature parity with the existing system. Feature parity means the new system does everything the old one does. It does not mean the new system is better. Getting to genuinely better typically requires an additional three to six months of post-migration stabilisation.

Total cost of a rebuild for a system in this range: twelve to twenty-four months of engineering time, during which the existing system must be maintained, new feature development is significantly constrained, and the organisation carries the risk of a delayed or failed migration. For a funded startup, this is a material commitment. For a bootstrapped one, it is often existential.

These numbers are not arguments against rebuilding. They are arguments for being honest about what a rebuild actually costs before committing to one, so that the decision is made with accurate information rather than optimistic estimates.

THE DECISION FRAMEWORK

Run through these questions in sequence. The answers will converge on the right path more reliably than any single criterion evaluated in isolation.

  • Is the core architecture structurally incompatible with where the product needs to go in the next twelve months? If yes, lean rebuild. If no, continue.
  • Is the technical debt distributed throughout every layer of the system, or concentrated in specific areas? If distributed throughout, lean rebuild. If concentrated, lean refactor.
  • Is the system currently generating revenue that depends on continuous operation? If yes, add 20 to 30 percent to the rebuild cost and timeline before comparing. If no, the rebuild path is less constrained.
  • Does the team building the replacement have a thorough understanding of the business logic encoded in the existing system? If no, budget six to eight weeks of discovery before the rebuild starts, or accept that the new system will reproduce the problems of the old one.
  • Has the team attempted targeted refactoring of the worst areas and found that improvements in one area consistently create problems in others? If yes, the debt is likely structural rather than incidental, and refactoring is producing negative returns.
  • What is the cost of twelve more months on the existing system in terms of lost velocity, developer attrition risk, and features that cannot be built? If that cost is lower than the rebuild cost and timeline, refactor. If it is higher, rebuild.

Most honest evaluations of these questions produce a clear answer. When they do not, the answer is almost always to refactor first: address the highest-cost areas incrementally, reassess in three to six months, and make the rebuild decision with better information than you have today.

THE HYBRID PATH MOST TEAMS DO NOT CONSIDER

The framing of refactor versus rebuild implies a binary choice. In practice, the most successful outcomes often come from a third path: a targeted partial rebuild of the structural problem areas while refactoring the rest.

If the data model is the structural problem but the API and frontend layers are serviceable, rebuilding the data layer and migrating to it incrementally is faster and lower-risk than rebuilding the entire system. If the frontend is the problem but the backend API is solid, rebuilding the frontend while keeping the existing API is a common and well-understood pattern.

The hybrid path requires a clear assessment of which layers are structurally compromised and which are incidentally messy. That assessment is worth commissioning as a standalone exercise before committing to either a full refactor or a full rebuild, because it often reveals that the scope of the structural problem is narrower than it feels from inside a painful codebase.

WHAT TO DO BEFORE YOU COMMIT TO EITHER PATH

Before committing to a refactor or rebuild, two things are worth doing that most teams skip.

The first is a documented audit of the current system. Not a code review in the traditional sense, but a structured assessment of where the debt is concentrated, what the structural constraints are, and what the encoded business logic is that any replacement would need to preserve. This audit takes one to two weeks for a typical small to medium product and produces the information the decision framework requires.

The second is an honest velocity measurement. How long do features actually take to ship on the current system, and how does that compare to what the business needs? The gap between actual velocity and required velocity is the most concrete measure of what the current technical situation is costing. That number, translated into engineering months per year, is what the refactor or rebuild investment has to beat to be worth making.

With those two inputs, the decision framework produces a defensible answer that can be communicated to a board, a co-founder, or an investor in business terms rather than technical ones. That is the standard the decision needs to meet, and it is achievable if the evaluation is done honestly before the commitment is made.

CLOSING THOUGHT

Refactor versus rebuild is not a technical decision. It is a business decision that requires technical input to make correctly. The teams that get it right are the ones that evaluate specific criteria rather than reacting to how the codebase feels, that cost both paths honestly before committing to either, and that resist the pressure to make the decision faster than the information supports. The right answer exists for every situation. Finding it requires asking the right questions rather than defaulting to the answer that feels most satisfying in the moment.

This post was originally published on brianmakumi.com.

Top comments (0)