I have been evaluating micro-frontends for the past three months, and I want to share what I found because the landscape has changed significantly since the last time most people looked at this.
Module Federation Is No Longer Webpack-Only
The biggest shift: Module Federation has evolved from a Webpack 5 plugin into a cross-bundler standard. As of early 2026, it works with Vite, Webpack, Rollup, and Rspack through the Module Federation 2.0 project. This is a meaningful change because it removes the bundler lock-in that was one of the strongest arguments against micro-frontends.
The promise is compelling: independently deployable frontend modules owned by different teams. Team A deploys their dashboard module on Tuesday, Team B deploys their settings module on Thursday, and the shell application composes them at runtime. No coordinated releases. No monolithic build pipeline. No “your PR is blocking my deploy.”
The Maturity Curve
Micro-frontends have followed a pretty clear maturity curve:
- 2020: Experimental. A few brave companies (IKEA, Spotify) tried it. Lots of blog posts about the concept, very little production tooling.
- 2023: Adopted by large companies. Webpack Module Federation stabilized. Real production stories emerged — both success and horror stories.
- 2026: Supported by tooling. Cross-bundler federation, better dev tooling, TypeScript support across boundaries. The technical barriers are mostly solved.
That last point is important: the technical barriers are mostly solved. The question is no longer “can we do micro-frontends?” but “should we?”
Our Situation
My company has 5 frontend teams and 1 monolithic React application. Every team’s code lives in the same repo, builds in the same pipeline, and deploys as a single artifact. The pain is real:
- A CSS change by one team breaks layouts in another team’s module
- Deployments require a full build and regression test across all modules
- A single flaky test in Team C’s code blocks Team A’s hotfix
- Teams cannot adopt new libraries or patterns without coordinating with everyone else
Micro-frontends would solve the deployment coupling. Each team builds and deploys their module independently. The shell app loads them at runtime.
What Module Federation Solves
Federation handles the hard parts of runtime composition:
- Shared dependencies: React, React DOM, and your design system library are loaded once and shared across modules
- Independent builds: Each module has its own build pipeline, CI/CD, and deployment schedule
- Version negotiation: If Module A needs React 18.3 and Module B needs React 18.2, federation can resolve this at runtime (in theory)
- Type safety: Module Federation 2.0 supports TypeScript type extraction across module boundaries
What It Does NOT Solve
Here is where my evaluation got sobering:
Shared state management. User authentication, global application state, feature flags — these cut across module boundaries. Module Federation gives you runtime composition, not state management. You still need a solution for “the user just logged out, and all modules need to know.” Most teams build custom event buses or use a shared state library, both of which add their own complexity.
Consistent design. This is my biggest concern as a design systems lead. When each module is built independently, keeping visual consistency requires extraordinary discipline. Different teams diverge on spacing, color usage, component patterns. Without a strong design system and enforcement mechanism, your app starts looking like a Frankenstein of different design languages.
Routing. Navigating between modules without full page reloads is surprisingly hard. Deep linking, browser history, and URL state all need coordination between the shell and modules. This is solvable but it is not solved by Module Federation itself.
Debugging. When something breaks at a module boundary — a shared dependency version mismatch, a missing exported component, a type error that only manifests at runtime — the debugging experience is poor. Error traces do not cross federation boundaries cleanly.
The Complexity Tax
My evaluation found that Module Federation adds significant operational complexity:
- Shared dependency management: Keeping React, your design system, and other shared libraries compatible across independently deployed modules requires active coordination. The “independence” is partial.
- Version compatibility: Module A deploys with a new shared library version. Module B has not updated yet. Runtime errors for users who get the mismatch.
- Runtime errors from type mismatches: TypeScript types are extracted at build time but modules deploy independently. Types can drift between modules.
- Integration testing: Unit tests pass for each module. Integration tests need a running shell with all modules loaded. This testing surface is large and flaky.
My Decision
After three months of evaluation, I am recommending a monorepo with shared libraries and parallel builds instead of micro-frontends.
Specifically: Turborepo with package-based module boundaries, shared design system package, and parallel CI pipelines per package. Each team owns their packages. Builds are fast because Turborepo caches aggressively. Deployments are still coordinated (single artifact), but with good caching the build time is under 3 minutes.
This gives us:
- Team ownership and clear boundaries (packages, not runtime modules)
- Shared design system enforced at build time, not runtime
- Standard debugging tools that work across the entire app
- Type safety checked at build time, not runtime
We lose independent deployment, but for 5 teams, I do not think the complexity tax of runtime federation is worth the independence benefit.
The Question
Has anyone here adopted micro-frontends in production? At what scale did the complexity become worth it? I am genuinely curious whether there is a team size or deployment frequency where the calculus flips.