The deployment goal: independent, atomic, cache-safe
Each microfrontend must deploy on its own pipeline, its release must be atomic (users never load a half-updated app), and caching must let the shell pick up new remotes without serving a stale entry file. The AWS building blocks map cleanly: S3 for the static artifacts, CloudFront for the CDN and cache control.
One S3 origin per microfrontend
Each microfrontend builds to its own S3 bucket/prefix and exposes a Module Federation remoteEntry.js. The shell (or host app) references those remotes. Because each has its own origin and pipeline, the billing team's deploy touches only the billing artifacts — the dashboard team is unaffected.
// CloudFront cache strategy: fingerprint chunks, don't cache the entry
// remoteEntry.js -> Cache-Control: no-cache (always revalidate)
// [name].[hash].js -> Cache-Control: max-age=31536000, immutable
// The entry is small and must be fresh; hashed chunks are forever-cacheable.The cache subtlety that breaks people
If you cache remoteEntry.js aggressively, a deploy ships new chunks but users keep loading the old entry that points at chunks that may no longer exist — white screen. The fix: the entry file is always revalidated (no-cache), while the content-hashed chunks it references are immutable and cached forever. New deploy, fresh entry, correct chunks, no stale references.
The classic microfrontend production bug is a stale remoteEntry pointing at deleted chunks. Keep the entry revalidated and the hashed chunks immutable, and it can't happen.
Pipeline and resiliency
- Each microfrontend has its own CI/CD (build -> upload to S3 -> invalidate the entry in CloudFront).
- Share singletons (React, router, design system) so remotes don't each ship their own copy.
- Plan the failure case: if a remote fails to load, the shell should render a graceful fallback, not crash the whole page.
- Monitor per-microfrontend (Sentry/CloudWatch) so an error is attributed to the team that owns it.
Key takeaways
- Give each microfrontend its own S3 origin and CI/CD pipeline for independent, atomic deploys.
- Serve through CloudFront; revalidate remoteEntry.js and cache hashed chunks immutably.
- Share React/router/design-system as singletons across remotes.
- Render a fallback when a remote fails — one microfrontend down shouldn't take the page down.