An in-depth look at Angular, practical patterns, and production best practices. The size, complexity, and team distribution of contemporary online applications have all increased. Ten years ago, the majority of frontend teams used a single codebase and deployment workflow to create single applications. When there were fewer features, a smaller team, and simpler business requirements, that strategy proved effective. However, today's companies manage many separate release cycles, run numerous parallel product lines, and demand quick iteration while maintaining a consistent user experience. In this context, micro frontends have emerged as a significant architectural option.

Microfrontends bring microservices concepts to web browsers. We divide it into smaller, independent applications that can be developed, deployed, and maintained separately rather than creating a single, massive, monolithic frontend. Better code ownership, quicker releases, and scalability are all promised by this design. But it's also complicated. It takes careful planning, robust governance, and an established development culture to implement micro frontends in a clean, production-safe manner.

Micro frontends are not something one implements just because they seem trending. They solve very specific organisational and technical challenges.

When Frontend Monoliths Become a Problem

A monolithic frontend starts becoming hard to manage when:

  • Teams grow beyond 8–10 developers.
    • More people touching the same codebase creates merge conflicts, inconsistent code quality, and slow onboarding.
  • Features require isolated release cycles.
    • One team’s changes often block another team’s deployment.
  • The build pipeline becomes slower.
    • Large builds and test suites increase CI/CD time.
  • Shared dependencies create version lock-in.
    • Upgrading Angular, RxJS, or UI libraries becomes a huge task affecting all teams.
  • Different parts of the application evolve at different speeds.
    • Some modules may require rapid iteration, others remain stable for years.

Micro frontends break this bottleneck by enabling each domain or feature to become an independently maintained slice of the UI.

What Micro Frontends Actually Mean

A micro frontend is not simply:

  • Multiple modules inside one Angular application
  • Lazy-loaded routes
  • A component library

Instead, a micro frontend is a fully independent application that owns:

  • Its own codebase
  • Its own state
  • Its own dependencies
  • Its own build pipeline
  • Its own deployment pipeline

It integrates into a larger shell application at runtime, not compile time.

Business Benefits
The architecture becomes worthwhile when:

  • You have multiple teams working on independent product domains
  • Release cycles vary by team
  • You want to scale development without rewriting everything
  • Stability and resilience matter
  • You want to test and deploy features independently
  • You want technology flexibility across teams

Micro frontends unlock long-term maintainability and organisational scalability.

2. Micro Frontend Architecture: The Big Picture
A typical micro frontend system includes:

  • A shell (container) application
  • Multiple micro frontend modules
  • A communication mechanism
  • A build and deployment strategy
  • A shared design system (optional but recommended)
  • Versioning and dependency governance

The Shell Application
The shell acts as the entry point of the system. Its responsibilities include:

  • Routing between micro frontends
  • Hosting shared dependencies
  • Bootstrapping the UI
  • Handling authentication and global state
  • Providing shared services (optional)

With Angular, this is often called the host or container application.

Micro Frontend Applications
Each micro frontend is responsible for:

  • Its own UI
  • Its own routing
  • Its own data management
  • Business logic for its domain
  • Independent deployments

A micro frontend must not depend on other micro frontends directly.

Integration Strategies
There are four dominant ways to integrate micro frontends:

  • Build-time integration (bad)
  • Server-side integration
  • Iframe-based integration
  • Runtime integration using Module Federation (modern and recommended)

Among these, Module Federation has become the de facto standard for micro frontends built using Angular, Webpack, or any modern frontend framework.

3. Angular + Module Federation: A Practical Approach
Angular 13+ introduced built-in support for Module Federation, which makes runtime integration smoother.

What Is Module Federation?

Module Federation is a Webpack feature (initially introduced with Webpack 5) that allows multiple independently built applications to load code from each other at runtime.

With Module Federation:

  • The shell can load Angular modules from remote applications
  • Micro frontends can expose specific modules
  • Each micro frontend can have its own Angular version (with caution)
  • No need to recompile or redeploy the shell when micro frontends update

How It Works?
Every micro frontend defines:

  • Expose configuration
  • RemoteEntry.js file containing the exported modules
  • Angular module to expose

The shell defines:

  1. Remote configuration pointing to each micro frontend
  2. Lazy-loaded routes consuming the exposed modules

When the system runs:

  • The shell loads the remote modules on demand via HTTP
  • Angular bootstraps the micro application inside the shell
  • Routing behaves as if the micro frontend is part of the shell

4. Setting Up a Micro Frontend Architecture in Angular
Let’s go step-by-step with a production-grade example.
Assume we are building a scalable e-commerce platform with teams for:

  • Catalogue
  • Cart
  • Checkout
  • User Profile

We will build:

  • A shell (host) application
  • Four micro frontends

Create the Angular Workspace

  • Each application should ideally live in its own Git repository.
  • However, during development, you can start with a monorepo.

ng new ecommerce-shell --routing --style=scss
ng new ecommerce-catalogue --routing --style=scss
ng new ecommerce-cart --routing --style=scss
ng new ecommerce-checkout --routing --style=scss
ng new ecommerce-profile --routing --style=scss

Add Module Federation
Install the toolkit:
ng add @angular-architects/module-federation

This command updates the Webpack configuration and adds a basic module federation setup.

Configure the Shell
Example webpack.config.js for the shell:
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

module.exports = {
  output: {
    uniqueName: "ecommerceShell",
  },
  plugins: [
    new ModuleFederationPlugin({
      remotes: {
        catalogue: "catalogue@http://localhost:4201/remoteEntry.js",
        cart: "cart@http://localhost:4202/remoteEntry.js",
        checkout: "checkout@http://localhost:4203/remoteEntry.js",
        profile: "profile@http://localhost:4204/remoteEntry.js",
      },
      shared: {
        "@angular/core": { singleton: true, strictVersion: true },
        "@angular/common": { singleton: true, strictVersion: true },
        "@angular/router": { singleton: true, strictVersion: true }
      },
    }),
  ],
};


