Micro-Frontend Architecture Diagrams: Module Federation & Shell-Remote Patterns (2026)
How to create micro-frontend architecture diagrams. Covers Module Federation 3.0, shell/remote topology, shared dependencies, cross-MFE communication, Islands Architecture, and deployment pipelines — with AI prompt templates.
A micro-frontend architecture decomposes a web application's frontend into a set of independently deployable units — each owned by a separate team, built with its own tech stack, and released on its own schedule. The architectural principle is the same as microservices, applied to the UI layer: instead of a single monolithic frontend bundle, multiple smaller applications are composed at runtime (or build time) into a cohesive user experience.
Diagramming a micro-frontend architecture is critical for onboarding engineers, aligning ownership boundaries across teams, planning deployments, and communicating the dependency graph between the shell application and its remotes. This guide covers every core component of a micro-frontend system, explains Module Federation 3.0's 2026 feature set, and provides ready-to-use AI prompt templates for generating accurate diagrams.
What is micro-frontend architecture and when should you use it?
The micro-frontend pattern is appropriate when two or more of the following conditions are true: multiple independent teams need to deploy frontend changes without coordinating releases; different parts of the application have significantly different technical requirements or update cadences; the codebase has grown to the point where a monorepo CI build takes more than 15 minutes; or the organization wants to migrate a legacy frontend incrementally rather than rewriting it all at once.
It is not appropriate for small teams (fewer than 5–6 frontend engineers), greenfield applications that don't yet have clear domain boundaries, or use cases where consistent, pixel-perfect cross-feature UX is the primary concern. The operational overhead of micro-frontends — module federation runtime, shared dependency management, cross-MFE routing — is non-trivial. A well-structured monorepo with strong module boundaries often delivers 90% of the benefit at a fraction of the complexity.
Core components of a micro-frontend architecture
Shell application (host)
The shell application (also called the host or container) is the top-level application that users load first. It is responsible for global layout, primary navigation, authentication state, and orchestrating which remote modules are loaded for a given route. The shell does not contain business logic — it is deliberately thin, acting primarily as a composition layer. It owns the global design system tokens, the shared authentication context, and the top-level routing configuration that maps URL paths to remote modules.
Remote modules
Remote modules are the individual micro-frontends — each one a self-contained application owned by a product team. A remote module exposes one or more components, pages, or feature slices via the Module Federation runtime. It is built, tested, and deployed independently. Remotes must be able to render correctly in isolation (for testing and development) and within the shell (for production). Each remote declares its own dependencies and the components it exposes; the federation runtime handles loading the remote bundle and resolving shared dependencies at runtime.
Module Federation runtime
Module Federation (originally introduced in webpack 5, now managed by the Module Federation organization) is the dominant mechanism for runtime JavaScript composition in micro-frontends. It allows the shell to load remote module bundles from separate deployment origins at runtime — not at build time. The federation runtime manages the handshake between host and remotes: it fetches the remote's manifest (the remoteEntry.js or native ESM equivalent), negotiates shared dependency versions, and dynamically imports the requested component. In 2026, Module Federation 3.0 with native ESM support means this handshake no longer requires webpack on either side.
Shared dependency graph
One of the most complex aspects of micro-frontend architecture is the shared dependency graph. React, React DOM, a design system library, and shared utility packages must be loaded once — not once per remote. Module Federation's shared scope mechanism negotiates which version of a shared package is loaded at runtime, based on singleton constraints and semver compatibility rules. The shared dependency configuration must be explicitly diagrammed: which packages are shared as singletons (React), which are shared with version negotiation (router, state management), and which are bundled independently per remote.
Cross-MFE event bus
Micro-frontends that need to communicate without creating tight coupling use a cross-MFE event bus. This is typically a publish/subscribe system exposed from the shell's shared scope — implemented as a simple custom event emitter on the global window object or as a shared singleton module via Module Federation. Examples of cross-MFE events include "user logged out," "cart item count changed," "notification dismissed," and "theme toggled." Direct prop passing between remotes is an anti-pattern — if two remotes need to share state, the state should live in the shell or in a shared singleton exposed via the federation runtime.
Module Federation 3.0 in 2026
Module Federation 3.0, released in late 2025, introduced two capabilities that significantly change how micro-frontend architectures are designed and diagrammed:
- Native ESM federation: Remotes can now expose native ES modules rather than webpack bundles. The host imports them via dynamic
import()with no webpack runtime required on either side. This unlocks Vite, Rollup, and esbuild as build tools for both shell and remote applications, and makes the architecture compatible with browser-native module loading without a bundler intermediary. - Federated TypeScript types: The Module Federation 3.0 runtime can generate and serve TypeScript type definitions for remote module exports, consumed automatically by the host at development time. This eliminates the manual type stub files that plagued earlier Module Federation setups and enables proper IDE autocomplete and type checking across the shell/remote boundary without a monorepo.
Micro-frontend vs. alternatives comparison
| Dimension | Micro-frontends | Monolithic frontend | Frontend monorepo |
|---|---|---|---|
| Deployment | Independent per team | Coordinated, single release | Per-package or coordinated, depends on CI config |
| Team ownership | Hard ownership by domain | Shared ownership, coordination required | Shared repo, team boundaries by convention |
| Tech stack flexibility | Each remote can use a different framework | Single framework for all features | Single framework, shared tooling |
| Initial load performance | Higher latency — multiple remote fetches at runtime | Single bundle, simpler caching | Optimized via code-splitting, tree shaking |
| Operational complexity | High — federation runtime, shared deps, versioning | Low | Medium — build tooling complexity |
| Best for | Large orgs, multiple product teams | Small teams, early-stage products | Mid-size teams, shared design system |
Architecture patterns with prompt templates
Basic shell + two remotes
Enterprise MFE with Backend for Frontend (BFF)
Islands Architecture
Multi-cloud MFE deployment
Deployment and CI/CD considerations
Micro-frontend CI/CD pipelines must be designed so that deploying one remote cannot break the shell or other remotes. Key principles:
- Independent pipelines per remote: Each remote module has its own CI/CD pipeline triggered by changes to its source directory. The shell pipeline is only triggered by changes to the shell itself — not by remote deployments.
- Contract testing between shell and remotes: The shell must test that each remote's exposed API (component props, event bus event names) has not broken its contract before a remote is promoted to production. Module Federation 3.0's federated types make this testable at the TypeScript level.
- Versioned remote manifests: Remote bundles should be deployed to versioned paths (e.g.,
/v1.4.2/remoteEntry.js) rather than a mutable/latest/remoteEntry.js. The version registry controls which version is active in each environment, enabling instant rollback without redeployment. - Canary deployments per remote: Route a percentage of traffic to a new remote version while the majority remain on the stable version. Monitor error rates and performance metrics for the canary cohort before promoting to 100%.
- Shared dependency version governance: A shared dependency like React must not have its version bumped by one team without coordinating with all other teams. Enforce this with a bot that fails CI if a remote's shared dependency version diverges from the shell's approved version list.
Common mistakes in micro-frontend architecture
- Splitting by technical layer rather than business domain — creating a "header remote," "footer remote," and "sidebar remote" replicates the problems of a monolith without the independence benefits; split by product domain (checkout, catalog, profile) instead
- Not managing shared dependencies explicitly — leaving shared dependencies to version negotiation at runtime leads to multiple versions of React loading simultaneously, breaking React context and event propagation
- Direct imports between remotes — one remote importing directly from another (not through the shell's shared scope) creates hidden coupling and breaks independent deployability
- No graceful fallback when a remote fails to load — if a remote bundle is unavailable, the shell must show a meaningful fallback UI, not a blank section or an uncaught error that crashes the entire page
- Treating the shell as a feature application — the shell should be extremely thin; putting business logic in the shell defeats the purpose of micro-frontends by creating a bottleneck every team must deploy through
- Ignoring initial load performance — each additional remote add a network round-trip at page load; use lazy loading, prefetching, and CDN placement close to users to keep Time to Interactive competitive with a monolith
- Using micro-frontends for a team of under six engineers — the operational overhead (federation runtime, versioning, cross-MFE contract testing, multi-pipeline CI) is substantial; smaller teams almost always build better products faster with a monorepo
Frequently asked questions about micro-frontend architecture
What is the difference between Module Federation and an iframe-based micro-frontend?
Module Federation loads remote JavaScript modules directly into the host application's runtime — they share the same DOM, CSS cascade, and JavaScript globals (with explicit shared scope management). This enables tight visual and behavioral integration: a remote component renders inside the shell's layout with full access to shared design tokens and context providers. iframes provide complete isolation — each remote runs in a separate browsing context with its own DOM, styles, and JavaScript environment. Iframes are simpler to reason about from a security and isolation perspective but create UX challenges: modals can't escape the iframe boundary, routing must be synchronized manually, and consistent styling requires explicitly passing CSS variables. Module Federation is the right choice when tight UI integration matters; iframes are appropriate for embedding genuinely independent applications (e.g., a third-party analytics widget or a legacy application you don't control).
How do micro-frontends handle authentication?
Authentication in a micro-frontend architecture is owned by the shell and shared downward to remotes via a singleton auth context exposed through Module Federation's shared scope. The shell performs the login flow, stores the session token (typically in an HttpOnly cookie or localStorage), and exposes a React context (or framework-agnostic auth singleton) that all remote modules consume. Remotes should never implement their own login flows. For API calls, remotes either read the session token from the shared context or rely on browser cookies — depending on whether their BFF is same-origin or cross-origin. Cross- origin remotes that need to pass auth tokens to their BFFs should receive the token from the shell's shared auth context, not re-implement token storage themselves.
Can micro-frontends use different frameworks (React, Vue, Angular)?
Yes — this is one of the core use cases for micro-frontends, especially when migrating a legacy Angular or Vue application to React incrementally. Module Federation 3.0 supports cross-framework composition: a React shell can load a Vue 3 remote component, wrapped in a thin framework- agnostic adapter (e.g., a web component wrapper or a custom element bridge). In practice, cross-framework composition is architecturally possible but operationally expensive: each framework ships its own runtime, shared dependencies like design systems may not work across frameworks, and debugging cross-framework interactions is complex. The recommended approach is to use cross-framework composition only as a migration strategy — new remotes should converge on a single framework. Your architecture diagram should explicitly annotate which framework each remote uses, since this determines the runtime bundle size and compatibility constraints.
Related guides: Microservice architecture patterns, API gateway architecture diagrams, and Microservice architecture diagrams.
Ready to try it yourself?
Start Creating - Free