Back to System Design
System Design
hard
mid

What is micro frontend architecture and when would you use it?

Microfrontends extend microservice ideas to the UI: a single app is composed at runtime (or build time) from independently developed, deployed, and owned pieces. Each team ships their slice end-to-end. Composition via iframes, Module Federation, web components, or server-side includes. Trade-off: team autonomy and independent deploys vs. bundle duplication, version drift, and harder cross-team UX consistency.

8 min read·~5 min to think through

What it is

Microfrontend architecture splits a single web app into independently developed and deployed pieces — usually aligned with team or domain boundaries. Each piece owns its code, its build, its release cadence, and often its tech stack.

It is the UI counterpart to microservices: instead of one monolithic frontend that every team commits to, each team ships their slice.

Composition techniques

  • Iframes: hardest isolation, weakest UX (no shared DOM, sizing pain).
  • Webpack/Vite Module Federation: runtime import of remote bundles. Most common modern choice.
  • Web Components: custom elements as the integration contract; framework-agnostic.
  • Server-side composition (SSI, Edge Side Includes): assemble HTML fragments at the edge. Used by Spotify, Zalando.
  • Build-time composition: each team publishes an npm package; shell app installs and ships. Loses independent deploy.

Real-world use case: a large e-commerce site

Think of an online store with these surfaces:

  • Header / Nav / Search — Platform team
  • Product Detail Page — Catalog team
  • Cart + Checkout — Payments team
  • Account / Orders — Customer team
  • Recommendations — ML team

Each is a separate microfrontend. The shell app is just a thin layout + router that mounts the right remote at the right slot. Catalog can deploy a PDP redesign on Tuesday without coordinating with Payments. Payments can A/B a new checkout flow without Catalog rebuilding.

Zalando, IKEA, Spotify, and DAZN run variants of this in production.

Why teams reach for it

  • Independent deploys: no coordinated release train.
  • Team autonomy: each team picks its stack, testing approach, release cadence.
  • Scale of org: 50+ engineers on one repo + one build pipeline becomes painful.
  • Incremental migration: legacy app stays mounted while new pieces ship in modern stack.

Costs

  • Bundle bloat: every team ships its own React → multiple copies unless federation shares deps.
  • Version drift: shared design system at v3 in one team, v5 in another.
  • UX consistency: only as good as your design system enforcement.
  • Performance: more JS, more requests, hydration boundaries multiply.
  • Cross-cutting concerns: auth, telemetry, feature flags need a shared contract.
  • Debugging: errors cross remote boundaries.

When NOT to use

  • Small team (<20 engineers). The overhead dwarfs the benefit.
  • Single-product startup. You do not need autonomy yet.
  • Tightly coupled UX where every page shares heavy state.

Architecture decisions

  1. Composition model: federation vs. iframes vs. SSI.
  2. Shared runtime: how do remotes share React, design system, auth context?
  3. Routing: shell-owned or per-microfrontend?
  4. State: each remote isolated, or shared store with contracts?
  5. Versioning: how do remotes signal breaking changes?
  6. Observability: unified telemetry across remotes.

Mental model

Microfrontends are an org-scaling pattern, not a performance pattern. The win is team velocity. The cost is paid in bundle size, consistency, and integration complexity. Reach for it when team coordination becomes the bottleneck — not before.

Follow-up questions

  • How does Module Federation share dependencies between remotes?
  • How do you keep design-system consistency across microfrontends?
  • What is the routing model — shell-owned or per-remote?
  • How do you handle auth and shared state across remotes?

Common mistakes

  • Adopting microfrontends in a small team — overhead > benefit.
  • Duplicating React/framework in every remote — bundle bloat.
  • No shared design system contract — UX drifts immediately.
  • Tight coupling via shared global state — defeats the isolation.
  • Ignoring telemetry boundaries — cannot debug cross-remote errors.

Performance considerations

  • Naive microfrontend setups ship 2-5x the JS of a monolith due to duplicated runtimes. Module Federation shared singletons fix some of this. Hydration cost multiplies per remote. Initial load tends to regress; team velocity is the offsetting win.

Edge cases

  • A remote fails to load — shell must render a graceful fallback slot.
  • Two remotes load conflicting major versions of a shared lib.
  • Auth token expires mid-session and only one remote notices.
  • SSR + microfrontends: composition at the edge changes everything.

Real-world examples

  • Spotify — squad-owned surfaces composed at the edge.
  • Zalando — Project Mosaic, fragment-based composition.
  • DAZN — Module Federation across team-owned remotes.
  • IKEA — federation for product surfaces.

Senior engineer discussion

Seniors frame microfrontends as Conway's Law applied to the UI: ship your org chart. They argue strongly against premature adoption, insist on a shared design system contract before the first remote ships, and design for graceful degradation when a remote fails. They quantify the bundle/perf cost and weigh it against team-velocity gains before recommending.

Related questions