Almost nothing I build survives contact with its second requirement unchanged. So the question I really care about is not “is this right?” but “how cheaply can I be wrong?”
This is a working note rather than a definitive guide — the patterns here come from systems I’ve actually shipped and the trade-offs I kept running into along the way.
Optimize for the second version
When I design the first version of anything, I am quietly designing the seam where the second version will plug in. That usually means a clear interface, a reversible default, and resisting the urge to bake in a guess as if it were a fact.
Good architecture is not about predicting the future — it is about being cheap to correct.
The payoff is compounding. Every decision that stays easy to change keeps the next decision easy too, and a system made of reversible choices stays young far longer than one built to be perfect on day one.
None of this is glamorous, but it’s the part that decides whether a design holds up once real traffic and real deadlines arrive.