Technology·15 min read

Micro Frontends: Module Federation vs Single-SPA vs Astro 2026

Micro frontends promise team autonomy and independent deployments, but picking the wrong approach can double your complexity for zero benefit. Here is how Module Federation, Single-SPA, and Astro actually compare in production.

Nate Laquis

Nate Laquis

Founder & CEO

Why Micro Frontends Exist and When You Actually Need Them

Micro frontends apply the same principle behind microservices on the backend to your UI layer. Instead of one monolithic frontend that every team commits to, you split the application into independently built, tested, and deployed units. Each team owns a vertical slice of the product, from the UI component all the way down to the API call.

The promise is compelling: Team A ships a new checkout flow on Tuesday without waiting for Team B to finish refactoring the product catalog. No merge conflicts across team boundaries. No coordinated release trains. Each team picks its own framework version, its own build tooling, its own deployment cadence.

But here is the uncomfortable truth. Most teams that adopt micro frontends do not need them. If you have fewer than 30 frontend engineers, a well-structured monorepo with clear module boundaries gives you 90% of the autonomy at 10% of the complexity. Micro frontends solve an organizational scaling problem, not a technical one. If your teams are not stepping on each other's code multiple times per week, you are adding infrastructure overhead for a problem you do not have.

code on a dark monitor showing frontend application architecture and module imports

That said, when you do need them, the difference is transformative. We have seen organizations go from two-week release cycles with 40 developers blocking each other to daily deployments per team with zero cross-team coordination. The key is choosing the right approach for your situation. In 2026, three architectures dominate the micro frontend landscape: Module Federation, Single-SPA, and Astro's islands architecture. Each makes fundamentally different tradeoffs, and picking the wrong one will cost you months of engineering time.

Module Federation: Runtime Composition with Webpack and Rspack

Module Federation, introduced in Webpack 5 and now supported natively in Rspack 1.x, is the most popular micro frontend approach for single-page applications. The core idea is simple: one application can dynamically load modules from another application at runtime, sharing dependencies like React across the network boundary without duplicating them in every bundle.

How It Works Under the Hood

Each micro frontend ("remote") exposes specific modules through its Webpack or Rspack configuration. A host application declares which remotes it consumes and which shared libraries (React 19, React DOM, your design system) should be deduplicated. At runtime, the host fetches a manifest file (remoteEntry.js) from each remote, negotiates shared dependency versions, and lazily loads the exposed components.

The version negotiation is where Module Federation shines. If your host runs React 19.1 and a remote was built with React 19.0, the federation runtime can share a single copy because they are semver-compatible. If a remote ships React 20 while the host is still on 19, federation loads both versions in isolation. No crashes, no runtime conflicts. This is a massive win for teams that cannot upgrade frameworks in lockstep.

Performance Profile

Module Federation adds roughly 15 to 25 KB of runtime overhead (gzipped) for the federation plugin itself. The remoteEntry.js manifest per remote is typically 2 to 5 KB. The real cost is the waterfall: the host loads, then fetches remote manifests, then fetches the actual chunks. Without prefetching or server-side composition, you are looking at 200 to 400ms of additional load time on a median 4G connection. Rspack 1.2 mitigates this with manifest prefetch hints, cutting the waterfall by about 40% in our benchmarks.

Setup Complexity

Getting a basic Module Federation setup running takes about two days for an experienced engineer. Getting it production-ready with shared state, error boundaries for remote failures, versioned deployments, and a local development story that does not require running six dev servers simultaneously takes two to four weeks. You need a shared configuration package to keep federation configs consistent, a deployment pipeline that publishes remoteEntry.js to a CDN, and a fallback strategy for when a remote is down or returns a broken build.

When Module Federation Fits

  • Large SPA teams (30+ frontend engineers) where multiple teams contribute to a single user-facing application
  • Incremental migration from a monolithic React or Vue app, because you can federate one route at a time
  • Shared runtime requirements where all micro frontends use the same framework (React + React) and benefit from dependency deduplication
  • Dashboard-style products where widgets from different teams compose into a single page

Single-SPA: Framework-Agnostic Lifecycle Orchestration

