Micro-frontends promised independent team deployability but delivered complexity. After years of production experience, we know when they work and when they're overkill.
The Micro-Frontend Value Proposition
The promise is compelling: independent teams deploy independently, different technologies can coexist, and applications scale organizationally. But these benefits come with costs: increased complexity, performance overhead, and coordination challenges.
When Micro-Frontends Actually Help
Large organizations with autonomous teams: When teams of 50+ developers work on the same application and need deployment independence.
Integration of legacy systems: When you're gradually migrating from legacy tech and need old and new to coexist.
Acquisitions and mergers: When combining applications from different companies with different tech stacks.
// Module Federation setup for genuine independence
// webpack.config.js (shell application)
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'shell',
remotes: {
products: 'products@https://products.example.com/remoteEntry.js',
checkout: 'checkout@https://checkout.example.com/remoteEntry.js',
admin: 'admin@https://admin.example.com/remoteEntry.js',
},
shared: ['react', 'react-dom', 'react-router-dom'],
}),
],
}
When They're Overkill
Teams under 20 developers: The coordination overhead exceeds the benefit.
Single technology stack: If everyone uses React, a monolith with good architecture works better.
Tight feature coupling: If features share state and require coordination, micro-frontends add friction.
Alternative Patterns for Large Teams
Before micro-frontends, consider:
// 1. Monorepo with clear module boundaries
packages/
shared/ # Design system, utilities
feature-products/ # Products team owns
feature-checkout/ # Checkout team owns
app/ # Shell that composes features
// 2. Feature flags for independent deployment
if (flags.isEnabled('new-checkout')) {
return
}
return
// 3. Vertical slice architecture
// Each feature is self-contained with its own:
// - Components
// - State management
// - API layer
// But shares infrastructure and design system
Implementation Approaches
If you do need micro-frontends:
// Module Federation (Webpack 5+)
// + Native bundler support
// + Shared dependencies
// - Complex configuration
// Single-SPA
// + Framework agnostic
// + Mature ecosystem
// - Learning curve
// Native Federation (esbuild, Vite)
// + Modern tooling
// + Better DX
// - Newer, less battle-tested
Key Takeaways
Micro-frontends solve organizational problems, not technical ones. If you don't have team scaling issues, you don't need them.
Start with simpler patterns. Monorepos, feature flags, and good architecture solve most problems.
The overhead is real. Performance costs, complexity, and coordination overhead must be justified by genuine independence needs.
