Review this. One checkout page is assembled at runtime from five independently deployed fragments - cart summary, address, delivery options, payment and order review - each owned by a different team. The fragments talk to each other through custom DOM events on the window object. Each team deploys daily. The page ships 2.4 MB of JavaScript because four fragments each bundle their own copy of the form library. A delivery-options change broke address validation twice last quarter. What would you remove, what is the one change that matters, and what would you leave alone?
Show the full answer Hide the answer
What is actually required
Five teams want to ship without waiting for each other. That is a real and legitimate requirement, and nothing about it requires five bundles on one page.
Look at what the page is. Checkout is one transaction with one invariant - the order is priced, addressed, paid and confirmed consistently or not at all. The five fragments are not five products; they are five steps of one workflow, and the workflow's rules now live in the gaps between five deployables where no owner and no type checker can see them.
What I would remove, and why it is safe to
The window event bus. It is an untyped, unversioned, unmonitored RPC channel with no schema, no delivery guarantee and no replay. When delivery-options changed its event payload, address validation stopped receiving a field it needed - no error, no HTTP 500, just a form that never validates, which is why it took two incidents to attribute. Removing it is safe because once the fragments share one build, the same communication becomes function calls the compiler checks.
Four duplicate copies of the form library. At roughly 45 KB compressed each, that is about 135 KB of pure duplication, and the framework runtime and the design system are duplicated the same way. The composed page's 2.4 MB is nobody's budget: each team's own number looks fine.
The one change that matters
Fold the five fragments into one build with one router, one form library and one design-system copy, and keep team ownership through directory ownership and required reviewers. Independent deployment of a shared transaction was the mistake; independent ownership of code was never in question.
Then put a budget on the thing users experience - the assembled page, as one number with one owner - because per-fragment budgets sum to something nobody is accountable for.
What I would leave alone, even though it looks odd
Daily deploys. That is what the teams actually wanted and a single application delivers it; the deploy cadence was never the reason for the split.
The shell and its slots, if genuinely independent page regions use them elsewhere - a marketing banner, a support widget, a region owned by a team on a different framework. Runtime composition is the right tool when the thing being composed is independent. Here it was applied inside a transaction.
How I would argue this in the review
Not as "micro-frontends are bad". Ask one question: name the invariant that spans these five fragments, and point at the code that enforces it. If nobody can, the boundary is in the wrong place. Then show the incident timeline and the composed-page byte count next to each team's green dashboard.
When not to split at all
A single application is the right answer until two conditions hold at once: the teams' release cadences are genuinely independent, and their code shares no page and no invariant. In practice that means they own different routes or different products - admin versus reporting, or an acquired application on a framework you are not going to rewrite.
The usual honest threshold is organisational rather than technical: beyond roughly eight to ten teams who cannot agree on a release train, or one codebase you cannot migrate, runtime composition starts paying for itself. Below that, route-level splitting gives the same deploy independence with none of the runtime resolution, singleton skew or un-rollbackable remotes.