Single-SPA takes a fundamentally different approach. Instead of sharing modules at the Webpack level, it operates as a top-level router and lifecycle orchestrator. Each micro frontend is a full application (React, Vue, Angular, Svelte, whatever) that registers mount, unmount, and bootstrap lifecycle hooks. Single-SPA decides which applications are active based on the current URL and manages their lifecycles accordingly.

The Lifecycle Model

Every micro frontend in Single-SPA must export three functions: bootstrap (called once, for initial setup), mount (called when the route activates, renders the app into a DOM container), and unmount (called when the user navigates away, cleans up the DOM and event listeners). This lifecycle contract is framework-agnostic. Single-SPA provides adapter packages for React (single-spa-react 6.x), Vue (single-spa-vue), Angular (single-spa-angular 10.x), and most other frameworks. You can literally run a React 19 app alongside an Angular 18 app alongside a Svelte 5 app in the same browser window.

Routing and Layout

Single-SPA 6.x introduced single-spa-layout, which gives you an HTML-based layout engine for defining where each application mounts. You declare routes and application mounting points in a layout template, and the router handles activation and deactivation. This is cleaner than the original approach of programmatically registering applications with route-matching functions, though both still work.

laptop screen showing frontend routing code with multiple framework integrations

Performance Profile

Single-SPA's core router is tiny, about 8 KB gzipped. But the real performance story is less flattering. Because each micro frontend is a standalone application, you pay the full framework cost for each one. Two React apps mean two copies of React DOM (roughly 40 KB gzipped each). A React app and an Angular app mean you load both framework runtimes. On a page where three micro frontends are simultaneously active, you can easily add 120 to 200 KB of duplicated framework code. There is no built-in dependency sharing like Module Federation provides. You can use import maps or SystemJS to share dependencies manually, but this requires careful coordination and version pinning across teams.

Setup Complexity

A basic Single-SPA setup is surprisingly quick, maybe a day. The official create-single-spa CLI scaffolds a root config and micro frontend templates. But production complexity escalates fast. You need to solve cross-app communication (custom events, a shared event bus, or a state store like Redux in the root config), handle CSS isolation (Shadow DOM, CSS Modules, or naming conventions to prevent style collisions), and build a deployment pipeline that independently deploys each micro frontend's JavaScript bundle to a CDN while updating the import map atomically.

When Single-SPA Fits

  • Multi-framework environments where you genuinely need React, Angular, and Vue apps coexisting (common during long migrations)
  • Route-based composition where each micro frontend owns a full page or route section, not individual components within a page
  • Acquired product integration where you are stitching together products from different companies or teams that already have their own tech stacks
  • Enterprise portals where different business units maintain independent frontend applications under a unified navigation shell

Astro Islands: Partial Hydration for Content-Heavy Architectures

Astro approaches micro frontends from a completely different angle. Instead of splitting a single-page application into independently deployed chunks, Astro renders most of your page as static HTML on the server and lets you sprinkle interactive "islands" using any framework: React, Vue, Svelte, Solid, Preact, or Lit. Each island hydrates independently, and the rest of the page ships zero JavaScript.

The Islands Architecture

In Astro 5.x, you import a React component and add a client directive: client:load (hydrate immediately), client:idle (hydrate when the browser is idle), client:visible (hydrate when the component scrolls into view), or client:media (hydrate when a media query matches). Everything outside these islands is pure HTML and CSS. No JavaScript, no hydration, no framework runtime. For content-heavy sites, marketing pages, docs, and e-commerce catalogs, this means your pages can ship under 50 KB of total JavaScript while still having rich interactive components where they matter.

Performance Profile

Astro's performance numbers are genuinely impressive. A typical Astro page scores 95 to 100 on Lighthouse performance out of the box. Time to Interactive on a content page with two interactive islands is under 1.2 seconds on a mid-tier mobile device over 4G. Compare that to a Module Federation or Single-SPA setup where Time to Interactive is often 3 to 5 seconds because the entire page requires JavaScript to render.

The tradeoff is that Astro is primarily a Multi-Page Application (MPA) framework. Navigation between pages is a full page load (though Astro 5 added view transitions that make page navigations feel SPA-like with crossfade animations). If your application requires complex client-side state that persists across route navigations (think a shopping cart, a multi-step form wizard, or a collaborative editor), you need to manage that state in islands using shared stores like nanostores or hoist state to a framework-level provider within an island.

