Article Guide
Senior16 min readJune 12, 2026

Module Federation Deep Dive for Micro Frontends

Understand webpack Module Federation from fundamentals to production architecture, including host, remote, remoteEntry.js, exposes, shared dependencies, singleton React, runtime loading, deployment, and failure handling.

Tags:
Module FederationMicro FrontendswebpackFrontend ArchitectureInterview Prep

Module Federation is one of the most popular ways to build micro frontends in modern JavaScript applications.

It allows one frontend application to load code from another frontend application at runtime.

That one idea unlocks a powerful architecture:

textEditor
Different teams
Different codebases
Different builds
Different deployments
One composed user experience

But Module Federation is also easy to misunderstand.

It is not just a way to import components from another app.

It is a runtime architecture pattern that affects deployment, dependency sharing, versioning, testing, rollback, and observability.

This guide explains Module Federation from beginner level to production architect level.

1. What Is Module Federation?

Module Federation is a webpack 5 feature that allows multiple independently built applications to share and consume code at runtime.

In simple words:

One application can expose code, and another application can load that code when needed.

Example:

textEditor
Product App exposes ProductList
Shell App loads ProductList at runtime

This is useful for micro frontends because the shell app does not need to bundle every feature during its own build.

Instead, each remote app can be built and deployed independently.

2. Why Module Federation Matters

Before Module Federation, frontend applications usually shared code in these ways:

textEditor
npm packages
monorepo libraries
script tags
iframes
build-time imports

These approaches work, but they have limitations.

ApproachLimitation
npm packageRequires rebuilding consumers after package updates
Monorepo libraryOften still tied to one build/release process
Script tagHarder dependency and type management
iframeStrong isolation but poor UX integration
Build-time importNo true independent runtime deployment

Module Federation solves a specific problem:

How can one app consume another app’s code without rebuilding itself every time?

That is why it is powerful for micro frontends.

3. Core Mental Model

Think of Module Federation like this:

textEditor
Remote App
exposes something

Host App
consumes that exposed thing

Example:

textEditor
cartApp exposes CartPage
shellApp consumes CartPage

Architecture:

architecture diagram
┌────────────────────┐
│     Shell App      │
│      Host          │
└─────────┬──────────┘
        │ loads at runtime
        ▼
┌────────────────────┐
│     Cart App       │
│     Remote         │
│ exposes CartPage   │
└────────────────────┘

The shell does not directly own the cart code.

The cart team can build and deploy the cart remote independently.

4. Important Terms

TermMeaning
HostApplication that consumes remote modules
RemoteApplication that exposes modules
ExposesModules/components made available by a remote
RemotesRemote applications configured inside the host
remoteEntry.jsRuntime manifest used by host to discover and load remote modules
Shared dependenciesLibraries shared between host and remote
SingletonShared dependency loaded as one instance
Eager loadingLoads dependency upfront
Lazy loadingLoads remote only when needed

5. Host Application

The host is usually the shell app.

It owns:

  • Global layout
  • Navigation
  • Top-level routes
  • Authentication bootstrap
  • Remote loading
  • Fallback UI
  • Error boundaries

Example:

textEditor
Shell App
├── Header
├── Navigation
├── Auth Guard
├── Route Config
└── Remote Loader

The host consumes modules from remote apps.

Example:

textEditor
/products → load productApp/ProductList
/cart → load cartApp/CartPage
/checkout → load checkoutApp/CheckoutPage

The host should coordinate composition. It should not become a place where every remote’s business logic is dumped.

The host should own composition concerns, not domain business logic.

6. Remote Application

The remote is an independently built application that exposes modules.

Example:

textEditor
Product Remote
├── ProductListPage
├── ProductFilters
├── ProductCard
└── Product API client

The remote may expose:

  • Page components
  • Widgets
  • Feature modules
  • Route configs
  • Utility modules

Example:

textEditor
productApp exposes:
- ProductListPage
- ProductDetailsPage
- ProductRecommendationsWidget

In a clean architecture, a remote owns its business domain.

The product remote should own product listing logic. The cart remote should own cart logic. The checkout remote should own checkout logic.

7. What Is remoteEntry.js?

remoteEntry.js is the runtime entry file generated by the remote application.

It acts like a manifest that tells the host:

  • What modules are exposed
  • Where chunks can be loaded from
  • How dependencies should be resolved
  • How runtime loading should happen

Runtime flow:

textEditor
Shell App
    │
    │ fetches remoteEntry.js
    ▼
Remote container initialized
    │
    │ resolves exposed module
    ▼
Remote chunks loaded
    │
    ▼
Remote component rendered

Without remoteEntry.js, the host does not know how to load the remote.

8. Runtime Loading Flow

When a user visits a route, this is what can happen:

textEditor
User opens /cart
    │
    ▼
