CDN & Infrastructure • Modern Web
Home  /  Modern Web  /  CDN Micro Frontend Delivery
Modern Web

CDN for Micro Frontends: Module Federation and Independent Deployment

By FlyFish NWA Editorial, DevOps & Infrastructure Engineer September 4, 2026 9 min read

Micro frontends promise independent teams and independent deploys, but without a CDN-aware delivery strategy, Module Federation becomes a runtime liability. The CDN is not just a cache — it is the integration layer that makes federated modules fast, version-safe, and resilient.

When every team ships its own JavaScript bundle to production on its own schedule, the browser becomes the integrator. Webpack 5 Module Federation makes this possible by letting a host application consume remotes at runtime. The CDN determines whether that runtime integration is instant or painfully slow, consistent or broken. This guide covers the architecture, caching, and deployment patterns that make CDN-backed micro frontends work at scale.

Why Micro Frontends Need a Different CDN Strategy

Traditional single-page applications have one build, one deployment, and one cache invalidation. Micro frontends invert that model. A single page may compose five remotes owned by three teams, each deployed dozens of times per week. If you treat them like a monolith, you get version skew, long cache tails, and cascading failures.

A federated architecture introduces two distinct artifact types with opposite caching requirements:

Your CDN must serve both correctly. Understanding your CDN architecture overview is critical before you split the frontend, because origin topology, cache key design, and purge strategy directly affect federation reliability.

Core principle: Never overwrite an immutable asset. Every deployment creates new files. Only the small manifest files are updated in place, and they are versioned and purged atomically.

How Module Federation Works at the Edge

With Module Federation, the host does not bundle remote code at build time. At runtime it fetches remoteEntry.js for each remote, which registers exposed modules on window and loads the required chunks on demand.

Performance Comparison: Edge vs Origin Processing
Metric Edge Processing Origin Processing Improvement
Latency (p50)8–15 ms120–300 ms15–20x faster
Cache Hit Ratio85–95%N/AReduces origin load
TLS Handshake1–5 ms (nearby PoP)50–150 ms10–30x faster
Bandwidth Cost$0.01–0.04/GB$0.05–0.12/GB3–5x cheaper
Availability99.99% (multi-PoP)99.9% (single DC)10x fewer outages
// webpack.config.js — Host
new ModuleFederationPlugin({
  name: "host",
  remotes: {
    header: "header@https://cdn.flyfishnwa.com/mfe/header/remoteEntry.js",
    checkout: "checkout@https://cdn.flyfishnwa.com/mfe/checkout/remoteEntry.js",
    search: "search@https://cdn.flyfishnwa.com/mfe/search/remoteEntry.js"
  },
  shared: { react: { singleton: true, requiredVersion: "^18.0.0" } }
});

// webpack.config.js — Remote (team-checkout)
new ModuleFederationPlugin({
  name: "checkout",
  filename: "remoteEntry.js",
  exposes: { "./Cart": "./src/Cart", "./CheckoutFlow": "./src/CheckoutFlow" },
  shared: { react: { singleton: true } }
});

The URLs in remotes are CDN URLs, not origins. That is intentional. The browser should never contact your S3 bucket or Kubernetes ingress directly. All federation traffic flows through the edge, where you can apply optimized DNS resolution, TLS, compression, and failover.

CDN Delivery for Module Federation Diagram showing host app and three remote micro frontends delivered via CDN edge to browser BROWSER Host App imports header/cart CDN EDGE — Single Distribution /mfe/header/ remoteEntry.js TTL 120s /mfe/checkout/ remoteEntry.js TTL 120s /mfe/search/ remoteEntry.js TTL 120s Immutable chunks • *.8f3a1b.js • Cache-Control: immutable, max-age=31536000 Served from edge cache — never revalidated Edge Worker: Composes manifest • A/B • Rollback • Failover origin fetch Origins S3 / GCS / R2 per-team buckets
Figure 1: Host and remotes served from a single CDN distribution with path-based routing. Immutable assets are cached forever; only remoteEntry.js is revalidated.

Independent Deployment Without Breaking the Host

Independent deployment is the goal, but naive implementation breaks users mid-session. If team Checkout deploys a new remoteEntry.js that points to chunks that are not yet replicated to all edge PoPs, some users fetch a manifest that references 404s.

The solution is an atomic, versioned deployment pipeline:

  1. Upload immutable chunks first to object storage with Cache-Control: public, max-age=31536000, immutable. Wait for replication.
  2. Upload new remoteEntry.js to a versioned path like /mfe/checkout/v2.4.1/remoteEntry.js and also to /mfe/checkout/remoteEntry.js (the live pointer).
  3. Purge the CDN cache for the live pointer only using surrogate keys (e.g., purge key=mfe-checkout) — not a wildcard purge.
  4. Keep previous versions addressable for instant rollback and for users with long-lived sessions.

