Inheriting a codebase you did not write, and migrating it anyway
Taking over someone else platform is a different job from building one. The code works, the client depends on it, and you do not know why any given decision was made until you need to change it.
The brief was to migrate the stack and extend the product. The tempting route is an incremental port, translating file by file, because it feels lower risk. It usually preserves every mistake in the original, because a port asks how do I express this in the new stack rather than does this need to exist.
I rewrote it. That forced a decision about every one of the eighteen models, and two turned out to be unnecessary, so the migrated system has sixteen. Fewer models with more capability is the direction that indicates the original was understood rather than copied.
Then I documented it with full endpoint tables, because the reason inheriting a codebase is painful is almost never the code. It is that nothing was written down.