Les micro-frontends sont devenus l'un des patterns architecturaux les plus débattus dans le développement frontend. Les partisans disent qu'ils permettent des déploiements d'équipe indépendants et une mise à l'échelle. Les critiques disent qu'ils ajoutent une complexité inutile. Les deux ont raison — la question est quel compromis compte le plus pour votre situation spécifique.
J'ai une perspective unique sur le sujet car j'étais l'architecte principal d'une architecture micro-frontend pour la stratégie B2C d'AXA Suisse, et j'ai aussi choisi de NE PAS utiliser les micro-frontends dans des rôles ultérieurs. Les deux décisions étaient correctes dans leur contexte.
Le problème que les micro-frontends résolvent vraiment
Les micro-frontends résolvent bien un problème : l'indépendance organisationnelle. Quand vous avez plusieurs équipes qui doivent livrer des fonctionnalités pour la même application utilisateur à des rythmes différents, et que la coordination entre ces équipes est devenue un goulot d'étranglement, les micro-frontends peuvent aider.
C'est tout. Ils ne rendent pas votre application plus rapide (généralement le contraire). Ils ne rendent pas votre code plus propre. Ils ne réduisent pas la complexité. Ils échangent de la complexité technique contre de la flexibilité organisationnelle.
Chez AXA, nous avions exactement ce problème. Plusieurs équipes géraient différentes parties de l'expérience client B2C : devis d'assurance, sinistres, gestion des polices et onboarding. Chaque équipe avait sa propre cadence de sprint, ses propres priorités et son propre calendrier de releases. Un frontend monolithique signifiait qu'un bug dans le module sinistres pouvait bloquer une release du module devis. Les équipes passaient plus de temps à coordonner les déploiements qu'à développer des fonctionnalités.
Comment nous l'avons fait chez AXA
Notre approche était pragmatique, pas idéologique. Nous n'avons pas poursuivi le rêve microservices du « chaque équipe choisit son propre framework ». Nous avons standardisé sur React et TypeScript — la liberté était dans l'indépendance de déploiement, pas dans le choix technologique.
Chaque module était une application autonome qui pouvait être construite, testée et déployée indépendamment. Une application shell légère gérait le routage, l'authentification et le layout partagé. Les modules communiquaient via un bus d'événements défini, pas par des imports directs. La différence clé avec les approches runtime : l'agrégation se faisait au moment du build, mais chaque app pouvait quand même se déployer individuellement. Cela signifiait que l'équipe devis pouvait déployer trois fois par jour tandis que l'équipe sinistres déployait chaque semaine, sans aucune coordination.
// Simplified module registration in the shell app
interface MicroFrontendModule {
name: string;
basePath: string;
load: () => Promise<{ mount: (el: HTMLElement) => void }>;
}
const modules: MicroFrontendModule[] = [
{
name: 'quotes',
basePath: '/insurance/quotes',
load: () => import('quotes-module/bootstrap'),
},
{
name: 'claims',
basePath: '/claims',
load: () => import('claims-module/bootstrap'),
},
];
// Each module mounts into its container independently
// Shell handles routing and passes context via eventsLes vrais coûts dont personne ne parle
Voici ce que les conférences omettent :
L'état partagé est difficile. Vraiment difficile. Quand deux micro-frontends doivent partager le contexte utilisateur, l'état du panier ou les compteurs de notifications, vous construisez essentiellement un système distribué dans le navigateur. Nous avons passé des semaines à synchroniser l'état d'authentification de manière fiable entre les modules sans conditions de course.
La cohérence UX coûte cher. Quand les modules sont déployés indépendamment, des incohérences visuelles s'installent. Le module A est livré avec des styles de boutons mis à jour tandis que le module B a encore les anciens. Nous avons résolu cela avec notre bibliothèque de guide de style basée sur les Web Components — des composants agnostiques au framework que chaque module consommait. Mais construire et maintenir cette bibliothèque était un investissement considérable.
La surcharge de performance est réelle. Chaque module apporte sa propre surcharge d'exécution. Même avec les dépendances partagées extraites dans un chunk commun, le chargement initial est plus lourd qu'une application unique. Chez AXA, notre Time to Interactive a augmenté d'environ 800ms par rapport au monolithe. Nous avons optimisé avec du lazy loading et du prefetching agressifs, mais la surcharge n'a jamais complètement disparu.
L'expérience développeur en souffre. Faire tourner l'application complète localement signifie orchestrer plusieurs serveurs de développement. Le débogage à travers les frontières des modules est pénible. Les tests d'intégration nécessitent que tous les modules soient disponibles. Nous avons construit un outillage conséquent pour rendre cela praticable, ce qui était en soi une charge de maintenance.
Quand j'ai choisi de ne pas les utiliser
Chez Migros, en construisant Bikeworld et Micasa, nous avions un problème similaire en surface : plusieurs boutiques partageant de l'infrastructure. L'instinct aurait pu être d'utiliser des micro-frontends. Mais j'ai choisi un monorepo PNPM avec Turbo à la place.
Pourquoi ? Parce que le problème organisationnel était différent. Nous avions une seule équipe qui construisait les deux boutiques, pas plusieurs équipes nécessitant des déploiements indépendants. Les boutiques partageaient un design system et de l'infrastructure mais avaient des pages produit et des flux de checkout différents. Un monorepo avec des packages partagés nous donnait la réutilisation de code sans la complexité de déploiement.
Chez Vontobel, en construisant une plateforme financière complexe unique, les micro-frontends auraient été du pur overhead. Une équipe, une cible de déploiement, un cycle de release. Une application Next.js bien structurée avec des frontières de modules claires — imposées par les règles de linting et la revue de code, pas par l'isolation à l'exécution — était la bonne réponse.
Chez UBS, nous utilisons effectivement des micro-frontends avec Webpack Module Federation au sein de 3 équipes. Nous avons un monorepo basé sur Turborepo, mais les modules sont agrégés au runtime — chaque équipe peut déployer indépendamment. C'est une approche différente d'AXA, où l'agrégation se faisait au build. Les deux fonctionnent, mais la fédération runtime nous donne des déploiements indépendants plus rapides tandis que le monorepo maintient la cohérence du code partagé et de l'outillage.
Le cadre de décision
Après avoir vécu avec les micro-frontends et choisi des alternatives, voici mon cadre pour déterminer quand ils ont du sens :
Utilisez les micro-frontends quand : vous avez 4+ équipes livrant à la même application, la coordination des déploiements est devenue un goulot d'étranglement mesurable (pas juste un désagrément), les équipes ont des cadences de release véritablement différentes, et vous avez la capacité d'ingénierie pour construire et maintenir l'infrastructure requise (shell app, bibliothèques partagées, outillage, pipelines CI/CD).
N'utilisez pas les micro-frontends quand : vous avez moins de 3 équipes, vous voulez utiliser différents frameworks par module (le coût UX est trop élevé), votre application a de fortes dépendances de données inter-modules, vous n'avez pas de capacité dédiée en ingénierie de plateforme, ou vous les choisissez parce qu'ils sont à la mode plutôt que parce que vous avez ressenti la douleur qu'ils résolvent.
// Alternatives that solve similar problems with less cost
// 1. Monorepo with package boundaries
// Good for: shared code, independent builds, one team
// pnpm-workspace.yaml + turborepo
// 2. Module-level code splitting in a single app
// Good for: lazy loading, team ownership areas
const AdminModule = lazy(() => import('./modules/admin'));
const QuotesModule = lazy(() => import('./modules/quotes'));
// 3. Feature flags for independent feature releases
// Good for: decoupling deployment from release
if (flags.newCheckout) {
return <NewCheckout />;
}L'architecture est une question de compromis
La meilleure architecture est la plus simple qui résout vos problèmes réels. Pas les problèmes que vous pourriez avoir dans deux ans. Pas les problèmes que l'entreprise qui a écrit cet article Medium avait. Vos problèmes, aujourd'hui.
Les micro-frontends ont résolu un vrai problème chez AXA avec l'agrégation au build. Chez UBS, la fédération runtime avec Webpack Module Federation convient à 3 équipes travaillant depuis un monorepo. Un monorepo a résolu un vrai problème chez Migros. Une application unique bien structurée a résolu un vrai problème chez Vontobel. Le pattern n'a pas changé — comprenez d'abord le problème, puis choisissez la solution la plus simple qui y répond.
Si cela ressemble à YAGNI appliqué à l'architecture, c'est exactement ça. Les principes sont les mêmes à chaque niveau d'abstraction.

