Micro-Frontend Architecture
1. Overview
Definition: A micro-frontend (MFE) is an architectural style that decomposes a single web frontend into several small applications that can be developed, tested, and deployed independently by business domain, and then integrates them into one user-facing screen through composition at runtime or build time.
Unlike microservice architecture (MSA), which splits the backend into business-capability units to secure per-service autonomy, a traditional frontend often remains a single giant single-page application (SPA). In that case dozens of teams deploy the backend independently, yet the screen is bound to one codebase, one build, and one deployment pipeline, so the frontend becomes the bottleneck for the whole organization. Micro-frontends are an attempt to solve this "frontend monolith" problem by extending the autonomous deployment and team ownership gained on the backend all the way to the presentation layer.
The essence of this architecture is not "a technique for chopping screens into small pieces" but "a technique for drawing boundaries so that an organization can deliver value independently." According to Conway's Law, a system's structure mirrors the communication structure of the organization that built it. Therefore, when many teams share one SPA, the cost of code conflicts, release coordination, and regression testing explodes in proportion to the number of teams. Micro-frontends align organizational structure with architecture by taking a business domain (e.g., search, product detail, cart, checkout) as a vertical slice so that each team fully owns one capability from backend to screen.
1.1 Background and Necessity
First, the frontend deployment bottleneck has intensified in large organizations. Screen-heavy services such as e-commerce, portals, and fintech let dozens of teams add features to a single SPA, so one team's small change triggers a build, regression test, and deployment of the entire application. Because every team must board the release train, even a ready feature is delayed by other teams' schedules. Micro-frontends break this coupling by deploying each slice through an independent pipeline.
Second, the demand for gradual evolution of the tech stack and legacy modernization has grown. Frameworks change significantly on a 3–5 year cycle (e.g., AngularJS→Angular, class components→React Hooks), but a single SPA cannot easily adopt new technology short of a full replacement. Micro-frontends can let different frameworks and versions coexist per screen fragment, so combined with the earlier [[strangler-fig-pattern]] they enable gradual modernization of the presentation layer.
Third, team autonomy and scalability have become organizational competitiveness. For a stream-aligned team to own a user journey end to end, it must own not only the backend API but also the screen that consumes that API. Because subordinating the frontend to a separate team raises cognitive load and handoff cost, micro-frontends are also a product of organizational design that extends "You build it, you run it" to the screen.
1.2 Core Design Principles
The first principle of micro-frontends is independent deployability. Each MFE must be deployable to production through its own CI/CD pipeline regardless of other fragments' release schedules; when this does not hold, it becomes a distributed monolith that is an MFE in name only.
The second principle is isolation of team code. When fragments are implicitly coupled through global variables, global CSS, or shared runtime state, one team's change breaks another team. Therefore style, JavaScript execution context, and state are isolated at fragment boundaries, and fragments communicate only through explicit contracts (browser events, URL, props).
The third principle is cautious allowance of technology independence (polyglot). The ability to mix different frameworks is a capability, not a goal. Considering bundle duplication and runtime overhead, it is practically desirable to converge on one base stack and allow a heterogeneous stack only when there is a legitimate reason such as legacy migration or M&A integration.
2. Overall Structure and Components
Micro-frontends do not work with fragments alone. They are composed together with a container (shell) that receives user requests and places and assembles fragments, an integration layer that discovers and loads fragments, management of inter-fragment communication, routing, and shared dependencies, and a design system that guarantees design consistency.
flowchart TB
U["User Browser"] --> Shell["Container Shell(App Shell)"]
Shell --> Router["Routing / Orchestration"]
Router --> MFE1["MFE-Search (Team A)"]
Router --> MFE2["MFE-Product Detail (Team B)"]
Router --> MFE3["MFE-Cart / Checkout (Team C)"]
MFE1 --> BFF1["BFF / API (Team A)"]
MFE2 --> BFF2["BFF / API (Team B)"]
MFE3 --> BFF3["BFF / API (Team C)"]
Shell -.shared.-> DS["Design System / Shared Library"]
Shell -.shared.-> Bus["Event Bus / Shared State Contract"]
subgraph IndepDeploy["Per-team Independent CI/CD Pipeline"]
MFE1
MFE2
MFE3
end
The container shell is a thin skeleton that provides the common layout (header, footer, navigation), the authentication session, and the entry point for global routing. Because a shell that grows thick becomes a new bottleneck itself, the principle is that the shell decides only "what to load and when" while delegating concrete screen logic to each fragment.
The integration (orchestration) layer decides which fragment to place at which URL/region and loads the fragment's assets (JS/CSS). When this layer operates at build time it is build-time integration, at the server it is server-side integration, and in the browser it is runtime integration (Chapter 3).
Each fragment completes a vertical slice with its own BFF (Backend for Frontend) or API. The design system and shared event contracts are the minimal common foundation that lets fragments keep visual and behavioral consistency, and version management of this common foundation becomes the core challenge of MFE governance.
3. Composition Methods and Detailed Architecture
Composition is divided according to "when and where fragments are combined into one screen." Below is a detailed view of how webpack/Rspack Module Federation, the representative technique of runtime integration, operates.
sequenceDiagram
participant B as "Browser"
participant H as "Host (Container)"
participant R as "Remote (MFE Fragment)"
participant S as "Shared Scope"
B->>H: Page request / load Host bundle
H->>S: "Register shared deps(react etc.)"
H->>R: "Request remoteEntry.js(remote manifest)"
R-->>H: "Return exposed modules / shared version info"
H->>S: "Version negotiation(single instance on duplicate)"
H->>R: "Lazy-load needed module chunks(lazy)"
R-->>B: "Render fragment(mount into Host DOM)"
Note over H,R: Fragment deploys independently; Host consumes latest fragment without rebuild
A. Build-time integration publishes each fragment as an npm package and lets the container include it as a dependency and bundle it into one. Type safety and initial loading performance are good, but the container must be rebuilt and redeployed whenever a fragment changes, so it violates the independent deployment principle. Therefore it is closer to component reuse than to a pure MFE, and it is reasonable to use it only for common widgets that rarely change.
B. Server-side integration has the server combine multiple fragments' HTML pieces and respond with a complete page; representative examples are SSI (Server Side Includes), Edge-Side Includes (ESI), or Node.js assembly servers such as Zalando's Tailor and FINN.no's Podium. Because the initial render is delivered as completed HTML, it is favorable for First Contentful Paint (FCP) and SEO, and there is no assembly load even on low-spec devices. On the other hand the complexity and latency of the server assembly layer increase, and if one fragment is slow the whole page response can be delayed, so timeout and fallback design is essential.
C. Runtime (client) integration has the browser dynamically load a fragment's assets and mount them into the DOM, and it is further divided by implementation detail.
The iframe approach has the strongest isolation but is weak in routing, resizing, accessibility, and SEO.
Web Components (Custom Elements + Shadow DOM) are strong in style isolation through standards-based encapsulation.
single-spa standardizes the lifecycle (bootstrap/mount/unmount) of apps in multiple frameworks so they coexist on one screen.
Module Federation is currently the most widely used technique, in which fragments directly load each other's code at runtime and negotiate shared dependencies to reduce bundle duplication.
D. Edge-side integration assembles fragments at the CDN edge (e.g., ESI, edge functions) to distribute server load and reduce latency, and it is adopted as an extended form of server-side integration in media and commerce that handle global traffic.
| Integration Method | Assembly Time | Independent Deploy | Initial Perf / SEO | Isolation | Representative Tech |
|---|---|---|---|---|---|
| Build-time | Build | ✕(rebuild needed) | Excellent | Medium | npm package |
| Server-side | Server request | ○ | Excellent | Medium | SSI·ESI·Tailor·Podium |
| Runtime | Browser | ◎ | Moderate(needs care) | iframe: strong / else medium | Module Federation·single-spa·Web Components |
| Edge-side | CDN edge | ○ | Excellent | Medium | ESI·Edge Functions |
4. Cross-cutting Concerns: Routing, State Sharing, Style Isolation, Communication
Routing is dualized into the shell's global routing and the local routing inside a fragment.
The shell decides which fragment to delegate the top-level path (/search, /cart) to, while detailed paths are managed by each fragment itself.
When this boundary is ambiguous, state drifts on back navigation, deep links, and refresh, so a design that treats the URL as an inter-fragment contract and reflects state in the URL is robust.
State sharing is the most sensitive topic in MFE. When fragments share a single global state store (e.g., a single Redux store), coupling becomes strong and independence collapses. Therefore the principle is to share only truly common minimal state such as auth tokens and user profiles, and to loosely connect inter-fragment interaction through browser CustomEvent or a publish-subscribe (pub/sub) event bus. For example, when the product detail fragment publishes an "add to cart" event, the header's cart-counter fragment subscribes and updates, cooperating without direct dependency.
Style isolation must be designed because of CSS's global nature. Prevent per-fragment style leakage with CSS Modules, CSS-in-JS, BEM prefixes, Shadow DOM, and so on, while guaranteeing visual consistency with shared design tokens (color, spacing, typography) and design system components. Because isolation and consistency are conflicting goals, the balance of "share tokens, isolate implementation" is close to the practical answer.
5. Comparison and Adoption Judgment
Micro-frontends are not a panacea but a product of trade-offs. A single SPA is simple to develop and makes bundle optimization, type sharing, and refactoring easy, but as teams grow the deployment bottleneck and code coupling increase. Conversely, MFE gains team autonomy and independent deployment but newly takes on bundle bloat from shared-dependency duplication, complexity of operation and observation, and the burden of managing version consistency across fragments.
| Category | Single SPA (Monolithic) | Micro-Frontend |
|---|---|---|
| Deployment unit | Whole application | Independent per fragment |
| Team scalability | Bottleneck as teams grow | Per-team autonomy(horizontal scale) |
| Tech stack | Single, unified | Different per fragment allowed |
| Initial load performance | Optimization-friendly | Shared-dependency management needed |
| Operational complexity | Low | High(observation, coordination) |
| Suitable scale | Small/medium, single team | Large, many teams |
The root cause of the difference is the location of coupling. A single SPA couples all code at build time to gain consistency and optimization but leaves organizational coupling. MFE defers coupling to the runtime/organizational boundary to gain autonomy, but at the cost of new failure points: runtime integration failure, version mismatch, and performance degradation. Therefore, if there are three or fewer teams and the screen is not large, adopting MFE is over-engineering, and "whether five or six or more teams contribute to one frontend simultaneously so that deployment is actually a bottleneck" becomes the practical criterion for adoption.
The trade-off is clear in practice. Zalando adopted the Mosaic project and the Node.js-based server-side assembler Tailor to let many teams independently develop large commerce screens, assembling fragments on the server. DAZN, IKEA, HelloFresh, American Express, and others are also known to have adopted MFE for team autonomy and gradual modernization, and in common "organizational scaling" was the primary driver of the technology choice.
6. Deep Dive: Latest Trends and Standard Changes
The latest trend in micro-frontends can be summarized as decoupling the runtime from the build tool. Module Federation, built into webpack 5 in 2020, became the de facto standard for MFE implementation by having fragments load each other's code at runtime and negotiate shared dependencies. Module Federation 2.0, stabilized in 2026, decoupled the runtime from a specific bundler and evolved to broadly support not only webpack but also Rspack, Rollup, Rolldown, Rsbuild, Vite, and Metro.
The main advances of MF 2.0 are as follows. First, it provides dynamic TypeScript type hints so the interface of a remote fragment can be consumed as safely as at compile time. Second, it provides runtime plugins, preloading, and dedicated developer tools (Chrome DevTools) to improve observability and performance tuning. Third, with first-class Node.js runtime support, remote modules can be consumed even in server-side rendering (SSR) and BFF, so the boundary of client-server integration is blurring.
Meanwhile, alternatives based on standard web technologies are also growing.
Using browser-native import maps and Web Components reduces bundler dependence and enables framework-neutral fragment assembly, so research and tooling on "bundler-independent federation" is increasing.
In addition, server/edge assembly (Podium, ESI, edge functions) is drawing attention again in commerce and media with strong Core Web Vitals and SEO demands.
In sum, recent trends converge on "standardization of runtime integration, bundler independence, and fusion with server/edge rendering," and from the professional engineer's perspective it is important to understand this direction rather than a specific tool.
7. Considerations and Implications
First (adoption strategy), a micro-frontend is an organizational design decision before it is a technical one. By Conway's Law, team boundaries and domain boundaries must be aligned first, and when teams are few or domain boundaries are unclear, MFE increases complexity more than benefit. Even when adopting, separate gradually starting from the most bottlenecked domain in the [[strangler-fig-pattern]] way rather than a full switch, and establish clear completion and integration criteria.
Second (trade-off), the cost of autonomy is performance and consistency. Because the bundle bloats when the framework runtime is loaded redundantly per fragment, shared-dependency versions must be standardized and a single instance kept via Module Federation's shared scope. Because excessive version management of the design system and shared contracts again invites tight coupling, the principle of "minimal sharing, explicit contracts" must be enforced through governance along with backward-compatibility policy and versioning rules.
Third (operation/quality), a distributed structure newly requires observability and a test strategy. Place error boundaries and fallback UI so errors do not propagate across fragment boundaries, and verify that inter-fragment contracts do not break with consumer-driven contract testing. Introduce distributed tracing and a per-fragment performance budget to continuously monitor which fragment worsens Core Web Vitals, which connects with [[slo-error-budget]]-based reliability management.
Fourth (outlook/related tech), MFE is completed when combined with the backend's [[msa]], operations' [[ci-cd-pipeline]] and [[gitops]], and organizational theory (Team Topologies, Conway's Law). As fusion with server/edge rendering, bundler-independent runtimes, and AI-based code generation raise fragment development productivity, the scope of MFE will widen, but the point that "organizational maturity to handle complexity" determines success or failure of adoption does not change. Therefore a professional engineer must be able to prescribe whether to adopt and which integration method to use based on the context of organization size, deployment bottleneck, and modernization demand rather than on trends.
References
- Micro Frontends (Cam Jackson, martinfowler.com): https://martinfowler.com/articles/micro-frontends.html
- Micro Frontends (micro-frontends.org): https://micro-frontends.org/
- Module Federation official docs: https://module-federation.io/
- Module Federation 2.0 Reaches Stable Release (InfoQ, 2026): https://www.infoq.com/news/2026/04/module-federation-2-stable/
- Rspack Module Federation guide: https://www.rspack.org/guide/advanced/module-federation
- single-spa official docs: https://single-spa.js.org/
In one line: A micro-frontend is an architecture that decomposes a frontend monolith by domain to secure per-team independent deployment and autonomy; around build/server/runtime/edge integration methods and Module Federation, one must prescribe the trade-offs of performance, consistency, and operational complexity to fit organizational maturity.