Teams rarely pick the wrong framework. They pick the wrong architecture. The framework is a detail; the architecture is the set of decisions that determine whether the app is easy to change, fast to load, and cheap to run a year from now. Here are the decisions that actually matter.
Start with the data model
The single most important decision in a web app is the data model. Get the core entities and their relationships right and most other problems become easier. Get them wrong and no amount of clever frontend code will save you.
Practical advice: model the real business, not the UI. The screens will change; the underlying entities usually will not. Design the database around the things that are stable.
Monolith first, microservices later
There is a strong default that is often ignored: start with a modular monolith. A single deployable unit with clear internal boundaries is far easier to build, test and operate than a fleet of microservices.
Microservices earn their keep when you have multiple teams, genuinely independent scaling needs, or isolated failure domains. For most products, that is not true at the start — and the operational cost of microservices is real and ongoing.
Distributed systems are not "better" — they are a different set of trade-offs. Reach for them when a specific, measurable problem demands it, not as a default.
Design the API boundary early
Even in a monolith, treating your internal boundaries like an API pays off. Clear, versioned contracts between modules mean you can change the inside without breaking the outside. It is the difference between a codebase you can evolve and one you can only rewrite.
Performance is an architecture decision
Speed is not something you add at the end. It is decided by where you cache, how you structure queries, and how much work you do on the server versus the client. A few architectural choices — pagination, sensible caching, avoiding N+1 queries — do more for perceived performance than any optimisation trick.
Make it easy to change
The best test of an architecture is how cheap it is to make the next change. If adding a feature requires touching a dozen files, the architecture is fighting you. Keep modules small, keep dependencies pointing one way, and favour boring, well-understood technology for the parts that do not need to be novel.
Conclusion
Modern web app architecture is less about the latest stack and more about a handful of durable decisions: a data model that reflects the business, a structure that is easy to change, an API boundary that holds, and performance built in from the start. Get those right and the framework becomes a detail you can swap.