Shell app loads
    │
    ▼
Shell checks route configuration
    │
    ▼
Shell identifies cartApp remote
    │
    ▼
Shell fetches cart remoteEntry.js
    │
    ▼
Shell loads exposed CartPage module
    │
    ▼
Cart remote chunks load
    │
    ▼
CartPage renders inside shell
    │
    ▼
Cart API fetches cart data
    │
    ▼
Cart UI appears

This is runtime composition. The cart app can be deployed separately from the shell.

9. Build-Time Import vs Runtime Federation

This distinction is very important.

Build-Time Import

textEditor
Shell imports ProductList during build
Shell bundle contains ProductList
Changing ProductList requires shell rebuild

Example:

typescriptEditor
import { ProductList } from "@company/product";

Runtime Federation

textEditor
Shell loads ProductList at runtime
ProductList comes from product remote
Product remote can deploy independently

Conceptually:

Build-time import = coupled at build time. Runtime federation = connected at runtime.

Comparison:

AreaBuild-Time ImportRuntime Federation
DeploymentConsumer rebuild neededRemote can deploy independently
Runtime riskLowerHigher
SimplicitySimplerMore complex
Team autonomyLowerHigher
Version controlPackage versionRuntime manifest/version strategy

10. Exposes

exposes define what a remote makes available to other apps.

Example:

textEditor
cartApp exposes:
./CartPage
./CartDrawer
./CartSummary

The host can then consume these exposed modules.

Good exposes are stable and intentional. Bad exposes leak internal implementation details.

Good Exposes PracticeBad Exposes Practice
Expose CartPageExpose internal reducer
Expose CartWidgetExpose random utility
Expose route configExpose private component
Expose API implementation details

Expose stable public contracts, not internal implementation details.

11. Remotes

The host configures which remotes it can load.

Example conceptual mapping:

textEditor
productApp → https://cdn.company.com/product/remoteEntry.js
cartApp → https://cdn.company.com/cart/remoteEntry.js
checkoutApp → https://cdn.company.com/checkout/remoteEntry.js

The shell uses this mapping to know where to fetch each remote.

In production, this mapping may come from:

  • Static config
  • Environment variables
  • Remote manifest service
  • Feature flag service
  • Deployment registry

The more dynamic the setup, the more governance you need.

12. Shared Dependencies

Shared dependencies are libraries used by both host and remotes.

Examples:

  • React
  • React DOM
  • Design system
  • Router package
  • Analytics SDK
  • Auth SDK
  • Utility libraries

Without proper sharing, each remote may load its own copy.

That can cause: large bundle size, duplicate React instances, hook errors, inconsistent state, runtime crashes, and version conflicts.

Shared dependency management is one of the most important production concerns in Module Federation.

13. Singleton Dependencies

A singleton dependency is loaded only once and shared across host and remotes.

React is the classic example.

Why? Because multiple React instances can cause serious issues, especially with hooks and context.

Shell uses React instance A. Remote uses React instance B. Shared context or hooks behave unexpectedly.

Recommended config list:

  • React → singleton
  • React DOM → singleton
  • Design system runtime → often singleton
  • Auth SDK → often singleton
  • Analytics SDK → depends on architecture

But do not mark everything as singleton blindly. Overusing singleton dependencies creates hidden coupling.

14. Dependency Sharing Strategy

Dependency TypeRecommendation
React / React DOMShare as singleton
Design systemShare with strict versioning
RouterBe careful; routing ownership matters
Utility functionsUsually avoid runtime sharing unless stable
API clientsKeep domain-owned
Business logicDo not share through federation casually
State storesAvoid global shared state unless required

Strong rules to enforce:

  • Share platform-level dependencies.
  • Keep business logic inside the owning domain.

Bad architecture coupling examples:

  • Cart remote imports product business logic from product remote.
  • Checkout remote depends on cart internal reducer.
  • Shell imports internal functions from every remote.

This creates distributed coupling.

15. Version Mismatch Problems

Version mismatch is a common production issue.

Example: Shell expects productApp/ProductList v2 props, but product remote deploys ProductList v3 with breaking props, causing the shell to crash at runtime.

Possible mismatch issues:

  • Breaking prop changes
  • Changed event payloads
  • Missing exposed module
  • Different shared dependency version
  • Removed route contract
  • Remote deployed before shell is compatible

Recommended solutions:

  • Versioned contracts
  • Contract tests
  • Backward-compatible changes
  • Deployment promotion checks
  • Feature flags
  • Version pinning
  • Remote manifest governance

Independent deployment requires compatibility discipline.

16. Remote Loading Failures

Because remotes are loaded at runtime, they can fail.

Common causes:

  • remoteEntry.js is unavailable
  • CDN outage
  • Network failure
  • Wrong remote URL
  • Remote deployed with bad bundle
  • Shared dependency conflict
  • Chunk loading error
  • CORS issue
  • Cache mismatch
