Decision: use a modular monolith by default. Move to microfrontends only when independent frontend deployment is worth the platform tax.

The Default Fighter: Modular Monolith

A modular monolith keeps one app, one routing model, and one local setup while preserving domain boundaries in the code. It is the heavy hitter when delivery speed, simplicity, and product consistency matter more than separate deployments.

  • Speed: teams spend less time maintaining integration infrastructure while the product is still changing.
  • UX consistency: one shell, shared state, and one design system leave fewer seams for users to trip over.
  • Debugging: failures usually remain inside one runtime and one call stack instead of crossing remote boundaries.

The Specialist: Microfrontends

Microfrontends become useful when several mature teams own stable domains and genuinely need to ship them independently. They trade simplicity for autonomy; that trade is worthwhile only when the shared frontend release train has become a measurable bottleneck.

  • Independent deploys: domain teams can ship without waiting for a crowded central release.
  • End-to-end ownership: a team can own its UI, runtime, contracts, and delivery path.
  • Incremental migration: old and new stacks can coexist behind a shell when a full rewrite would be too risky.

Fight Summary

SituationSmall or medium team
Better defaultModular monolith
WhyLess platform work and more time shipping.
SituationMany teams blocked by one release train
Better defaultMicrofrontends
WhyIndependent deployments remove the shared queue.
SituationStrong need for consistent UX
Better defaultModular monolith
WhyOne app shell protects product polish.
SituationStable domains with separate owners
Better defaultMicrofrontends
WhyOwnership maps cleanly to shipped slices.
SituationProduct direction still changing
Better defaultModular monolith
WhyBoundaries are not stable enough to split.
SituationLegacy migration
Better defaultMicrofrontends
WhyNew UI can enter without forcing a full rewrite.

The Knockout Rule

Do not split because the codebase feels big. Messy components, slow CI, unclear ownership, and framework arguments are cleanup and platform problems first. Microfrontends can expose those problems faster; they rarely make them disappear.

Split only after domains are stable, teams own product areas end to end, and someone is ready to own the shell, contracts, observability, and integration tests.