← Back to articles

Micro-Frontends: Worth It or Not? (2026)

Micro-frontends split a frontend into independently deployable pieces, each owned by a different team. Big companies love them. Small teams regret them. Here's the honest take for 2026.

What Are Micro-Frontends?

Monolith frontend: One codebase, one build, one deployment. Everything in one Next.js app.

Micro-frontend: Multiple independent apps composed into one user experience. Each team owns and deploys their piece independently.

┌─────────────────────────────────┐
│           App Shell              │
├──────────┬──────────┬───────────┤
│  Team A  │  Team B  │  Team C   │
│  Product │ Checkout │  Account  │
│  (React) │  (React) │  (Vue)    │
└──────────┴──────────┴───────────┘

When Micro-Frontends Make Sense

Large Organizations (50+ Frontend Developers)

When 5+ teams work on the same frontend, a monolith creates bottlenecks:

  • Merge conflicts across teams
  • One team's deploy blocks another
  • Shared dependencies cause upgrade wars
  • CI takes 30+ minutes

Micro-frontends give teams independence: separate repos, separate deploys, separate tech choices.

Acquisitions and Integrations

Company acquires another company. Each has a different frontend stack. Micro-frontends let you compose them without rewriting.

Gradual Migration

Migrating from Angular to React? Micro-frontends let you replace one section at a time while keeping the old code running.

When Micro-Frontends Don't Make Sense

Small Teams (< 20 Developers)

If your frontend team is under 20 people, a monolith (or monorepo) is simpler, faster, and cheaper. The overhead of micro-frontends exceeds the benefits.

Startups

You're optimizing for speed, not team independence. A monorepo with Turborepo gives you code sharing without the micro-frontend complexity.

Single Product

If you have one product with tightly integrated features, splitting it into micro-frontends adds communication overhead with no benefit.

The Honest Cost

MonolithMicro-Frontends
Setup time1 day2-4 weeks
Build complexitySimpleComplex (module federation, orchestration)
Shared stateEasy (one app)Hard (events, shared stores)
Consistent UIEasy (one design system)Hard (versioning, drift)
PerformanceGood (one bundle)Variable (multiple bundles, duplication)
Team independenceLowHigh
Deploy independenceLowHigh
Developer experienceGoodDepends on tooling

Implementation Patterns

1. Module Federation (Webpack/Vite)

Apps expose and consume modules at runtime:

// app-shell/vite.config.ts
import federation from '@originjs/vite-plugin-federation'

export default {
  plugins: [
    federation({
      remotes: {
        productApp: 'http://localhost:3001/assets/remoteEntry.js',
        checkoutApp: 'http://localhost:3002/assets/remoteEntry.js',
      },
    }),
  ],
}
// Load remote component
const ProductList = React.lazy(() => import('productApp/ProductList'))

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <ProductList />
    </Suspense>
  )
}

2. Route-Based Composition

Different apps handle different routes. Nginx or a reverse proxy routes traffic:

location /products { proxy_pass http://product-app:3001; }
location /checkout { proxy_pass http://checkout-app:3002; }
location /account  { proxy_pass http://account-app:3003; }

Simplest pattern. Each route is a separate app. Shared layout via a common header/footer component.

3. iframe Composition (Legacy)

<iframe src="https://checkout.example.com" />

Don't do this unless integrating truly legacy systems. Iframes have terrible UX (no shared state, no shared styling, accessibility issues).

4. Server-Side Composition

// App shell fetches HTML fragments from micro-frontends
const productHTML = await fetch('http://product-app/fragment/list').then(r => r.text())
const cartHTML = await fetch('http://cart-app/fragment/sidebar').then(r => r.text())

return `
  <div id="app">
    <div id="products">${productHTML}</div>
    <div id="cart">${cartHTML}</div>
  </div>
`

The Problems Nobody Talks About

1. Shared State Is Hard

User logs in on the app shell. How does the checkout micro-frontend know? Options:

  • Custom events (window.dispatchEvent)
  • Shared state library
  • URL parameters
  • Cookies

All are messier than a monolith's useContext.

2. Design Consistency Drifts

Team A updates the button component. Team B doesn't. Now your app has two button styles. Solutions:

  • Shared design system as an npm package
  • Strict versioning and automated visual regression tests
  • Design tokens

This works but requires discipline and governance.

3. Performance Overhead

Each micro-frontend may bundle its own React, lodash, etc. Without careful deduplication:

  • 3 micro-frontends × React = 3× the React code downloaded
  • Module Federation can share dependencies, but configuration is tricky

4. Testing Is Harder

Integration testing across micro-frontends requires running multiple apps simultaneously. End-to-end tests are more complex and slower.

5. Developer Onboarding

New developer joins: "How do I run the whole app locally?" With micro-frontends, the answer is complicated.

The Better Alternative: Monorepo

For most teams, a monorepo gives you micro-frontend benefits without the costs:

monorepo/
├── apps/
│   ├── web/           # Main Next.js app
│   └── admin/         # Admin dashboard
├── packages/
│   ├── ui/            # Shared components
│   ├── utils/         # Shared utilities
│   └── config/        # Shared config
  • Code sharing without module federation
  • Independent deployable apps via Turborepo
  • Consistent tooling across packages
  • Simple local development (one repo, one npm install)

Decision Framework

Team size < 20 → Monorepo (Turborepo)
Team size 20-50 → Monorepo with strict boundaries
Team size 50+ → Consider micro-frontends
Acquisition integration → Micro-frontends (temporarily)
Greenfield project → Always start with monorepo

FAQ

Should my startup use micro-frontends?

No. Use a monorepo. Micro-frontends solve organizational problems (team independence at scale), not technical problems. Startups don't have these organizational problems yet.

Can I migrate from monolith to micro-frontends later?

Yes, and this is the recommended path. Start monolith, split when organizational pain justifies the complexity.

What about Next.js Multi-Zones?

Next.js Multi-Zones is a lightweight micro-frontend pattern. Different Next.js apps handle different URL paths. Simpler than module federation but limited.

Do FAANG companies use micro-frontends?

Yes. Amazon, Spotify, and IKEA use micro-frontends. But they have 100+ frontend developers. Their scale justifies the complexity.

Bottom Line

Micro-frontends solve organizational scaling problems, not technical problems. For teams under 50 developers, a monorepo with Turborepo gives you code sharing and deploy independence without the overhead. Only adopt micro-frontends when team independence at scale is a real bottleneck — not because it's trendy architecture.

Default: monorepo. Micro-frontends only when you've outgrown it.

Get AI tool guides in your inbox

Weekly deep-dives on the best AI coding tools, automation platforms, and productivity software.