Configure a Micro Frontend
Example for Catalogue micro frontend:
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

module.exports = {
  output: {
    uniqueName: "catalogue",
  },
  plugins: [
    new ModuleFederationPlugin({
      name: "catalogue",
      filename: "remoteEntry.js",
      exposes: {
        "./Module": "./src/app/catalogue/catalogue.module.ts",
      },
      shared: {
        "@angular/core": { singleton: true },
        "@angular/common": { singleton: true },
        "@angular/router": { singleton: true }
      },
    }),
  ],
};


Routing in the Shell
The shell application loads each micro frontend lazily:
const routes: Routes = [
  {
    path: 'catalogue',
    loadChildren: () =>
      loadRemoteModule({
        remoteName: 'catalogue',
        exposedModule: './Module'
      }).then(m => m.CatalogueModule)
  },
  {
    path: 'cart',
    loadChildren: () =>
      loadRemoteModule({
        remoteName: 'cart',
        exposedModule: './Module'
      }).then(m => m.CartModule)
  }
];

This gives clean runtime integration.

5. Managing Shared Dependencies Across Micro Frontends
The Shared Dependencies Problem

Without governance:

  • Teams upgrade Angular independently
  • Shared libraries become misaligned
  • Bundle size increases
  • Runtime version conflicts break the UI

Best Practices

  • Use strictVersion for Angular packages.
  • Maintain a shared dependency contract across teams.
  • Use a central design system for UI components.
  • Establish versioning guidelines for shared libraries.

Angular Version Compatibility
Module Federation allows different versions of Angular, but this should be avoided unless:

  • Teams have strong reasons
  • You can guarantee compatibility
  • You are ready to handle runtime mismatches

The safest approach is to maintain a uniform version across all micro frontends.

6. Communication Between Micro Frontends

Micro frontends must be loosely coupled. Direct service injection across boundaries is not recommended.

Valid Communication Methods

  • URL-based communication
    • Encode identifiers in the route or query params.
    • This is the simplest and most stable approach.
  • Custom events (browser-native)
    • Suitable for parent-child communication inside the shell.
  • Shared service via shell dependency
    • Only when the service is stable and global (like Auth).
  • Cross-application state management
    • Only for limited use cases with clear governance.

Avoid

  • Direct Angular service injection between micro frontends
  • Shared mutable state
  • Synchronous coupling
  • Global event buses without versioning

7. Deployment Strategies
Independent Deployment Pipelines

Each micro frontend should:

  • Have its own CI/CD pipeline
  • Produce its own build artifact
  • Deploy to its own URL

The Shell Must Not Rebuild for Every Micro Frontend Release

The shell should only reference the remote entry URLs.

You must avoid:

  • Rebuilding the shell for micro frontend updates
  • Hardcoding versions in the shell
  • Self-Healing Deployments

Use:

  • Cache busting
  • Versioned remoteEntry files
  • Rollback support

8. Security and Authentication
The Shell Should Handle Authentication

Reasons:

  1. Prevent duplicate implementations
  2. Avoid inconsistent session logic
  3. Prevent insecure micro frontends
  4. Micro Frontends Use Tokens Provided by Shell

Options:

  1. Pass tokens via localStorage
  2. Use a shared Auth service exposed by shell
  3. Use cookies (with secure, HttpOnly flags)
  4. Route Guard Strategy

Use shell-based guards:

  • All protected routes go through shell-level checks
  • Micro frontends should not implement auth logic independently

9. Performance Considerations
When Micro Frontends Improve Performance

  • Parallel loading
  • Smaller independent bundles
  • Less re-rendering
  • Faster deployments

When They Hurt Performance

  • Too many remote loads
  • Overuse of shared dependencies
  • Fragmented UI leading to layout shifts

Solutions

  1. Use preloading strategies in the shell.
  2. Use shared libraries wisely.
  3. Cache remoteEntry files.

10. Real-World Best Practices
Start With Domain-Driven Boundaries
Each micro frontend should map to a self-contained business capability.

Avoid Over-Splitting
Micro frontends should be coarse-grained. Too many MFEs increase complexity.

Good example: Catalogue + Cart + Checkout + Profile
Bad example: Button micro frontend + Table micro frontend

Build a Strong Governance Model
Define:

  • Dependency rules
  • Angular version policy
  • Shared library update guidelines
  • Code quality expectations

Introduce Micro Frontends Gradually
Never rewrite the whole system into micro frontends at once.
Migrate module by module.

Monitoring
Use:

  • Application performance monitoring
  • Distributed logs
  • Error tracking per micro frontend

11. A Production Checklist
Before going live:

  • Stable Angular versions across MFEs
  • Central design system implemented
  • Shell handles authentication
  • Independent deployment pipelines configured
  • RemoteEntry files versioned
  • Routing tested for all MFEs
  • Error handling implemented
  • Performance benchmarks done
  • Security tests completed
  • Clear rollback strategy in place

12. Conclusion
Micro frontends offer a powerful way to scale frontend development in large organisations. They allow teams to work independently, release faster, and manage complexity with long-term sustainability. However, the architecture demands discipline, governance, and careful planning.

When implemented correctly with Angular and Module Federation, micro frontends provide:

  • Independent deployment
  • Domain isolation
  • Technology flexibility
  • Faster builds
  • Better team autonomy

In real world production systems, success depends less on framework capabilities and more on strong engineering practices, clear boundaries, and consistent dependency management. Micro frontends are not just a technical choice; they are an organisational strategy for scaling frontend teams responsibly.