A software engineering truism that no longer makes sense after AI codegen:
"Never do a full rewrite."
Historically, rewrites were always a terrible idea. What would happen is the team feels like they have learned so much more about the business since the original system was written, the existing code/architecture is terrible, and the engineers have naturally improved as programmers.
Some engineer will bring up something called "the strangler fig pattern" and find the right domain boundary to break apart into a new microservice.
A POC is even made that breaks a controller out into the new service.
🎉 in the slack ship-it channel.
This is going great and cannot fail, right?
6 months later instead of having one terrible service you now have one terrible service and one service that makes no sense in isolation and always requires you to read the code of the terrible service to understand what is happening.
Reasons the rewrite would fail:
- There would always be a ton of hidden business logic in the original code that would be underestimated and wasn't captured by tests. I mean there is a reason why everyone wants to re-write this, right?
- You would either have to stop shipping new features or always be playing catch up. Software always takes longer to ship than estimated.
- The initiative naturally loses steam because of urgent business needs, or because the engineers who spearheaded the change lost interest and wanted to work on something new. Usually the latter to be honest.
So the end state would be:
- The rewrite never fully finished.
- The old system never fully went away.
- And now every feature required understanding two systems instead of one.
Rewrites would almost invariably be a net loss.
AI has meaningfully changed the dynamics of a rewrite to the point where they often can and do make sense.
- AI is particularly good at doing a 1:1 language port in a manner that captures business logic/intent.
- AI makes it much quicker to generate a ton of tests around legacy behavior, making the port safer.
- AI is good at understanding poorly written code. Can much more easily explore a large codebase at a macro and micro level and really understand what the system is actually doing.
The equation now is:
Do you have an engineer who knows where the dragons are in the old system? + Are they comfortable using the latest LLM agent harnesses to drive a large migration? + How many tokens are you willing to throw at the problem? At a certain point the ROI still may not be there, even if the migration does not require a large number of human engineering hours.
Rewrites still have to be done thoughtfully and with intent, but they are no longer almost always a terrible idea.
In my estimation, this has been true for about a year or so. And with high-profile OSS examples like Bun’s rewrite, I think many engineers are starting to come around to this line of thought as well.