Micro Frontend Angle

Astro is not a traditional micro frontend framework. It does not give you independent deployment of islands or runtime composition from separate build pipelines. But it solves the same organizational problem differently. Each island can be maintained by a different team in a monorepo, built with a different framework, and tested independently. A marketing team can build their hero section in Svelte while the product team builds the pricing calculator in React. They compose at the Astro page level, and the build pipeline handles everything.

For teams that need the multi-framework flexibility of micro frontends but primarily build content-driven sites, Astro's islands give you the architectural boundary without the runtime overhead. You lose independent deployability, but you gain massive performance wins and a dramatically simpler infrastructure story.

When Astro Fits

  • Content-heavy applications like marketing sites, documentation portals, e-commerce catalogs, and media-rich publications
  • Performance-critical pages where every kilobyte of JavaScript impacts conversion rates (landing pages, product pages)
  • Multi-framework teams that want component-level framework mixing without the runtime overhead of Single-SPA
  • Progressive enhancement where the page must work without JavaScript and interactive features are layered on top

Head-to-Head Comparison: The Metrics That Matter

Let's cut through the marketing and compare these three approaches on the dimensions that actually affect your engineering team and your users.

Bundle Size and Initial Load

Module Federation with three remotes sharing React 19 and a design system: approximately 180 to 250 KB total JavaScript (gzipped). The shared dependency deduplication keeps this reasonable, but you still pay for the federation runtime and the waterfall of remote entry fetches.

Single-SPA with three micro frontends (two React, one Vue): approximately 280 to 400 KB total JavaScript (gzipped). The duplicated framework runtimes are the killer here. Even with import map sharing, version mismatches between teams often force duplicate loads.

Astro with three interactive islands (React pricing calculator, Svelte testimonial carousel, vanilla JS newsletter form): approximately 60 to 90 KB total JavaScript (gzipped). Everything else is static HTML. This is not even close.

Team Autonomy and Deployment Independence

Module Federation scores highest here. Each remote deploys independently to its own CDN origin. A team can push a new version of their micro frontend without touching the host application. The version negotiation handles compatibility automatically. Rollbacks are as simple as reverting the remoteEntry.js file.

Single-SPA offers similar deployment independence. Each micro frontend deploys its bundle independently, and the import map update controls which version is live. The weak spot is that import map updates need to be atomic, if you update the map while a user is navigating, they can get a mix of old and new bundles.

Astro requires a full site rebuild when any island changes, because islands are composed at build time. You can work around this with incremental builds in Astro 5 (which only rebuilds changed pages), but it is fundamentally not an independently deployable architecture. For teams that need true deployment independence, this is a dealbreaker.

Shared State Management

This is where all three approaches struggle, but in different ways. Module Federation can share a state store (Zustand, Jotai) as a federated module, and because React is shared, context providers work across remote boundaries. Single-SPA requires a framework-agnostic approach: custom events, a shared Redux store in the root config, or a pub/sub library. Astro uses nanostores or similar lightweight stores that work across framework boundaries, but state does not persist across page navigations without external storage (localStorage, URL params, or a server session).

Developer Experience

Module Federation's local development story has improved significantly with Rspack Dev Server and the @module-federation/enhanced plugin, but running multiple dev servers simultaneously still taxes your machine. Expect 4 to 8 GB of RAM for a setup with four remotes running locally.

Single-SPA's local dev story is similar. The recommended approach is running the root config locally and pointing it at deployed versions of the micro frontends you are not actively developing. This works but means you are testing against production versions of other apps, not the latest code.

Astro's local dev story is excellent. One dev server, one port, hot module replacement across all islands regardless of framework. It is just a normal development experience, which is a huge advantage.

Architecture Decision Framework: Choosing the Right Approach

After building micro frontend architectures for over a dozen organizations, here is the decision framework we use at Kanopy. It comes down to three questions.

Question 1: Is your application an SPA or content-driven?

