The honest 'when'
Adopt microfrontends when independent teams need to deploy independently. The real symptoms: teams blocked in a shared release train, one team's bug forcing everyone's rollback, build and CI times that grow with headcount, and ownership boundaries that don't map to the codebase. If you have one to three engineers, a well-structured monolith is faster — microfrontends add real coordination and runtime cost you shouldn't pay yet.
Split along ownership, not along tech
The boundary that works is the team/domain boundary — billing, dashboard, admin — each a unit a team owns end to end. Splitting by technical layer (a 'components' microfrontend, a 'utils' one) recreates the coupling you were trying to escape. The question for each boundary is: can this team deploy this piece on a Tuesday without asking anyone?
Module Federation and the shared-dependency trap
Runtime composition (Webpack/Rspack Module Federation, or a Next.js multi-zone setup) lets independently-built apps load each other at runtime. The classic mistake is shipping React three times — once per microfrontend. You declare shared, singleton dependencies so React, the router and the design system load once, and you version them deliberately.
// Module Federation: share singletons, don't duplicate React
new ModuleFederationPlugin({
name: 'dashboard',
remotes: { billing: 'billing@/mf/billing/remoteEntry.js' },
shared: {
react: { singleton: true, requiredVersion: '^19.0.0' },
'react-dom': { singleton: true },
'@acme/ui': { singleton: true }, // shared design system
},
});The three hard problems
- Shared state & auth: keep a single source of truth for the session (one token, one auth context) and pass it down; don't let each microfrontend re-implement login.
- Shared types: publish the enterprise TypeScript types as a versioned package so contracts between apps are checked, not assumed.
- CSS isolation: scope styles (CSS Modules, or a token-based system) so one team's stylesheet can't leak into another's UI.
Microfrontends trade build-time coupling for runtime and coordination complexity. That's a good trade only when independent deploys are worth more than the added moving parts. Below a few teams, it usually isn't.
Migrate piece by piece, never big-bang
You don't stop the world and rewrite. You carve one domain out of the monolith behind the composition layer, ship it, prove the deploy pipeline and the shared-dependency story work, then peel off the next. The monolith shrinks as the microfrontends grow, and the product never goes dark.
Key takeaways
- Microfrontends solve independent-deploy problems for multiple teams — not small teams.
- Split along team/domain ownership, not technical layers.
- Share React, the router and the design system as singletons — never ship them N times.
- Migrate incrementally behind a composition layer; big-bang rewrites are the risk you're avoiding.