Concept #039
ArchitectureL'Architecture Monolithique
- architecture
- programmation
- devops
Qu'est-ce qu'un monolithe ?
Une architecture monolithique désigne une application déployée comme une seule et unique unité. Toute la logique métier, la gestion des données, l'interface utilisateur et les appels externes vivent dans la même base de code, partagent le même processus, et s'appuient sur une seule base de données.
Imaginez un immeuble où toutes les fonctions — bureaux, commerces, logements, parking — sont interconnectées en un seul bâtiment sans séparation structurelle. Changer une cloison peut affecter la stabilité de l'ensemble.
C'est l'architecture par défaut de la plupart des projets à leurs débuts, et souvent pour de bonnes raisons.
Les avantages du monolithe
Simplicité de démarrage
Lancer un monolithe ne requiert qu'un seul environnement, un seul déploiement, une seule configuration. Pour une équipe réduite ou un projet naissant, c'est un gain de temps considérable. Pas besoin de gérer la communication inter-services, les contrats d'API internes, ou l'orchestration de conteneurs.
Debugging et observabilité facilités
Toute la pile d'appels se trouve au même endroit. Reproduire un bug, inspecter les logs, suivre une requête de bout en bout — tout cela est immédiatement accessible. Pas besoin de corréler des traces distribuées entre cinq services différents pour comprendre pourquoi une commande a échoué.
Cohérence des transactions
Dans un monolithe, une transaction en base de données peut couvrir plusieurs domaines métier en un seul appel atomique. Pas de saga pattern, pas de compensation distribuée, pas d'état intermédiaire incohérent entre services. La cohérence des données est naturellement garantie par la base de données elle-même.
Itération rapide
Modifier une fonctionnalité qui touche plusieurs couches de l'application — du modèle à la vue, en passant par la logique métier — se fait en une seule pull request, dans un seul dépôt. L'équipe avance vite, sans coordination inter-équipes ni versioning d'API à gérer.
Les inconvénients à mesure que le projet grandit
Le déploiement devient un événement risqué
Quand tout est couplé, chaque déploiement déploie l'intégralité de l'application. Un changement mineur dans le module de facturation oblige à redéployer le module d'authentification, le catalogue produit, et tout le reste. La moindre régression peut affecter l'ensemble du système. Les déploiements deviennent rares, lourds, et stressants.
La scalabilité est coûteuse et rigide
Si le module de traitement d'images consomme beaucoup de CPU, vous devez scaler toute l'application — pas uniquement ce module. Impossible de n'allouer des ressources qu'aux parties qui en ont besoin. Le coût d'infrastructure augmente de façon disproportionnée.
La dette technique s'accumule
Au fil du temps, les frontières entre les modules s'estompent. Des dépendances croisées apparaissent. Le code de gestion des utilisateurs appelle directement la logique de recommandation, qui elle-même dépend du module de paiement. On se retrouve avec un big ball of mud : un enchevêtrement de dépendances où il devient difficile de modifier quoi que ce soit sans effets de bord imprévisibles.
Les équipes se marchent dessus
Avec une seule base de code, plusieurs équipes qui travaillent en parallèle multiplient les conflits de merge, les régressions involontaires et les blocages de déploiement. La coordination devient un goulot d'étranglement organisationnel autant que technique.
Quand le monolithe est le bon choix
Le monolithe n'est pas un anti-pattern. C'est souvent le choix le plus sensé dans ces situations :
- MVP et phases d'exploration : vous ne connaissez pas encore les vrais contours de votre domaine métier. Découper prématurément en services vous ferait tracer de mauvaises frontières, difficiles à corriger ensuite.
- Petites équipes (moins de 5-10 développeurs) : l'overhead de coordination des microservices dépasse largement les bénéfices.
- Applications à faible trafic : si votre application ne nécessite pas de scalabilité indépendante par domaine, la complexité ajoutée n'est pas justifiée.
- Domaine métier encore flou : mieux vaut un monolithe évolutif qu'une architecture distribuée figée autour de mauvaises abstractions.
Le monolithe modulaire : le meilleur des deux mondes
Une approche intermédiaire gagne du terrain : le monolithe modulaire. L'idée est simple — garder un seul déploiement, mais structurer rigoureusement le code en modules aux frontières bien définies, avec des interfaces explicites entre eux.
Chaque module encapsule son propre domaine métier, ses propres modèles de données, et n'expose que ce qui est nécessaire aux autres modules via des interfaces publiques claires. Les dépendances croisées directes sont interdites.
Cette approche offre la simplicité opérationnelle du monolithe tout en préparant le terrain pour une éventuelle migration vers des services indépendants. Si un module devient un candidat naturel à l'extraction, ses frontières sont déjà propres.
Quand envisager la migration vers SOA ou microservices
Certains signaux indiquent qu'il est temps de faire évoluer l'architecture :
- Les déploiements durent plus de 30 minutes et mobilisent toute l'équipe
- Des modules ont des besoins de scalabilité radicalement différents
- Des équipes autonomes doivent pouvoir déployer indépendamment
- Le temps de build et de test ralentit significativement l'itération
- Certaines parties du système nécessitent des technologies différentes (ex. un moteur de recommandation en Python dans une app Node.js)
La migration ne se fait pas en une seule fois. Le pattern Strangler Fig consiste à extraire progressivement des modules du monolithe vers des services autonomes, sans réécriture globale. Le monolithe "rétrécit" au fur et à mesure que les nouveaux services prennent le relais.
En résumé
Le monolithe est souvent diabolisé à tort. Pour démarrer vite, itérer en équipe réduite, et comprendre son domaine métier, c'est fréquemment le choix le plus pragmatique. Les problèmes n'apparaissent qu'à mesure que le système et l'équipe grandissent — et c'est précisément à ce moment-là qu'il faut savoir faire évoluer l'architecture.
La vraie erreur n'est pas de commencer par un monolithe. C'est de ne pas anticiper le moment où il faudra en sortir — et de ne pas avoir gardé le code suffisamment propre pour le faire.