If your application is a complex SPA (dashboards, admin panels, data-heavy tools, collaborative editors), Module Federation or Single-SPA are your options. Astro is not designed for highly interactive, client-state-heavy applications. If your application is content-driven with pockets of interactivity (marketing sites, documentation, e-commerce storefronts, media publications), Astro is almost certainly the right choice. The performance advantage is too large to ignore.

Question 2: Do all your teams use the same framework?

If every team runs React (or every team runs Vue), Module Federation is the clear winner. Shared dependency deduplication eliminates the biggest performance penalty of micro frontends, and the runtime composition model is mature and well-tooled. If teams use different frameworks and cannot or will not converge, Single-SPA is the only SPA-based option that handles true multi-framework composition at the application level.

Question 3: Do you need independent deployability?

If independent deployment per team is a hard requirement (common in large enterprises with strict change management), Module Federation and Single-SPA both deliver. Astro does not, at least not without building a custom composition layer on top. But be honest about whether you actually need independent deployability or just want it. A well-configured monorepo with per-package CI and incremental builds gives you most of the deployment speed without the architectural overhead. We covered the tradeoffs of distributed versus unified deployment in our guide to multi-region deployment architecture.

development team collaborating on architecture decisions around a whiteboard with system diagrams

The Hybrid Path

Increasingly, we see teams combining approaches. An Astro marketing site that embeds a Module Federation-powered dashboard behind the login wall. A Single-SPA shell that routes between legacy Angular apps and new React micro frontends built with Module Federation. These hybrid architectures add complexity, but when the product requirements genuinely span content and application use cases, they can be the most pragmatic solution.

Implementation Checklist and Next Steps

Whichever approach you choose, here is what you need to get right from day one.

For Module Federation

  • Shared dependency policy: Define which packages are shared (React, your design system, your auth library) and enforce semver ranges across teams. Use the singleton option for packages that cannot be duplicated (React, React DOM).
  • Error boundaries: Wrap every remote import in a React error boundary with a meaningful fallback UI. Remotes will fail in production, and your users should see a graceful degradation, not a white screen.
  • Versioned manifests: Deploy remoteEntry.js behind a CDN with cache-busting hashes. Stale manifests are the number one cause of production issues in federated apps.
  • Local development contract: Provide a CLI or Docker Compose setup that lets developers run only the remotes they are working on, with stubs or deployed versions for everything else.

For Single-SPA

  • Import map management: Use a server-side import map service (like import-map-deployer) to ensure atomic updates. Never update import maps by manually editing a JSON file in production.
  • CSS isolation: Choose one strategy (Shadow DOM, CSS Modules, or BEM conventions) and enforce it. Cross-app style leaks are the most common bug in Single-SPA setups and the hardest to debug.
  • Shared utilities package: Publish a shared package with your event bus, authentication helpers, and analytics wrappers. Keep it small and backward-compatible.
  • Lifecycle testing: Test mount/unmount cycles aggressively. Memory leaks from incomplete unmount cleanup compound over time and crash the browser tab.

For Astro

  • Island budget: Set a JavaScript budget per page (we recommend under 100 KB gzipped). Track it in CI. Astro makes it easy to add islands, and teams will add them until performance degrades.
  • Hydration strategy: Default to client:visible for below-the-fold islands and client:idle for non-critical interactive elements. Only use client:load for components that must be interactive immediately on page load.
  • State persistence: If you need state across page navigations, choose your persistence layer upfront (nanostores with localStorage sync, URL search params, or server sessions). Retrofitting this later is painful.

Micro frontends are a powerful pattern when applied to the right problem at the right scale. The worst outcome is adopting them prematurely and spending six months building infrastructure instead of product features. The best outcome is giving your teams true autonomy to ship independently while your users get a fast, cohesive experience.

Not sure which architecture fits your product and team structure? We help startups and scaling companies make these decisions every week. Book a free strategy call and we will walk through your specific situation together.

Need help building this?

Our team has launched 50+ products for startups and ambitious brands. Let's talk about your project.

micro frontendsmodule federation webpacksingle-spa frameworkAstro islands architecturefrontend architecture 2026

Ready to build your product?

Book a free 15-minute strategy call. No pitch, just clarity on your next steps.

Get Started