DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Micro-Frontends: Splitting a Monolith Without Breaking Everything

Micro-Frontends: Splitting a Monolith Without Breaking Everything

Micro-frontends let independent teams own and deploy their part of the UI independently — but they add real complexity. Here's when they're worth it.

When to Consider Micro-Frontends

Consider it when:

  • Multiple teams deploy the same frontend and block each other
  • Different parts of the app have genuinely different tech requirements
  • You need independent deployability for regulatory or organizational reasons

Skip it when:

  • You have fewer than 3 frontend teams
  • Your app is a single SPA under 100k LOC
  • You can solve it with better monorepo tooling

Approach 1: Module Federation (Webpack 5)

// shell/webpack.config.js — the host app
new ModuleFederationPlugin({
  name: 'shell',
  remotes: {
    checkout: 'checkout@https://checkout.example.com/remoteEntry.js',
    dashboard: 'dashboard@https://dashboard.example.com/remoteEntry.js',
  },
  shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
});

// checkout/webpack.config.js — a remote
new ModuleFederationPlugin({
  name: 'checkout',
  filename: 'remoteEntry.js',
  exposes: { './CheckoutFlow': './src/CheckoutFlow' },
  shared: { react: { singleton: true }, 'react-dom': { singleton: true } },
});
Enter fullscreen mode Exit fullscreen mode
// Usage in shell — lazy loaded from remote
const CheckoutFlow = React.lazy(() => import('checkout/CheckoutFlow'));

function App() {
  return (
    <Suspense fallback={<LoadingSpinner />}>
      <CheckoutFlow />
    </Suspense>
  );
}
Enter fullscreen mode Exit fullscreen mode

Approach 2: iframes (Simpler, More Isolated)

// Strong isolation, easy to deploy independently
// Downside: full page reload, harder to share state
function EmbeddedCheckout({ orderId }: { orderId: string }) {
  return (
    <iframe
      src={`https://checkout.example.com/embed?orderId=${orderId}`}
      style={{ border: 'none', width: '100%', height: '600px' }}
      sandbox='allow-scripts allow-same-origin allow-forms'
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

Approach 3: Route-Level Splitting With Next.js

The simplest micro-frontend: different teams own different routes, deployed as separate Next.js apps behind a reverse proxy.

# nginx.conf
location /checkout/ { proxy_pass http://checkout-team-app; }
location /dashboard/ { proxy_pass http://dashboard-team-app; }
location / { proxy_pass http://main-app; }
Enter fullscreen mode Exit fullscreen mode

The Honest Take

Micro-frontends are an organizational solution, not a technical one. If your problem is team coordination, consider fixing that first. The complexity cost is real.

For most SaaS products, a well-structured monorepo with Turborepo gives you independent deployability without the micro-frontend overhead. The AI SaaS Starter Kit ships with that structure ready to scale.

Top comments (0)