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.
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
- Composition model: federation vs. iframes vs. SSI.
- Shared runtime: how do remotes share React, design system, auth context?
- Routing: shell-owned or per-microfrontend?
- State: each remote isolated, or shared store with contracts?
- Versioning: how do remotes signal breaking changes?
- 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.