Monolithe modulaire ou microservices : choisir la bonne architecture pour votre logiciel
Les microservices sont souvent présentés comme l'architecture moderne par excellence. Pourtant, pour une grande partie des projets, un monolithe modulaire bien conçu est plus rapide à livrer, plus simple à exploiter et tout aussi évolutif. Comment choisir, et quand changer ?
Sommaire 8 sections
- Le vrai sujet : maîtriser la complexité
- Le monolithe, mal-aimé à tort
- Les microservices : des bénéfices réels, des coûts souvent sous-estimés
- Le monolithe modulaire : le meilleur des deux mondes au démarrage
- Comparaison synthétique
- Les signaux qui justifient de passer aux microservices
- Évoluer progressivement : le modèle de l'« étrangleur »
- Notre recommandation
« Faut-il partir sur des microservices ? » C'est l'une des questions que nous entendons le plus souvent au démarrage d'un projet. La réponse honnête est : rarement dès le premier jour. Cet article explique pourquoi, et présente l'approche que nous privilégions : le monolithe modulaire.
Le vrai sujet : maîtriser la complexité
Une architecture logicielle a pour objectif principal de permettre au logiciel d'évoluer sans que chaque modification devienne plus coûteuse que la précédente. Le découpage en composants n'est pas une fin en soi : c'est un moyen de limiter l'impact d'un changement et de permettre à plusieurs personnes de travailler en parallèle.
Or on peut découper un logiciel de deux manières très différentes : en modules à l'intérieur d'une même application, ou en services déployés séparément et communiquant par le réseau.
Le monolithe, mal-aimé à tort
Le mot « monolithe » évoque souvent une application ancienne, enchevêtrée, où tout dépend de tout. Ce problème n'est pas lié au monolithe lui-même, mais à l'absence de structure interne. Un monolithe offre des avantages concrets :
- un seul déploiement, une seule base de code à comprendre ;
- des appels entre composants instantanés et fiables, sans latence réseau ;
- des transactions simples : une opération s'exécute entièrement ou pas du tout ;
- un débogage et des tests de bout en bout beaucoup plus simples ;
- une infrastructure et des coûts d'exploitation réduits.
Les microservices : des bénéfices réels, des coûts souvent sous-estimés
Les microservices permettent de déployer chaque partie du système indépendamment, de faire évoluer séparément les composants les plus sollicités et de confier chaque service à une équipe autonome. Ces bénéfices ont un prix :
- Le réseau devient un point de défaillance : chaque appel peut échouer, être lent ou arriver deux fois. Il faut gérer les délais d'attente, les nouvelles tentatives et les dégradations de service.
- La cohérence des données se complique : chaque service possède sa base, et une opération qui touche plusieurs services nécessite des mécanismes spécifiques (événements, compensations).
- L'observabilité devient indispensable : suivre une requête qui traverse cinq services nécessite du traçage distribué et une journalisation centralisée.
- L'infrastructure s'alourdit : orchestration de conteneurs, passerelle d'API, gestion des versions entre services.
- Les compétences requises augmentent, ainsi que le temps consacré à l'exploitation plutôt qu'aux fonctionnalités.
Pour une équipe de quelques développeurs, ces coûts dépassent généralement les bénéfices.
Le monolithe modulaire : le meilleur des deux mondes au démarrage
Un monolithe modulaire est une application unique, déployée d'un seul bloc, mais organisée en modules indépendants correspondant aux grands domaines métier. Chaque module possède ses propres données et n'est accessible aux autres qu'au travers d'une interface publique explicite.
src/
├── Inscriptions/
│ ├── Domain/ règles métier
│ ├── Application/ cas d'usage
│ ├── Infrastructure/ base de données, services externes
│ └── Api/ seul point d'entrée pour les autres modules
├── Facturation/
├── Pedagogie/
├── Communication/
└── Shared/ éléments techniques communs uniquement
Les règles qui font la différence :
- Découper selon le métier, pas selon les couches techniques. On s'appuie pour cela sur les « contextes délimités » de la conception pilotée par le domaine (DDD).
- Interdire les accès directs aux tables ou aux classes internes d'un autre module. Des outils d'analyse statique permettent de vérifier automatiquement ces règles à chaque modification.
- Privilégier les événements pour les réactions entre modules : lorsqu'un paiement est validé, le module Facturation publie un événement auquel le module Inscriptions réagit.
- Garder le module partagé minimal : il ne doit pas devenir un fourre-tout.
Cette organisation offre la simplicité d'exploitation du monolithe tout en préparant une éventuelle extraction de services : un module bien isolé peut devenir un microservice sans réécrire le reste de l'application.
Comparaison synthétique
| Critère | Monolithe modulaire | Microservices |
|---|---|---|
| Vitesse de démarrage | Élevée | Plus lente |
| Complexité d'exploitation | Faible | Élevée |
| Déploiement indépendant des composants | Non | Oui |
| Montée en charge ciblée | Globale | Par service |
| Cohérence des données | Simple (transactions) | Complexe (cohérence à terme) |
| Taille d'équipe adaptée | Une à plusieurs équipes | Plusieurs équipes autonomes |
| Coût d'infrastructure | Réduit | Plus élevé |
Les signaux qui justifient de passer aux microservices
- Plusieurs équipes se gênent mutuellement pour livrer, parce qu'elles partagent le même cycle de déploiement.
- Un composant a des besoins de charge très différents du reste de l'application, par exemple un moteur de calcul ou de génération de documents.
- Un composant nécessite une technologie différente, ou des exigences de disponibilité ou de sécurité spécifiques.
- Les modules sont déjà bien isolés, et leurs frontières stables.
Si aucun de ces signaux n'est présent, la migration apporterait surtout de la complexité.
Évoluer progressivement : le modèle de l'« étrangleur »
Lorsqu'une extraction devient nécessaire, nous évitons la réécriture complète, longue et risquée. Nous appliquons le modèle de l'« étrangleur » (strangler fig) :
- identifier le module à extraire et stabiliser son interface ;
- construire le nouveau service qui reprend cette responsabilité ;
- rediriger progressivement les appels vers le nouveau service, par exemple via une passerelle ;
- migrer les données correspondantes ;
- retirer l'ancien code une fois la bascule validée.
L'application reste en service pendant toute la transition, et chaque étape peut être annulée.
Notre recommandation
Commencez par un monolithe modulaire bien structuré. Extrayez un service lorsque vous avez une raison concrète et mesurable de le faire, pas avant.
Cette approche permet de livrer plus vite, avec des coûts maîtrisés, tout en conservant la possibilité d'évoluer. L'architecture n'est pas un choix figé : c'est une trajectoire, qui doit suivre la croissance réelle de votre produit et de vos équipes.