The instinct to rebuild is strong and almost always premature. A full rewrite means months where you ship nothing your customers can see, while the old system still needs maintaining. Sometimes that trade is worth it. More often the pain is concentrated in a few places, and those places can be replaced one at a time.
Is the problem the architecture or the code?
Ugly code inside a sound structure is cheap to fix incrementally. A sound structure means clear boundaries, data that lives in one place, and the ability to change one area without breaking three others. If those hold, refactor. If the fundamental shape of the system fights every change you want to make, that is an architecture problem, and no amount of cleanup fixes it.
Can you ship anything while you work?
A rewrite you can release in slices u2014 one screen, one service, one workflow at a time u2014 is a very different risk than one that only pays off at the end. If you cannot find a way to slice it, be honest that you are betting the next two quarters on a single delivery.
Where is the cost actually going?
Measure before you decide. Usually a small number of areas absorb most of the engineering time and generate most of the incidents. Replacing those specific pieces gets you eighty percent of the benefit for a fraction of the risk.
Does anyone still understand it?
This is the question that most often justifies a rebuild. If nobody on the team can explain how a critical part works, and there are no tests to tell you when you have broken it, then every change is a gamble. At that point the codebase is not an asset, and replacing it deliberately beats being surprised by it.
Rebuild when you cannot safely change the system. Refactor when you can, but it hurts.