The Rewrite That Actually Worked
Coding agent is a multiplier. Your environment is the exponent.
I have always been scared of system rewrites. The urge strikes when leadership changes, new people join the team, or the existing team gets tired of handling technical debt accumulated through generations of developers. Someone suggests that the current system is a horrible mess, and we can go much faster if we redo it from scratch. “It will only take a quarter, maximum two,” they say. The project starts. A year later, the rewrite is “80% done”. Another 20% will take another year. Or two.
All big rewrites and architectural changes are risky. One company started a refactoring project to carve a module out of a legacy desktop application so they could build a web application around it. They formed a team and got to work. Last time I heard about it, the project was still going six years later. I wasn’t in the room when the decision to start this project was made, but I guess the people who made it didn’t expect this timeline.
I am Roman, CTO at a startup. I write High-Impact Engineering — a weekly newsletter for engineering managers, directors, and CTOs.
In this issue, I talk about system rewrites, and share a recent one that actually worked.
The 80% trap
I participated in several rewrites and architectural revamps. We never met the expected goal. I don’t think I am alone in this. What is the reason for such a bad track record? It is the inherent complexity of the old systems. The business logic is convoluted, with hidden edge cases and rarely used functionality. When optimistic estimates are made, these unknown or forgotten things are not taken into account.
The artisan era
Until recently, I was a proponent of gradual system evolution. For example, a Strangler Fig pattern. If you are not familiar with it, the basic idea is to create a parallel implementation of an old module, and then, when it is ready, switch consumers to this new system. The old system then gets deleted. Repeat it enough times, and the old system turns into the proverbial Ship of Theseus — functionality is preserved, but the code is new.
It is a slow, deliberate approach that requires good test coverage to ensure the behaviour is preserved. I liked doing these projects in the past. I felt like a craftsman, carefully carving these TDD test suites that mirrored the behaviour of the legacy system. Then I wrote the functionality and felt satisfaction looking at the reports. PASSED: 120, FAILED: 0. Good times.
Then came AI
Then came AI and changed how I think about rewrites and bigger architectural changes. No, I don’t think we should point an agentic harness with the latest model attached to a folder and tell it “refactor this, please” and go for a walk. And I think the Strangler Fig pattern is still a good idea.
What I have learned since is simple. AI on its own does not make a rewrite work. The environment it runs in does. But I am getting ahead of myself.
The rewrite we risked
Recently, my team got complex new requirements from the business. A quick note on scale: this is a classic two-pizza team — developers, QA engineers, a product owner, and a designer, ten people in total. But the team runs several projects in parallel, so the real capacity behind this rewrite was closer to six.
The requirements would stretch an already shaky subsystem to its limits — read, very much refactoring plus a barrel of super glue. We haven’t been happy with this subsystem for a long time, because it caused us to say “no” too often. Adding simple functionality was a pain because of poor early architectural choices. On top of it, the UI was outdated and looked like something from 2013.
After a lot of deliberation, the decision was made to take a risk and go with the rewrite. I will put my cards on the table and say that the rewrite has been successful. We met the deadline, shipped the expected functionality, and upgraded the look and feel.
Here are the numbers. Scoping and early preparation — interviewing users and stakeholders, building a live prototype, and validating it — took one month. Development took two. Before, early validation alone would have taken two to three months, and development five to eight. And those old estimates were highly uncertain; the new ones held. The whole rewrite was done before the old process would have finished validating the idea.
What made the difference compared with the previous rewrites?
Obviously, one of the main drivers is the speed of code production. I want to mention this before we dive in, as I think it is essential — but alone, it would not have been enough. The system it runs within matters just as much.
Breaking up with Figma
One of the first changes we introduced was breaking up with Figma. Figma cannot keep up with the speed at which the development team moves. Trying several options for user interaction in Figma could take us days, and because the prototype is just a facade without real data, we would still miss important corner cases.
When we switched to prototyping with AI, iteration speed increased manyfold. We got a fully functional application that both product team members and developers can explore. It helps to catch inconsistencies earlier and saves a lot of work down the line. (Our main infrastructure is on AWS, but we host prototypes on Vercel — it is simple for product team members to use and cheap for small applications like these.)
Context is the second unlock
The second part of the unlock was the closeness of the team to the business. The team held several workshops where we went through the user pain points, current and future needs, and early versions of the prototype — both to show what we wanted to achieve and to get feedback. This comprehensive approach to context transfer allowed team members to act more autonomously, make smarter technical decisions, promptly notice inconsistencies, and challenge the product team’s approaches.
The effect was visible in the workshops. When the team saw an early version of the prototype, they could ask much better questions, and many edge cases were identified right there. We didn’t catch everything before development started, but most of the remaining issues surfaced early, as soon as the more detailed work began, instead of in month four.
To be fair, one thing did slip through. A single feature required multiple rewrites because some details of the domain were not clear to all team members. Miscommunication, plain and simple. But considering the speed of iteration, it was an acceptable trade-off: redoing a feature is cheap when a rewrite takes days, not weeks.
Creating prototypes and working through the use cases, armed with the broader context, is what weeds out the unknown unknowns that make rewrites so painful. Pick the right direction early, execute it fast with AI. That is the leverage.
Old patterns, new economics
We picked the Strangler Fig pattern for the rewrite. Instead of trying to boil the ocean, we chose the minimal set of functionality that would cover the business case and focused on it only. In technical terms, it looks like a microservice with a microfrontend. The legacy side routes users to the new application for the migrated use case. For everything else, users continue using the old service.
As we progress with the rewrite, more use cases will be moved to the new side, and eventually, after reaching feature parity, the old side will be shut down.
In an architectural sense, good old best practices hold. Microservices often have a bad reputation for their complexity. They indeed add complexity. On the other hand, they can be powerful, turning brownfield development into greenfield — a small, clean codebase with clear boundaries that an agent can actually hold in its head.
The last thing worth mentioning is a changing relationship with code reviews: not all code is created equal, and if a coding agent can review most of it, velocity through the development life cycle increases. The topic deserves its own article — I touched on it here.
The environment is the multiplier
Agentic coding in the team setting is as powerful as the environment it operates in.
Previously mission-impossible projects, such as rewrites, have become possible. But only if we think holistically. Not only about the lines of code we produce. We have to think about our process and culture from first principles, not run the same playbooks from 2019.
Everything I described here started as an experiment at some point, and it worked well for my team. It might work for you, or you might discover something better. Keep experimenting. Subscribe to get my free process experiment template.