For the host, avoid hardcoding remote URLs at build time. Inject them at the edge via an edge computing worker or via a lightweight manifest JSON that the host fetches on boot:

// https://cdn.flyfishnwa.com/mfe/manifest.json — generated by CI, served at edge
{
  "header": "https://cdn.flyfishnwa.com/mfe/header/v3.2.0/remoteEntry.js",
  "checkout": "https://cdn.flyfishnwa.com/mfe/checkout/v2.4.1/remoteEntry.js",
  "search": "https://cdn.flyfishnwa.com/mfe/search/v1.9.8/remoteEntry.js"
}

// host runtime — dynamic remote resolution
const manifest = await fetch("/mfe/manifest.json").then(r => r.json());
await __webpack_init_sharing__("default");
await loadRemote(manifest.checkout); // uses Module Federation runtime API

This decouples the host deployment from remote deployments. The host can ship without rebuilding when a remote updates, and you can perform canary releases by having the edge worker return different manifests based on a cookie or percentage.

Caching Strategy: The Table That Matters

Getting cache headers wrong is the most common failure mode. Use this reference for every micro frontend artifact:

Artifact Cache-Control CDN TTL Purge Strategy
Content-hashed chunks
*.<hash>.js / .css
public, max-age=31536000, immutable 1 year (edge + browser) Never purge. New deploy = new files.
remoteEntry.js (live pointer) public, max-age=60, s-maxage=120, stale-while-revalidate=600 60–120s Surrogate key purge on deploy
Versioned remoteEntry.js
/v2.4.1/remoteEntry.js
public, max-age=31536000, immutable 1 year Never purge. Immutable.
manifest.json public, max-age=30, s-maxage=60 30–60s Purge on any remote deploy
Host index.html no-cache, must-revalidate Bypass or 0s Purge on host deploy only

Note the use of stale-while-revalidate for remoteEntry.js. This keeps the edge fast during a purge — users get the stale manifest instantly while the edge revalidates in the background, avoiding a thundering herd to origin.

Pair this with image optimization at the edge for media-heavy micro frontends; each remote should not reimplement responsive images when the CDN can handle format negotiation and resizing.

Performance: Eliminating the Federation Waterfall

Module Federation adds network requests to the critical path. Without optimization, the sequence is: host HTML → host JS → fetch remoteEntry.js → fetch remote chunk → render. That is three round trips before pixels appear.

Mitigations that belong at the CDN layer:

Measure with Real User Monitoring segmented by remote. If search remote has a 90th percentile load of 800ms while others are 200ms, the problem is likely its chunk size or cache hit ratio, not the host.

Resilience, Security, and Rollback

A federated frontend is only as reliable as its weakest remote. The CDN must provide isolation:

# CloudFront / Fastly / Cloudflare — example cache behavior
location ~ ^/mfe/(?<mfe>[^/]+)/remoteEntry\.js$ {
  proxy_pass https://origin-$mfe.s3.amazonaws.com;
  add_header Cache-Control "public, max-age=60, s-maxage=120, stale-while-revalidate=600";
  add_header Surrogate-Key "mfe-$mfe";
  add_header Vary "Accept-Encoding";
}

# Immutable chunks — never revalidate
location ~ \.[a-f0-9]{8}\.(js|css)$ {
  add_header Cache-Control "public, max-age=31536000, immutable";
  expires 1y;
}

Checklist for Production

Before you go live with CDN-delivered Module Federation, verify these:

Done right, the CDN turns Module Federation from a clever Webpack trick into a true independent deployment platform. Teams ship when ready, users get instant updates without hard refreshes, and the edge guarantees consistency and speed.

Frequently Asked Questions

How does a CDN handle Module Federation remoteEntry.js files?

The CDN serves remoteEntry.js with a short TTL (60–300 seconds) and stale-while-revalidate. Deploy it immutably under a versioned path and keep a live pointer that you purge via surrogate keys. This gives you instant updates without long cache tails and allows instant rollback to a previous versioned file.

Should micro frontends share a single CDN distribution or use separate ones?

Use a single distribution with path-based origins (e.g., /mfe/header/*, /mfe/checkout/*). This simplifies edge logic, TLS, and WAF policies, and lets an edge worker compose a unified manifest. Separate distributions only make sense when teams need isolated security, billing, or geographic controls.

How do you avoid cache poisoning when independently deploying micro frontends?

Never overwrite content-hashed assets. Each build produces new filenames. Only remoteEntry.js and the version manifest are mutable, and they are protected by short cache, surrogate-key purges, and an upload order that ensures chunks exist at the edge before the manifest points to them.

Can Module Federation work with edge computing for personalization?

Yes. An edge worker can inspect cookies, headers, or geo data and return a tailored federation manifest — for example, serving an experimental checkout remote to 10% of users. This moves personalization to the edge with zero client-side waterfall and no host redeploy.

References & Standards: OWASP CDN Security · Cloudflare documentation