Rewrite it, or move it piece by piece? How I decide
Short answer
Move it piece by piece, unless the whole product is small enough to rebuild in one short project while feature requests wait. A rewrite stops your releases until it is finished. A piece-by-piece move keeps them going, and if you stop halfway you still have something that works.
Contents 5 sections
The urge to rewrite usually comes with good reasons. The code is slow to change. The developer who wrote it has left. The framework is two major versions behind and nobody wants to touch the upgrade. Those are all reasons to change the code. On their own, none of them is a reason to throw it away in one go.
Why is a full rewrite so risky?
The case against it was made in 2000 and has not aged much.
the single worst strategic mistake that any software company can make
Joel Spolsky was writing about Netscape, which had decided to rewrite its browser from scratch. At the time of his essay, its last major release was “almost three years ago”. His argument is still the one I would make to a founder: “Old code has been used. It has been tested.” The ugly parts that make you want to start over are often bug fixes, and each one is a lesson somebody paid for. Throw the code away and you throw the lessons away with it. He adds the line every developer recognises: “It’s harder to read code than to write it.”11Joel Spolsky, “Things You Should Never Do, Part I”, Joel on Software, 6 April 2000. joelonsoftware.com, checked 11 November 2026.
Martin Fowler, writing in 2024, has seen the same plan “go down in flames most of the time”. He gives two reasons, and both apply to a ten-person startup as much as to a bank.22Martin Fowler, “Strangler Fig”, 22 August 2024. martinfowler.com, checked 11 November 2026.
- Your users do not stop asking for things. “Replacing a serious IT system takes a long time, and the users can’t wait for new features.” A rewrite either freezes the product or chases a moving target.
- Nobody knows everything the old system does. “Replacements seem easy to specify, but often it’s hard to figure out the details of existing behavior.” The code is the only complete spec, and the rewrite is the moment you stop reading it.
So a rewrite has two costs that never show up in the estimate. Releases stop until it is done. And behaviour nobody wrote down gets lost, then found again by customers.
What does piece by piece look like?
Fowler calls the alternative “a gradual process of modernization”: you put the new system next to the old one and “move bits of behavior from the legacy system into the new code base”, one piece at a time.2 It is often called the strangler fig, after a plant that grows around a tree until the tree is no longer needed.
- Fig.
Each piece is small, so each move is small, and in Fowler’s words “there isn’t so much risk involved”. Each piece starts earning as soon as it is live, “allowing earlier return on the investment”.2
The approach costs something too, and Fowler says so. You write code whose only job is to bridge the two systems, “code that will go away once the modernization is complete”. That feels like waste. It is the price of never having a day when everything changes at once, and I think it is cheap at that price.
How do you move the data while people use it?
The data is the part that scares people, and it is also the part with the best-known recipe. In 2017 Stripe described how it moves data between stores “without any downtime”, using what it calls a common four-step pattern.33Jacqueline Xu, “Online migrations at scale”, Stripe, 2 February 2017. The four step names are Stripe’s. stripe.com, checked 11 November 2026. In plain words:
- Dual writing. Every change is written to both the old store and the new one. Old records are copied across in the background.
- Changing all read paths. The product starts reading from the new store, while still writing to both. Any difference between the two shows up here, while you can still go back.
- Changing all write paths. The new store becomes the only one written to.
- Removing old data. Only when nothing reads or writes the old store does it go.
Stripe runs this at a scale most products never reach, and it still does it in steps. That is the point. The steps are there so that at any moment one move can be undone, and that matters just as much to a product with two hundred customers.
When is a rewrite the right call?
Sometimes. A small product, few users, and a founder willing to hold feature requests for a few weeks: rebuild it. That describes plenty of early MVPs, and moving one piece by piece would cost more than it saves.
This is the table I go through on a first call. Each row gives the answer that points to a rewrite. Any other answer points to piece by piece.
| Question | Points to a rewrite |
|---|---|
| Can new features wait until it is done? | Yes, for the whole rebuild |
| How big is it? | Small enough to rebuild in one product build, usually 4–8 weeks |
| Is what it does written down anywhere? | Yes, or it does very little |
| Are real customers on it every day? | Few, and the data can move in one evening |
| Can the old code still be deployed and patched? | No |
| Are you changing what the product does? | Yes. Then it is a new product, not a rewrite |
The first two rows decide most cases. If both point to a rewrite, I would rebuild. If either points the other way, I would put a router in front and start with the piece that hurts most. The other rows move it at the edges: code that can no longer be patched at all pushes toward a rewrite, and customers on it every day push away from one.
Whichever way it goes, I write down every behaviour of the old system that customers rely on before anything is rebuilt. It is the cheapest insurance in the whole project.
I have not published a migration case of my own yet. When I do, it goes here: which way I went, why, and what I would change.
What about moving to a new platform?
A platform move, such as taking a product’s database or sign-in from one provider to another, is the same decision in a smaller box. The same rules apply: one piece at a time, with the data written to both places until the new one is trusted.
Disclosure, because it matters here: I work at Supabase as a design engineer. Supabase publishes migration guides for moving from Firebase Auth, Firestore, Firebase Storage, Auth0, Heroku, Amazon RDS, Render, Neon and others.44Supabase, “Migrating to Supabase”. supabase.com, checked 11 November 2026. They are worth a look whichever platform you end up on. I recommend a platform per project, and I will tell you on the call if the one you have is fine.
If your product is the thing that needs moving, the product page says how I scope and price that kind of work.
Notes and sources
-
Joel Spolsky, “Things You Should Never Do, Part I”, Joel on Software, 6 April 2000. joelonsoftware.com, checked 11 November 2026. ↩︎
-
Martin Fowler, “Strangler Fig”, 22 August 2024. martinfowler.com, checked 11 November 2026. ↩︎ ↩︎ ↩︎
-
Jacqueline Xu, “Online migrations at scale”, Stripe, 2 February 2017. The four step names are Stripe’s. stripe.com, checked 11 November 2026. ↩︎
-
Supabase, “Migrating to Supabase”. supabase.com, checked 11 November 2026. ↩︎
Written by Dion Zeneli. AI helped with research and editing. Sources are linked where they are used. Read this note as markdown.