Micro frontends: single-spa, Module Federation, and alternatives in real context
A practical comparison of single-spa, Module Federation, qiankun, and Piral for frontend architecture decisions.
Executive summary
A practical comparison of single-spa, Module Federation, qiankun, and Piral for frontend architecture decisions.
Last updated: 1/31/2026
Introduction: The Conway's Law of Frontend
Micro frontends are rarely a solution to a technical problem; they are almost exclusively an organizational response to scaling constraints. As engineering departments grow, having 50+ developers contributing to a single, monolithic React or Angular application becomes a bottleneck.
Deployments take hours. A bug in the marketing team's sidebar can break the checkout flow for the payments team. Upgrading a core dependency like the router or design system requires a coordinated, multi-quarter effort.
This is Conway’s Law in action: organizations design systems that mirror their own communication structures. Micro frontends attempt to decouple the frontend architecture so it matches the boundaries of autonomous, domain-focused squads.
However, adopting micro frontends simply because "Netflix does it" or because it’s a trending buzzword is a recipe for disaster. Wrong adoption drastically increases operational overhead, slows down local development, and results in a deeply fragmented User Experience (UX).
Evaluating the tooling landscape
There is no single "right" way to build a micro frontend architecture. The ecosystem is broadly split into two distinct philosophies: Build-time integration and Runtime orchestration.
1. Module Federation (Webpack/Rspack/Vite)
Module Federation (originally built into Webpack 5) revolutionized micro frontends by moving away from heavy frameworks. It allows JavaScript applications to dynamically load code from another application at runtime.
- How it works: App A (the host) can import a React component or utility function from App B (the remote) as if it were a local module.
- When to choose it: When your entire company uses a unified stack (e.g., everyone uses React + Webpack/Vite) and your primary goal is seamlessly sharing components and business logic at runtime without page reloads.
- The catch: Dependency management is notoriously difficult. If App A uses React 18 and App B uses React 17, runtime crashes can occur. Strictly enforcing singleton dependencies is mandatory.
2. single-spa
Where Module Federation is about sharing code, single-spa is about orchestrating lifecycles. It acts as a top-level router that decides which application to mount or unmount based on the URL.
- How it works: It requires a "Root Config" (or Shell) that registers applications. When the user navigates to
/billing, single-spa mounts the Billing Vue app. When they go to/profile, it unmounts Vue and mounts the Profile React app. - When to choose it: When you are dealing with legacy migrations (e.g., slowly strangling an old AngularJS app while building a new React app) or when different teams truly need to use different frameworks.
- The catch: The "shell" becomes a massive single point of failure and complexity. Sharing state between applications is intentionally difficult to enforce decoupling, which can frustrate developers used to global Redux stores.
3. qiankun and Piral
These are opinionated frameworks built on top of primitives like single-spa, but they offer stronger "sandbox" guarantees.
- qiankun: Born out of Alibaba, it provides an HTML-entry approach and strict JavaScript and CSS sandboxing (Shadow DOM / scoped CSS). This ensures that a rogue CSS class in the Cart app doesn't accidentally break the Header app.
- Piral: Highly opinionated, designed for portal-like enterprise applications where different plugins (pilets) are loaded into a rigid, central shell.
- The catch: You are coupling your architecture heavily to a specific meta-framework's way of doing things.
Deepening the analysis: Trade-offs and UX governance
The hardest part of micro frontends isn't routing or loading JavaScript—it's maintaining a cohesive user experience. An end-user doesn't care if the checkout is maintained by Squad A and the product page by Squad B; they expect it to look and behave like one product.
| Approach | Core Strength | Hidden Cost / Risk | Best Choice When |
|---|---|---|---|
| Module Federation | Feels like native JavaScript imports. Excellent developer experience once configured. | Dependency drift (versions getting out of sync) causes silent runtime crashes. | Teams are aligned on the tooling ecosystem (React + Webpack/Vite). |
| single-spa | Mature, framework-agnostic lifecycle orchestration. Perfect for strangler-fig legacy migrations. | The Shell orchestrator becomes highly complex. Sharing code requires externalizing dependencies (SystemJS). | Multi-framework environments or phased legacy rewrites. |
| qiankun / Piral | Strong enterprise governance with strict CSS/JS isolation and sandboxing. | Deep architectural coupling to the meta-framework. Harder to escape if the project is abandoned. | Enterprise portals with many distinct, untrusted internal modules. |
When adoption actually accelerates product delivery
Micro frontends solve ownership bottlenecks when multiple squads evolve the same product independently. They do not replace design systems or UX governance; without those, you simply move the coupling from build-time to runtime.
Decision prompts for your engineering context:
- Which organizational pain really justifies the massive orchestration overhead? (If your team has fewer than 20 frontend developers, stick to a monolith).
- How will navigation, global state (like user session), observability, and security work consistently across micro apps?
- What is your strict dependency version policy to prevent cross-app regressions?
Sprint-level optimization backlog
If you are committing to a micro frontend architecture, sequence your rollout deliberately:
Phased adoption plan
- Define global shell and navigation contracts.
- Assign domain ownership by micro app boundary.
- Standardize cross-squad design tokens and primitives.
- Set shared dependency and upgrade policy.
- Instrument errors/performance per app boundary.
- Run integration regression suites across apps.
Platform convergence metrics
Additional indicators to track:
- Cross-app regression frequency after independent releases.
- Coordination time across squads for integrated launches.
- Performance variance (LCP/INP) by micro app boundary.
Want to convert this plan into measurable execution with lower technical risk? Talk to a web specialist with Imperialis to design, implement, and operate this evolution.