Monolithe ou micro-services pour une application métier ? Notre choix par défaut
Vincent
Co-fondateur, direction technique

En bref
Faut-il partir sur une architecture monolithique ou en micro-services pour une application métier ?
Partez sur un monolithe modulaire, sauf raison explicite de faire autrement. Les micro-services résolvent des problèmes d'organisation — plusieurs équipes qui doivent déployer indépendamment — et de mise à l'échelle différenciée. Une application métier avec une seule équipe n'a ni l'un ni l'autre : elle hérite alors de toute la complexité distribuée sans aucun des bénéfices. Le bon découpage se découvre en construisant, pas en dessinant.
C’est la question qui revient le plus souvent en conception, et celle sur laquelle j’ai le plus changé d’avis en dix ans. Aujourd’hui ma position est stable : monolithe modulaire par défaut, et il faut une raison explicite pour en sortir.
Ce n’est pas du conservatisme. C’est le constat que les micro-services résolvent des problèmes que la plupart des applications métier n’ont pas — tout en créant des problèmes qu’elles n’avaient pas.
Ce que les micro-services résolvent réellement
Deux choses, et deux seulement.
Un problème d’organisation. Quand plusieurs équipes doivent livrer sans se coordonner, découper le système en services déployables indépendamment supprime le goulot d’étranglement. C’est le problème d’origine, chez des entreprises comptant des dizaines d’équipes.
Un problème de mise à l’échelle différenciée. Quand un composant consomme mille fois plus de ressources que les autres, l’isoler permet de le dimensionner séparément. Traitement d’images, calcul lourd, ingestion massive d’événements.
Si vous n’avez ni l’un ni l’autre, les micro-services vous apportent uniquement leur coût.
Ce qu’ils coûtent
Ce coût est réel, il est permanent, et il est rarement chiffré au moment de la décision.
Les transactions disparaissent. Dans un monolithe, écrire dans trois tables de façon atomique est une ligne de code. Réparti sur trois services, cela devient une gestion de cohérence à terme, des compensations, et des états intermédiaires à traiter. Ce n’est pas infaisable ; c’est un ordre de grandeur de complexité supplémentaire.
Le débogage devient une enquête. Une erreur traverse quatre services. Sans traçabilité distribuée correctement outillée, comprendre ce qui s’est passé prend des heures au lieu de minutes.
L’environnement de développement se dégrade. Faire tourner l’ensemble sur un poste devient difficile. Les développeurs travaillent alors sur une partie du système, avec des simulateurs — et les bugs d’intégration se découvrent tard.
Les déploiements se multiplient. Chaque service a son cycle, ses versions, sa compatibilité ascendante à préserver. C’est du travail d’infrastructure permanent, qui n’apporte aucune valeur fonctionnelle visible.
Photo : Leeroy — licence CC0.
Le monolithe modulaire, concrètement
Ce n’est pas « tout dans un fichier ». C’est une application unique, déployée d’un bloc, mais découpée en modules aux frontières explicites.
En pratique, chez nous :
- Chaque module possède son dossier, son interface publique et ses règles internes.
- Un module n’accède jamais aux tables d’un autre : il passe par l’interface publique.
- Les dépendances entre modules sont vérifiées automatiquement, et une violation casse la construction.
- Le schéma de base est découpé par domaine, même si la base est unique.
Le résultat : les bénéfices du découpage — clarté, testabilité, propriété des modules — sans le coût du réseau. Et surtout, une frontière mal placée se corrige en une journée au lieu d’une migration.
Les trois cas où nous sortons du monolithe
Un composant au profil de charge radicalement différent. Traitement de fichiers volumineux, génération de documents en masse, agent temps réel. Nous l’extrayons parce que son dimensionnement n’a rien à voir avec celui du reste.
Une contrainte de disponibilité asymétrique. Une partie du système doit rester debout quand le reste est en maintenance. Un tunnel de paiement, une API publique consommée par des tiers.
Une contrainte réglementaire d’isolation. Des données soumises à un régime particulier, qu’il vaut mieux séparer physiquement pour simplifier l’audit.
Notez qu’aucun de ces cas n’est « l’application devient grosse ». La taille seule ne justifie pas l’extraction ; elle justifie une meilleure modularité.
Photo : rawpixel — licence CC0.
Photo : The Building Envelope — licence CC0.
Comment préparer une extraction sans la subir
La bonne nouvelle : un monolithe modulaire bien fait rend l’extraction facile le jour où elle devient nécessaire.
Trois habitudes suffisent. Communiquer entre modules par interfaces explicites, jamais par accès direct aux données. Rendre les identifiants stables et non dépendants de la base, pour qu’ils survivent à une séparation. Isoler les effets de bord — envoi d’e-mails, appels externes — derrière des abstractions, pour pouvoir les déplacer.
Avec ça, extraire un module devient un chantier de quelques semaines, mené quand le besoin est avéré plutôt que par anticipation.
L’erreur de séquencement la plus coûteuse
Découper avant de connaître le domaine.
Sur un projet neuf, personne ne sait encore où passent les vraies frontières métier. Les poser d’emblée dans des services séparés fige un découpage fondé sur des hypothèses, et ces hypothèses sont fausses la plupart du temps.
Le problème n’est pas de se tromper — c’est que la correction devient très coûteuse. Déplacer une responsabilité d’un module à un autre à l’intérieur d’un monolithe se fait en une journée. La déplacer d’un service à un autre suppose de modifier deux dépôts, deux déploiements, un contrat d’interface et une migration de données.
D’où la règle que j’applique sans exception : le découpage se décide après avoir vécu avec le domaine, pas avant. Les frontières correctes se révèlent d’elles-mêmes, et elles se signalent par un fait observable : ce sont les endroits où les modifications ne traversent jamais.
Les sujets qu’on découvre après la séparation
Quatre points apparaissent le lendemain de l’extraction, et rarement dans les études préalables.
Les transactions disparaissent. Ce qui s’écrivait dans une transaction unique devient une suite d’opérations dont certaines peuvent échouer. Il faut alors prévoir des compensations, c’est-à-dire du code métier supplémentaire pour défaire ce qui a déjà réussi.
Les appels réseau échouent. Un appel de fonction ne rate jamais ; un appel entre services, oui. Chaque point d’appel doit gérer le délai d’attente, la reprise, et le cas où le service distant répond lentement plutôt que pas du tout — le plus pénible des trois.
Les environnements se multiplient. Faire tourner l’ensemble sur un poste de développeur devient un sujet en soi, et le confort de développement se dégrade nettement.
La donnée se duplique. Chaque service finit par conserver une copie locale de ce dont il a besoin, et il faut décider de la fraîcheur acceptable de cette copie. C’est une question métier, pas technique, et elle doit être posée à chaque fois.
Aucun de ces points n’est rédhibitoire. Ils expliquent simplement pourquoi une extraction ne se décide pas sur la seule élégance du schéma.
Le raisonnement que je propose en conception
Une seule question : qu’est-ce qui vous empêche aujourd’hui de livrer plus vite ?
Si la réponse est « nos équipes se marchent dessus au déploiement », les micro-services répondent au problème. Si la réponse est « nous ne savons pas ce que veut le métier » ou « la recette prend trois semaines », ils n’y changeront rien — et ajouteront de la complexité à un projet qui en a déjà.
Dans mon expérience, la deuxième réponse est de très loin la plus fréquente.