Skip to content
GenGraphic

Software · 2 min read

Refactoring a product without stopping delivery

A staged approach to UI systems, architecture, testing, and migration.

A large refactor is often proposed as a pause: stop shipping features for a set number of weeks, rebuild the foundation, then resume. In practice, that pause is rarely acceptable to a business, and rarely necessary. A staged approach can improve architecture, testing, and UI consistency while new features continue to ship alongside it.

Start with a map, not a rewrite

Before changing anything, identify which parts of the system are causing the most actual pain — slow builds, brittle tests, duplicated UI patterns, or a data layer that makes simple changes risky. A refactor scoped to the areas causing measurable friction is far more defensible, and far more likely to be finished, than one scoped to "the whole codebase."

Introduce the new pattern alongside the old one

Rather than migrating everything at once, introduce the improved pattern — a new component library, a new data-fetching layer, a new folder structure — in parallel with the existing code. New features are built using the new pattern immediately. Existing code is migrated gradually, prioritised by which areas are touched most often by ongoing feature work, so migration effort overlaps with work that was happening anyway.

A codebase with two patterns coexisting temporarily looks messier on paper than a clean rewrite, but it keeps the product shippable throughout. The temporary inconsistency is a reasonable cost for continuous delivery — as long as there is a clear, tracked plan for finishing the migration rather than leaving it permanently half-done.

Protect the migration with tests, not good intentions

Any large-scale change to shared code needs test coverage before the change starts, not after. At minimum: automated tests for the critical user paths that touch the code being refactored, so a regression is caught before release rather than reported by a customer. Where coverage is missing, adding it becomes the first step of the refactor, not an afterthought.

Migrate in reviewable, reversible steps

Large changes should be split into pull requests small enough to review properly and revert individually if something goes wrong. A single enormous refactor PR is difficult to review meaningfully and risky to roll back. Splitting by module, page, or feature area keeps each step's blast radius small and keeps the team shipping in between.

What this achieves

Done this way, a refactor stops being a separate project competing with the roadmap, and becomes a parallel track running alongside it — measurable in the same sprints, reviewed with the same rigour, and finished by attrition rather than by a single risky freeze on delivery.

GenGraphic Team

Engineering

ShareinX

We use privacy-friendly analytics to understand how the site is used. No non-essential tracking runs before you accept. Read our cookie policy.