Back to articles
ArchitectureMicrofrontendsReactTeam Scaling

Micro-Frontend Architecture: Lessons from 20+ Product Initiatives

Practical lessons learned from implementing and working with microfrontend architectures across multiple teams and product initiatives.

3 min read

Pietro Dessotti

Senior Frontend Engineer at Zenvia

After contributing to over 20 product initiatives across multiple engineering teams, I've accumulated strong opinions about when microfrontends help and when they add unnecessary complexity. Here's what I've learned.

What Microfrontends Actually Solve

Microfrontends don't solve a technical problem. They solve an organizational one. The core value proposition is team autonomy: the ability for multiple teams to own, deploy, and evolve their own UI surfaces without coordinating with every other team on every release.

If you have one team, you don't need microfrontends. If you have ten teams shipping to the same frontend codebase, you almost certainly do.

The Deployment Boundary is the Real Benefit

Most people focus on technology when discussing microfrontends: module federation, single-spa, and iframes. But the technology is secondary. The critical thing is the deployment boundary.

Each team controls their own deployment pipeline. A bug in Team A's checkout flow doesn't block Team B from shipping new features. This alone can dramatically change how teams operate.

// Module Federation host configuration
// apps/shell/webpack.config.js
new ModuleFederationPlugin({
  name: 'shell',
  remotes: {
    checkout: 'checkout@https://checkout.example.com/remoteEntry.js',
    catalog: 'catalog@https://catalog.example.com/remoteEntry.js',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
  },
})

The Design System Problem

One of the first challenges you'll face: each microfrontend may end up with a slightly different version of your component library. Team A upgrades the button. Team B doesn't. Now your users see two different button styles on the same page.

The solution isn't forcing everyone to update at the same time. It's designing your shared packages to be stable and versioning them carefully. Treat your design system like a public API.

When It Goes Wrong

I've seen microfrontends fail in two main ways:

1. Premature decomposition. Teams split the frontend before they had clear team ownership boundaries. The result is 12 microfrontends maintained by 3 people. Complexity without benefit.

2. Shared state hell. Teams try to share too much state across boundaries, such as user sessions, shopping carts, and UI preferences. Each new shared concern erodes the autonomy you were trying to achieve.

The rule of thumb: if two microfrontends need to communicate frequently, they may belong in the same application.

What I'd Do Differently

Starting fresh today, I'd:

  1. Start with a monorepo, not microfrontends. Extract only when team growth demands it.
  2. Define ownership boundaries before technical boundaries. Conway's Law applies.
  3. Invest heavily in the design system first. It's the foundation everything else sits on.
  4. Keep the shell application thin. Limit it to routing and authentication.

Microfrontends are a powerful tool. But like any powerful tool, they require understanding the problem before reaching for the solution.