The Monolith Problem Nobody Talks About
Most teams don't realize their frontend has become a monolith until it's too late. The symptoms are subtle at first — a slow CI pipeline, a merge conflict that takes half a day to resolve, a feature flag system that's grown into its own codebase.
By the time the pain is obvious, you're looking at a 400,000-line React app where touching the checkout flow risks breaking the navigation. This is the quiet crisis of the modern enterprise frontend.
What Micro-Frontends Actually Mean
The term gets thrown around loosely. At its core, micro-frontend architecture means decomposing a web application into independently deployable UI units — each owned by a separate team, each with its own build pipeline, and each composable into a coherent user experience at runtime.
This isn't just about splitting code. It's about splitting ownership. When the payments team can ship without waiting for the catalog team, you've fundamentally changed the velocity equation.
“The goal isn't smaller bundles. The goal is smaller blast radii.”
The Composition Strategies Worth Knowing
There are three primary composition models: build-time integration (npm packages), server-side composition (edge includes), and client-side composition (Module Federation, iframes, web components). Each has a different tradeoff profile.
Module Federation via Webpack 5 or Rspack is currently the most mature path for teams already in the React ecosystem. It allows true runtime sharing of dependencies and lazy-loaded remote modules without the overhead of iframes.
Where It Goes Wrong
The failure mode we see most often is teams treating micro-frontends as a technical solution to an organizational problem. If your teams aren't structured around product domains, decomposing the frontend just moves the coordination overhead — it doesn't eliminate it.
The other common trap is over-decomposing. Not every feature needs to be a remote. Start with the seams that already exist in your product — the natural boundaries where teams hand off work — and draw your module boundaries there.
