I tend to reason about the design of the code and system architecture by thinking about:
“How much are we speculating about the future in our code and system architecture?” (over-engineered for our current needs), and
“To which extent is the way that our code is written and designed hurting us already now and to which extent are we aware of that?” (under-engineered)
This is very much in line with the ‘just-in-time’ incremental and evolutionary design/architecture I tend to gravitate toward.
But, the very important caveat to be careful of is that for the exponential curves, just-in-time is far sooner than when we notice it. When we notice it, it’s already too late.
Developing this sensitivity to build situational awareness in order to react at the right time is one of the most important skills a team/org needs to nurture.