Modernization often starts from real pain: the system is slow to change, tests don't protect enough, deployment is stressful, or new features get built around old code instead of through it. That's a good reason for change, but not proof that you should start a rewrite.
A big rewrite sounds clean because it promises a fresh start. In practice, it often stops delivery, shows risks late, and ends up as a race between the old system that still needs maintenance and the new one that isn't ready yet.
Map the risk first, not the technology
Modernization doesn't start with the question "which stack are we migrating to?" It starts with the question of which part of the system most blocks changes or creates operational risk. Sometimes it's architecture, sometimes tests, sometimes deployment, and sometimes just unclear ownership.
A good audit looks for
- parts of the codebase that change most frequently
- modules where bugs keep recurring
- places without tests or clear contracts between systems
- manual release steps and operational dependencies
Modernize through verifiable boundaries
The best modernizations have a clear boundary: one module, one API, one workflow, or one piece of infrastructure. Such a change has a measurable end and can be deployed to production without waiting for the entire system to be rewritten.
Good first changes
- test harness around a critical workflow
- extracting a clear API contract
- automating deployment or rollback
- replacing one manual process with an internal tool
Warning signs
- plan has no incremental release
- new system has no users for months
- feature development stops while rewrite is underway
- success is measured by the new stack, not better delivery
AI can help, but doesn't replace engineering responsibility
AI tools can speed up codebase analysis, test preparation, documenting existing behavior, and scoped refactors. That's useful, but only if the team knows what it's checking. Modernization is too important to be left to a large automated patch without understanding system boundaries.
In practice, AI helps most when combined with a good software consulting process: first define the goal and risk, then use the tool for faster analysis and controlled changes.
Conclusion
Modernization without downtime means delivery stays alive while the system improves. That requires discipline: small scope, clear boundaries, tests, observability, and decisions that can be explained to the team.
The goal isn't to have the latest stack. The goal is a codebase that's easier to change, safer to deliver, and better supports the business the software is supposed to run.
Josip Budalić
HOTFIX team
Josip runs HOTFIX d.o.o. and works on software architecture, AI-assisted development workflows, codebase modernization, and practical software delivery.