Bad Behavior DesignGood Behavior Design
Remote fails → full shell crashesRemote fails → fallback UI appears. Shell remains usable. Error is logged with remote name and version

Fallback example text: Cart is temporarily unavailable. Please refresh or try again later.

17. Error Boundary Strategy

Each remote should be wrapped with an error boundary.

textEditor
Shell App
├── Product Remote
│   └── Error Boundary
├── Cart Remote
│   └── Error Boundary
└── Checkout Remote
  └── Error Boundary

The error boundary should capture: remoteName, remoteVersion, route, user action if available, error message, stack trace, and deployment version.

For critical flows like checkout, you may need stronger fallback strategies:

  • Retry loading remote
  • Redirect to stable fallback route
  • Disable feature flag
  • Rollback remote version
  • Show support message

18. Lazy Loading Remotes

Do not load every remote upfront.

Bad setup example:

textEditor
User opens homepage
Shell loads catalog
Shell loads cart
Shell loads checkout
Shell loads profile
Shell loads orders

Good setup example:

textEditor
User opens homepage
Shell loads only required remotes
Cart remote loads when user visits /cart
Checkout remote loads when user visits /checkout

Lazy loading improves initial load performance. But for critical paths, you can preload strategically.

Example: When a user adds an item to the cart, preload the checkout remote in the background to improve checkout transition speed.

19. Caching Strategy

Caching is tricky with Module Federation.

If remoteEntry.js is cached too aggressively, the shell may load old remote metadata. If chunks are not cached properly, performance suffers.

Common caching strategy:

  • remoteEntry.js → short cache or versioned URL
  • hashed chunks → long cache
  • manifest/config → controlled cache

Example chunks hashing:

textEditor
remoteEntry.js
main.8s7d9f.js
vendor.2a9sd1.js

Hashed chunks can be cached long-term because the filename changes when content changes. The remote entry or manifest needs careful version control.

20. Deployment Models

There are multiple deployment models.

Latest Remote Model

shell → cart/latest/remoteEntry.js

Benefit: Simple, fast independent deployment.

Risk: A bad remote deploy can break the shell immediately.

Version-Pinned Model

shell → cart/1.4.2/remoteEntry.js

Benefit: Safer compatibility, controlled rollout.

Risk: Requires release coordination.

Manifest-Based Model

jsonEditor
{
"cartApp": "https://cdn.company.com/cart/1.4.2/remoteEntry.js",
"productApp": "https://cdn.company.com/product/2.1.0/remoteEntry.js"
}

Benefit: Flexible, supports rollback, and supports environment promotion.

This is often the best production approach for large systems.

21. Rollback Strategy

Rollback must be designed before production incidents.

If the cart remote version 1.5.0 breaks, you should be able to switch back to 1.4.2 quickly.

textEditor
cartApp: 1.5.0 → broken
cartApp: 1.4.2 → stable

Rollback options include: revert remote deployment, update remote manifest, pin shell to older version, disable feature flag, or route traffic to stable remote.

Independent deployment is only safe when rollback is independent too.

22. Contract Testing

Contract testing verifies that host and remote still agree.

It can validate: exposed module exists, expected props are supported, event names are unchanged, event payload shape is compatible, route contract is stable, and shared dependency range is compatible.

Example contract payload validation:

textEditor
CartPage must accept:
- userId
- locale
- currency

CartUpdated event must emit:
- itemCount
- cartId

If the cart team changes this contract, CI should catch it before deployment. Without contract testing, runtime federation becomes risky.

23. E2E Testing

E2E tests validate full user journeys.

Example journeys:

  • Search product → add to cart → checkout
  • Login → view orders → reorder
  • Open product page → change quantity → cart count updates

E2E tests catch issues across boundaries, such as routing bugs, remote loading failures, auth context issues, shared dependency conflicts, event communication bugs, and layout integration issues.

Do not rely only on unit tests. Micro frontend bugs often happen at integration points.

24. Observability

Module Federation requires per-remote observability.

Track metrics such as: remote load time, remote load failure, remote version, route where remote loaded, JavaScript errors by remote, chunk loading errors, Web Vitals by route, deployment health, and fallback UI frequency.

Useful log fields example:

jsonEditor
{
"remoteName": "cartApp",
"remoteVersion": "1.4.2",
"route": "/cart",
"shellVersion": "2.0.1",
"userSessionId": "session_982a1s",
"errorType": "ChunkLoadError",
"chunkUrl": "https://cdn.company.com/cart/chunks/312.js"
}

Good observability answers: Which remote failed? Which version failed? Which route failed? Was it a network issue or runtime issue? Did the problem start after deployment? How many users were affected?

25. Security Considerations

