I've seen plenty of Scala codebases grow without ever needing an overall redesign, and don't see why it would be different for any other language. Of course the end state is very different from the start state, and no doubt pieces end up getting rewritten many times over. But being able to incrementally evolve the codebase while keeping it all working is much easier and cheaper than having to rewrite in one go. In my experience you only need a "redesign" when you did too much design up front in the first place; if you always keep code changes driven by concrete use cases and avoid premature generalisation, you end up with a codebase that won't impede future changes any more than it has to.