ESC
Type to search guides, tutorials, and reference documentation.
Verified by Garnet Grid

Micro-Frontend Architecture

Decompose monolithic frontends into independently deployable units. Covers composition patterns, module federation, shared state management, and the patterns that let multiple teams ship frontend features independently.

As organizations grow, the monolithic frontend becomes a bottleneck. Ten teams cannot merge changes to a single React app without stepping on each other. Micro-frontends apply the microservices principle to the frontend: each team owns a slice of the UI, builds it independently, deploys it independently, and the compositions come together at runtime.


Composition Patterns

Build-Time Composition:
  Approach: NPM packages imported at build time
  Pros: Simple bundling, type safety, tree shaking
  Cons: Shared deployment, not independently deployable
  Best for: Shared component libraries, design systems
  
  // package.json
  "@team-checkout/widget": "^2.0.0",
  "@team-search/bar": "^1.5.0"

Server-Side Composition:
  Approach: Server assembles HTML fragments from each micro-frontend
  Pros: SEO-friendly, fast initial load
  Cons: Complex server orchestration, not interactive until hydrated
  Best for: Content sites, SSR applications
  
  // Edge/server-side include
  <esi:include src="/fragments/checkout-widget" />
  <esi:include src="/fragments/search-bar" />

Client-Side Composition (Module Federation):
  Approach: Browser loads modules from different servers at runtime
  Pros: Truly independent deployment, runtime loading
  Cons: Larger bundle, runtime errors possible
  Best for: Large SPAs, multiple teams
  
  // webpack.config.js (Module Federation)
  new ModuleFederationPlugin({
    name: "shell",
    remotes: {
      checkout: "checkout@https://checkout.cdn.com/entry.js",
      search: "search@https://search.cdn.com/entry.js",
    },
  })

  // Usage in shell app
  const CheckoutWidget = React.lazy(
    () => import("checkout/Widget")
  );

Module Federation Example

// Team A: Shell Application (webpack.config.js)
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: "shell",
      remotes: {
        productCatalog: "productCatalog@https://products.app.com/remoteEntry.js",
        checkout: "checkout@https://checkout.app.com/remoteEntry.js",
        userProfile: "userProfile@https://profile.app.com/remoteEntry.js",
      },
      shared: {
        react: { singleton: true, requiredVersion: "^18.0.0" },
        "react-dom": { singleton: true, requiredVersion: "^18.0.0" },
      },
    }),
  ],
};

// Shell App component
function App() {
  return (
    <div>
      <Header />
      <Routes>
        <Route path="/products/*" element={
          <React.Suspense fallback={<Loading />}>
            <ProductCatalog />  {/* From Team B */}
          </React.Suspense>
        } />
        <Route path="/checkout/*" element={
          <React.Suspense fallback={<Loading />}>
            <CheckoutFlow />  {/* From Team C */}
          </React.Suspense>
        } />
      </Routes>
      <Footer />
    </div>
  );
}

Anti-Patterns

Anti-PatternConsequenceFix
Shared mutable global stateOne micro-frontend breaks anotherEvent-based communication, isolated state
Different React versions per micro-frontendMassive bundle size, incompatibilitiesShare React as singleton via Module Federation
No design systemInconsistent UI across teamsShared design system package, consumed by all
Micro-frontends for small teamsOverhead > benefitMicro-frontends solve SCALE problems (5+ teams)
No contract testing between shell and remotesDeployment breaks compositionContract tests verify interface compatibility

Micro-frontends are an organizational scaling pattern, not a technical improvement. A monolithic frontend built by one team is simpler and faster. Micro-frontends become necessary when team boundaries create deployment bottlenecks.

Jakub Dimitri Rezayev
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting

Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.

View Full Profile →