Module Federation loads code at runtime, so security matters.

Important concerns:

  • Only load remotes from trusted origins.
  • Use HTTPS.
  • Apply strict CORS policies.
  • Avoid exposing secrets in frontend config.
  • Validate event payloads.
  • Do not pass sensitive data through browser events.
  • Use CSP where possible.
  • Protect deployment pipelines.

A remote app is still executable JavaScript running inside the user’s browser. If a remote is compromised, the user experience can be compromised.

26. Common Anti-Patterns

Avoid these common federation anti-patterns:

Anti-PatternWhy It Is Bad
Sharing everythingCreates hidden coupling
Exposing internal modulesBreaks encapsulation
Loading all remotes upfrontHurts performance
No fallback UIRemote failure breaks product
No contract testsIndependent deployment becomes unsafe
Shell owns all domain logicShell becomes new monolith
Every team uses random dependency versionsRuntime instability
No version strategyRollback becomes difficult
Latest remote always in productionHigher blast radius
No observabilityDebugging becomes guesswork

27. Production Checklist

Before using Module Federation in production, ask:

  • Do we have clear host and remote ownership?
  • Are exposed modules stable and intentional?
  • Are React and React DOM shared safely?
  • Do we have a version strategy?
  • Do we have contract tests?
  • Do we have fallback UI for remote failures?
  • Can we roll back one remote independently?
  • Are remote load errors monitored?
  • Are Web Vitals tracked per route?
  • Is remoteEntry.js caching configured carefully?
  • Are remotes loaded only from trusted origins?
  • Do we avoid sharing business internals?

If these are missing, the implementation may work locally but fail operationally.

28. Interview Questions

Q1. What is Module Federation?

Module Federation is a webpack 5 feature that allows one application to expose modules and another application to consume them at runtime. It is useful for micro frontends because independently built apps can be composed without rebuilding the host every time.

Q2. What is the difference between host and remote?

The host is the consuming application, usually the shell. The remote is the application that exposes modules. The host loads remote modules at runtime through the remote entry file.

Q3. What is remoteEntry.js?

remoteEntry.js is the runtime manifest generated by the remote. It tells the host what modules are exposed and how to load the remote chunks.

Q4. Why do we share React as a singleton?

React should usually be shared as a singleton to avoid loading multiple React instances. Multiple React instances can cause issues with hooks, context, and bundle size.

Q5. What are the risks of Module Federation?

The main risks are runtime loading failures, version mismatches, shared dependency conflicts, caching issues, and harder debugging. These risks can be reduced with fallback UI, contract testing, versioned manifests, rollback strategy, and observability.

Q6. How do you handle remote failure?

Wrap each remote with an error boundary, show fallback UI, log the error with remote name and version, and support retry or rollback for critical flows.

Q7. How do you safely deploy remotes independently?

Use versioned contracts, CI checks, contract testing, feature flags, environment promotion, release health monitoring, and rollback support.

Q8. What should not be exposed from a remote?

Internal reducers, private components, unstable utilities, and domain implementation details should not be exposed. A remote should expose stable public modules only.

29. Strong Senior Answer

If an interviewer asks: "How would you use Module Federation in a large e-commerce frontend?"

A strong answer:

I would use a shell app as the host and domain-specific remotes for catalog, cart, checkout, orders, and profile. The shell would own global layout, top-level routing, authentication bootstrap, and remote loading. Each remote would own its domain UI and business logic. I would use Module Federation to load remotes at runtime, but I would not treat it as just a component-sharing tool. I would design around production concerns: shared dependency governance, singleton React, contract testing, fallback UI, versioned remote manifests, rollback, and per-remote observability. For state, I would avoid a giant shared store. Cart and checkout state should be backend-driven, with small explicit events only where needed. The goal is independent team deployment with a consistent and reliable user experience.

30. Summary

Module Federation is powerful because it allows independently built frontend applications to compose at runtime.

It enables: independent deployment, runtime composition, team autonomy, domain-owned frontend apps, and flexible micro frontend architecture.

But it also introduces: runtime failure risk, dependency version complexity, caching challenges, contract compatibility issues, observability needs, and rollback requirements.

The best engineers do not just say "Use Module Federation." They explain how to use it safely in production.

Module Federation gives you runtime composition, but production readiness comes from contracts, versioning, fallback UI, rollback, and observability.

References

  • webpack Module Federation Documentation (https://webpack.js.org/concepts/module-federation/)
  • Module Federation Official Site (https://module-federation.io)
  • Micro Frontends (https://micro-frontends.org)
  • Micro Frontends — Martin Fowler (https://martinfowler.com/articles/micro-frontends.html)
  • AWS Prescriptive Guidance: Micro-frontends (https://docs.aws.amazon.com/prescriptive-guidance/latest/micro-frontends-aws/introduction.html)