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.
The migration hurts more than the monolith did
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.
Modern tooling supports that experiment. Nx or Turborepo can provide independent build targets per feature. CODEOWNERS makes ownership explicit. ESLint boundaries can enforce import rules, while a design system and component library provide contracts between teams.
None of this is glamorous, and it requires discipline. Someone has to say, "You can't import directly from the cart module. Use the published interface." A new deployment model can't have that conversation for you. Without agreed boundaries, the arguments simply move into routing, shared state, and versioning.
When deployment really is the constraint
Micro-frontends do solve real problems in some contexts. The use cases I find convincing tend to have a constraint that in-process modularity 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.
Those are contextual decisions. They don't turn micro-frontends into a general upgrade for any codebase that feels slow.
The platform cost
The operational cost is easy to understate during an architecture review.
Shared state across micro-frontends is genuinely hard. Your cart and product pages need to agree on what's in the cart. In a monolith, that's a shared store. Across micro-frontends, that's a coordination problem. Custom events, shared state buses, or duplicated API calls. Each approach has tradeoffs and failure modes.
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. The original coordination problem hadn't vanished. Three people now maintained the place where it landed.
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 independent build and test targets. Most monorepo tools can run only what changed, so a button in the settings page doesn't need to trigger the entire suite.
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.
If you've worked in a micro-frontend setup, where did the coordination work end up? Did independent deployment remove a bottleneck, or did the integration layer become the new one?