← All articles

Micro-frontends won't fix your monolith

I keep seeing the same pitch. A team is frustrated with its frontend monolith. Changes take too long, pull requests touch too many files, and deployments make everyone nervous. Someone proposes micro-frontends so each team can own and deploy a smaller piece.

A LinkedIn post I saw recently made a useful distinction: "Big systems rarely grind to a halt because they're big. They grind to a halt because they're tangled." I agree with the diagnosis. I'm less convinced that independent deployment is always the next treatment.

What happened during the migration

A React or Angular app grows over a few years. It may have started with good structure, but components gradually become coupled, shared state leaks across features, and the design system becomes a set of suggestions.

Eventually a feature change requires coordination with three other teams and the review queue becomes a bottleneck. A micro-frontend spike promises independent deployments, team ownership, and faster iteration. On an architecture slide, it can look like a clean escape.

I watched this happen at an e-commerce company I worked with. Their product catalog, cart, and checkout were all in one Next.js app. They felt the pain of slow releases and proposed splitting each into its own micro-frontend. The plan was Module Federation, separate repos, independent CI pipelines.

Six months into the migration, they had extracted two of the three. They were spending more time debugging cross-app state than they had spent waiting on slow pull requests. The migration had changed the shape of the coordination work, but it hadn't made that work disappear.

Look for modularity first

When I've dug into these situations, unclear boundaries inside the existing app have usually caused more pain than the shared deployment pipeline.

Components import from each other freely. Features have no enforced interfaces. Shared state becomes a global soup that anyone can reach into. Splitting that code across deployments doesn't untangle it by itself.

You can test this before rebuilding the frontend infrastructure. Draw the feature boundaries, publish interfaces between them, and enforce the import rules inside the existing application. If teams still can't move independently, you have learned something useful about the deployment unit. If they can, you may have avoided a migration.

Nx or Turborepo can run separate build targets once you've split features into projects or packages. CODEOWNERS makes ownership explicit, and Nx's ESLint boundary rules can enforce which projects may import from each other. A shared component library also gives teams an interface they can agree on and version.

Someone still has to insist that other features use the cart module's published interface. Teams need to agree on that boundary and maintain it as the code changes. Without that work, the same disagreements tend to show up in routing, shared state, and versioning after a split.

When deployment really is the constraint

The cases I find convincing have a constraint that module boundaries within one application can't remove.

One is organizational scale. When many teams contribute to a frontend, good module boundaries may still leave releases coupled through a single build and deployment. At some point, the deployment unit itself can become the constraint. That point depends on the system and the organization, not a particular number of teams.

Another is legacy migration. The strangler fig pattern lets old and new frontends coexist while teams replace the system gradually. A full rewrite isn't always possible, so independently delivered pieces provide a workable seam during the transition.

The platform cost

The operational cost is easy to understate during an architecture review.

Your cart and product pages need to agree on what's in the cart. In a monolith, they can use the same store. Across independently deployed pieces, teams need to agree on how state changes travel between them, whether through custom events, a shared state bus, or API calls. That mechanism needs its own testing and maintenance.

Routing also needs an orchestrator to decide which micro-frontend handles each URL. That orchestrator becomes infrastructure in its own right. When two teams disagree about routing, the coordination problem now sits in the integration layer.

Dependencies multiply too. If three micro-frontends use React, they can share a copy and accept infrastructure-level coupling, or bundle separate copies and send more code to the browser. Either choice has a cost.

Then there's version skew. Team A ships a breaking change to the shared component library while Team B remains on the older version. Users see a different interface depending on which part of the page they're viewing. I've seen this happen in production, and it wasn't pleasant to debug.

A team I talked to last year used Module Federation to divide a B2B dashboard into five micro-frontends for five teams. Within a year, they had created an internal platform team to manage the integration layer. Three engineers worked full-time on the shell app and the cross-cutting concerns no product team wanted to own. That staffing cost belonged in the migration decision too.

Fix the modularity first

If your frontend feels slow to change, start by finding where the coupling actually lives.

Draw the module boundaries and decide which features should be isolated. Enforce those decisions with project boundaries or import restrictions.

Use CODEOWNERS to make responsibility and approval paths clear. Treat the component library and design system as shared infrastructure, with versions and documentation.

Then give features separate build and test targets. Tools such as Turborepo can limit runs to affected packages and their dependents. How much testing you can skip depends on the boundaries you've created; a change to a shared button may still affect most of the app.

After that work, you may still find that a shared deployment blocks teams. At least then the case for micro-frontends rests on a constraint you've measured, and you're going into the migration with clearer boundaries.