Advertisement

Micro-Frontends with Module Federation: Scaling Teams in 2025

Stop fighting the monolith. Discover how to split your frontend into independent, deployable apps that work together seamlessly.

📅 November 23, 2025⏱️ 32 min read🏷️ Architecture

Introduction

As applications grow, so does the complexity of the codebase. A single "monolithic" frontend can become a bottleneck where build times skyrocket and teams step on each other's toes.

Micro-frontends solve this by applying the microservices pattern to the frontend. And in 2025, Module Federation (originally from Webpack 5) is the gold standard for implementing them, enabling runtime integration of separately built applications.

💡 Why This Matters: Scalability isn't just about handling more traffic; it's about handling more developers and features without slowing down.

Key Concepts

Next.js Implementation

We'll configure two Next.js apps: a Host (Shell) and a Remote (e.g., Shop). We use the @module-federation/nextjs-mf plugin.

next.config.js (Host)
const NextFederationPlugin = require('@module-federation/nextjs-mf');

module.exports = {
  webpack(config, options) {
    if (!options.isServer) {
      config.plugins.push(
        new NextFederationPlugin({
          name: 'host',
          filename: 'static/chunks/remoteEntry.js',
          remotes: {
            shop: 'shop@http://localhost:3001/_next/static/chunks/remoteEntry.js',
          },
          exposes: {},
          shared: {},
        })
      );
    }
    return config;
  },
};

Then, importing the remote component in the Host:

pages/index.tsx (Host)
import dynamic from 'next/dynamic';

const RemoteProductList = dynamic(
  () => import('shop/ProductList'),
  { ssr: false, loading: () => <p>Loading Shop...</p> }
);

export default function Home() {
  return (
    <div>
        <h1>Host Application</h1>
        <RemoteProductList />
    </div>
  );
}

The Backend for Frontend (BFF)

Micro-frontends usually need to talk to microservices. A common pattern is to have a Spring Boot BFF for each domain.

ProductController.java (Shop BFF)
@RestController
@CrossOrigin(origins = "http://localhost:3000") // Allow Host App
@RequestMapping("/api/products")
public class ProductController {

    @GetMapping
    public List<Product> getProducts() {
        // Fetches data for the 'Shop' micro-frontend
        return productService.findAll();
    }
}

Security Considerations

Distributed frontends introduce new attack vectors.

🔒 CORS

Strictly configure CORS on your backend to allow only trusted hosts (the shell app).

🔒 Content Security Policy (CSP)

Update CSP headers to allow loading scripts from remote domains.

🔒 Authentication

Share auth tokens (JWT) securely between micro-frontends (e.g., via cookies or window events).

🔒 Dependency Isolation

Ensure one vulnerable dependency in a remote app doesn't compromise the host.

✅ Micro-Frontend Checklist

Before you split your app:

Visualize Your Architecture

Use our tools to diagram your microservices and micro-frontends interactions.

Related Topics

Conclusion

Micro-frontends with Module Federation provide the ultimate flexibility for large organizations. They allow teams to move fast, choose the right tools for their specific domain, and deploy without fear of breaking the entire application.

While they introduce complexity in build and deployment, the trade-off is often worth it for scalability and team autonomy.

Advertisement