Lessons Learned in Migrating to Micro-Frontends
Luca Mezzalira, Principal Solutions Architect at AWS, at QCon San Francisco 2025, published by infoq. Twenty years in architecture, and the talk is drawn from having taken hundreds of teams through monolith-to-micro-frontend migrations, inside Amazon and out.
T2, and here is what that rests on. Not a study — a practitioner reporting migrations he ran, with
numbers attached and named failures. That is the “someone used the thing” case in ../QUALITY.md. It is
also one person’s experience, selected by him.
The distinction the whole talk turns on
A micro-frontend is not a component loaded at runtime. Components are fine-grained and reusable, and the container tells them what to do — which means the container must know how to configure them. Mezzalira’s line: “when you optimize for reusability, you create coupling.” Micro-frontends are coarse-grained and self-contained, each one “aware of how the things are working,” and they optimize for independence rather than reuse — specifically, for reducing “external dependencies of our teams.”
That sentence is why this spoke exists and does not live inside ../ui-frameworks-wiki. The unit of
design here is a team’s boundary, not a widget.
The reasons that count as reasons
Before any technique, the talk insists on why anyone would distribute a frontend at all: team autonomy (no waiting on another team), organizational scalability (adding teams without slowing the existing ones), agility (responding to outside change), and fast flow (shipping often enough to learn from users). Absent one of those, the architecture is cost without benefit.
Six steps, compressed
- Decide four things up front — application shell versus UI composer (who owns configuration, authorization, composition, routing); vertical split (views grouped by domain) versus horizontal (several micro-frontends inside one view); server-side versus client-side rendering; and where routing happens (edge, API gateway, or client).
- Pick an architecture from the known shapes: CDN plus static files, server-side first-level URL routing to containers, runtime page loading, or a caching layer in front (the BBC’s approach).
- Identify the units by heuristics such as code volatility, starting coarse. His DAZN example split a live-streaming platform into five: landing, onboarding, catalog-plus-player, account, help.
- Take the first one end to end, design through production. The app shell should be “technology agnostic” and stable — “if you are capable of creating an application shell that doesn’t change very often after one year, you are in a good way.”
- Deploy the rest, deciding shared libraries deliberately and avoiding “micro-frontends anarchy” (frameworks and versions mixed as a permanent state rather than a migration phase).
- Communicate narrowly — cookies or local storage for persistent data, query strings for ephemeral data, event emitters for horizontal splits. Global state is out; it creates “a lot of complexity.”
The migration technique, which is the practical core
A Strangler Fig rollout run from edge compute: the CDN consults externalized JSON or a service to decide, per request, whether a user gets the legacy monolith or the new micro-frontend. That buys canary releases (10% of users on a new catalog) and rollback by configuration change rather than redeployment.
The number attached to it: one team went from 3 deployments a month to 25 per day per team, and the stated cause is not the architecture but the “safe net” — reversibility, not modularity.
Duplication, priced
“Duplication is far cheaper than the wrong abstraction.” The evidence he gives is a header his team changed once in three years, which is an argument that the abstraction would have earned nothing. The counter-example, also his: a team that spent four months shipping nothing refactoring global state.
What GenAI does and does not do here
Useful for fitness functions — he names a “micro-frontend bundle ≤ 30 kilobytes” constraint — and for enforcing architecture rules with libraries such as ts-arch (blocking unwanted imports), plus dependency management. It struggles with library incompatibility (React Router against Module Federation needed a manual downgrade), and with modularization itself, because the context is lost over a long session. His warning is about cognitive load: the tool generates and deletes code, so the person has to stay intentional. “Be explicit … and try to do it iteratively. Start small. Plan first.”
The fitness-function idea is the seam to ../webperf-wiki: a byte budget used as an architectural
boundary check rather than a performance target.
Stated anti-patterns
Loading everything at runtime with no plan · serving static files from containers instead of CDN plus object storage · abstracting shared components early · treating multi-framework anarchy as an end state · global state across units · choosing monorepo or polyrepo without seeing the cultural consequence · copying another company’s model (the Spotify one is named) without its context. And the summary position: micro-frontends are not a silver bullet, they require a distributed-systems mindset.
The socio-technical claim
Architecture, organization and engineering culture move together: a monorepo-versus-polyrepo choice “is affecting all three of those dimensions.” “Don’t think that it’s just a technical decision.” Two scale figures make the point concrete — a customer’s Vaadin migration covering 900 views, and the four-month refactor above.
Related
micro-frontends · application-architecture · app-shell · flutter-large-app-structure · luca-mezzalira · infoq · synthesis