Micro Frontends Architecture & System Design
Deep dive into shell-remote topology, Module Federation runtime composition, failure recovery, routing boundaries, and telemetry tracing.
What are Micro Frontends, and why do large teams use them?
When would you reject Micro Frontends in a system design interview?
Visual Architecture Flowcharts
High-Level Architecture
Global Layout
Header, Sidebar, Footer
Auth Bootstrap
Session & JWT Refresh
Route Resolver
Dynamic remote mounting
The host shell app acts as the container, orchestrating runtime composition, common layouts, and authentication while loading remotes on demand.
Runtime Loading Sequence
User opens /cart route
Browser fetches core container shell code
Shell matches route & checks dynamic manifest
Resolves Cart Remote CDN address from remoteEntry.js
Browser lazy loads Remote Entry bundle
Downloads remoteEntry.js script to mount exposed chunks
Shell loads dynamic entry and resolves shared singletons
React framework checks bounds and locks dependency singletons
Cart Remote mounts inside Shell container and calls API
Component mounts in slot and updates UI view dynamically
In runtime composition, the shell does not bundle every micro app at build time. Instead, it dynamically loads remote entry manifests at runtime when navigating to routes.
Build-Time vs Run-Time Integration
Drawback: Redeploying any minor feature requires compiling the full shell container and coordinates coordination releases.
Benefit: Autonomy to roll out updates and roll back errors without redeploying the shell.
Build-time integration packages micro frontends as npm libraries, coupling versions at compile-time. Run-time integration loads remote modules dynamically, enabling independent deployment cycles.
Remote Failure Recovery Flow
Graceful degradation: The Error Boundary isolates script exceptions, preventing global white screens. Telemetry logs detail remoteName: cartApp and rollbacks resolve routing.
When a remote micro frontend fails to resolve or throws a runtime error, the shell isolates the failure using localized Error Boundaries and falls back to a graceful degraded state.
Where should authentication live in a Micro Frontend architecture?
How do you prevent one broken remote from crashing the full application?
Decoupled Communication Design
Best For: Route-level navigation configs like search filters, page IDs, categories.
Risk/Tradeoff: Size constraints and visible to user (no sensitive tokens).
Best For: Immediate, cross-app UI triggers (like incrementing a header cart count).
Risk/Tradeoff: Can lead to event sprawl and harder debugging if overused.
Best For: Durable business data transitions (e.g. updating product inventory).
Risk/Tradeoff: Requires database writes and network latencies.
Best For: Complex state mappings within a single MFE.
Risk/Tradeoff: Tightly couples remotes to schema definitions, breaking independent deploys.
Performance Risk Mitigation
Cause: Misaligned or unconfigured shared dependencies in bundler config.
Solution: Use the Webpack Module Federation plugin 'shared' key to declare libraries as singletons.
Cause: Sequentially loading remote Entry scripts inside script tags dynamically.
Solution: Implement route-level preloading (e.g. load Checkout remote bundle when user opens Cart).
Cause: CDN endpoint outages or server crashes returning 404.
Solution: Wrap mount components in React Error Boundaries and configure CDN routing fallback pointers.
Cause: Lazy-loaded remote UI mounting late and pushing page flows.
Solution: Reserve grid dimensions and render styled loading skeletons in remote slots.