Architecture

Quand migrer d’un monolithe vers des microservices (et quand ne pas le faire)

| 11 min de lecture
Terminal avec code exécuté sur un écran sombre

Restez monolithique jusqu'à ce que vous ayez plus de 20 ingénieurs et résolvez les conflits de déploiement deux fois par semaine. Les microservices coûtent entre 500 et 5 000 $/mois en infrastructure, contre entre 50 et 200 $ pour un monolithe, et les équipes consacrent 20 à 30 % de leur capacité aux opérations. Utilisez le modèle de figue étrangleur pour extraire un service à la fois lorsque des signaux de douleur spécifiques apparaissent.

La plupart des startups qui adoptent les microservices trop tôt le regrettent. La plupart des entreprises qui s’en tiennent trop longtemps aux monolithes le regrettent. La question n’est pas de savoir lequel est le meilleur. C'est quand changer.

Cet article couvre les véritables compromis entre les architectures monolithiques et de microservices, les signaux qui vous indiquent qu'il est temps de migrer, les signaux qui vous indiquent que ce n'est pas le cas, et l'approche étape par étape qui évite les erreurs les plus courantes (et les plus coûteuses).

Qu'est-ce qu'un monolithe et pourquoi il fonctionne

Un monolithe est une seule unité déployable. Une base de code, une base de données, un pipeline de build, un déploiement. Votre module d'authentification, votre système de facturation, votre service de notification, votre couche API ; ils vivent tous dans le même référentiel et se déploient ensemble.

Cela semble limitatif, mais pour la plupart des équipes, c'est le contraire. Un monolithe vous donnevitesse. Vous refactorisez au-delà des limites du module en une seule demande d'extraction. Vous exécutez une suite de tests. Vous déployez un artefact. Vous déboguez en lisant un ensemble de journaux. Il n'y a pas de latence réseau entre les services car il n'y a pas d'appels réseau ; ce sont tous des appels de fonction en cours.

Chaque entreprise technologique prospère a commencé comme un monolithe. Shopify gère une application Rails monolithique qui génère des milliards de dollars de transactions. Stack Overflow dessert 100 millions de visiteurs mensuels à partir d'un monolithe. Ce ne sont pas des entreprises incapables de comprendre les microservices. Ce sont des entreprises qui ont compris que le monolithe était l’outil idéal pour résoudre leur problème.

Si moins de 20 ingénieurs travaillent sur la même base de code, un monolithe est presque certainement le bon choix. Arrêt complet.

Que sont les microservices et ce qu'ils vous coûtent

Une architecture de microservices divise votre application en services indépendants. Chaque service possède sa propre base de données, se déploie indépendamment et communique avec d'autres services via des API (généralement REST ou gRPC) ou des files d'attente de messages.

La promesse : les équipes peuvent déployer de manière indépendante, faire évoluer les composants individuels et utiliser différentes technologies là où cela a du sens. Le service de facturation peut évoluer pour gérer le traitement des factures de fin de mois sans faire évoluer l'ensemble de l'application. Le service de recherche peut utiliser Elasticsearch tandis que le reste de l'application s'exécute sur PostgreSQL.

Le coût : vous utilisez désormais un système distribué. Les systèmes distribués sont plus difficiles à créer, à tester et à déboguer. Voici à quoi vous vous inscrivez :

  • Pannes de réseau entre les services.Dans un monolithe, un appel de fonction fonctionne ou lève une exception. Dans les microservices, une requête peut expirer, renvoyer une réponse partielle ou échouer silencieusement. Vous avez besoin d'une logique de nouvelle tentative, de disjoncteurs et de stratégies de secours pour chaque appel interservices.
  • Transactions distribuées.Lorsqu'une seule opération s'étend sur deux services (facturer le client, puis mettre à jour l'inventaire), vous avez besoin de sagas ou d'éventuels modèles de cohérence. Ceux-ci sont complexes à construire et pénibles à déboguer.
  • Frais généraux d’observabilité.Une seule demande peut toucher 6 services. Sans traçage distribué (Jaeger, Zipkin ou Datadog APM), le débogage d'une requête ayant échoué signifie rechercher dans 6 flux de journaux distincts dans l'espoir de corréler les horodatages.
  • Complexité du déploiement.Vous avez besoin d'une orchestration de conteneurs (Kubernetes ou ECS), d'une découverte de services, de passerelles API et de pipelines CI/CD pour chaque service. Un pipeline devient 15.
  • Défis de cohérence des données.Chaque service possède sa base de données. La jonction de données entre services signifie des appels API, et non des jointures SQL. Le reporting devient un projet d'ingénierie, pas une requête.

Aucun de ces problèmes n’est insoluble. Mais chacun ajoute des heures d'ingénierie, des coûts d'infrastructure et une complexité opérationnelle qu'un monolithe ne supporte pas.

Le monolithe va bien jusqu'à ce que ce ne soit plus le cas

Quatre signaux spécifiques vous indiquent que votre monolithe est devenu trop grand :

1. Déployer les conflits de fréquence

L'équipe A doit envoyer un correctif de facturation aujourd'hui. La fonctionnalité à moitié terminée de l'équipe B se trouve dans le même pipeline de déploiement et interrompt la préparation. L'équipe A attend. L'équipe B se précipite pour corriger son code. Les deux seront expédiés plus tard que prévu. Lorsque cela se produit une fois par mois, c'est un petit désagrément. Lorsque cela se produit deux fois par semaine, vous perdez des jours de temps d'ingénierie en raison des frais généraux de coordination.

2. Les équipes se marchent les unes sur les autres

Fusionnez les conflits dans les modules partagés. Deux équipes modifiant le même schéma de base de données dans le même sprint. Révisions de code qui nécessitent le contexte de trois domaines de fonctionnalités différents. Ce sont des signes que votre base de code s'est développée au-delà de ce qu'une seule équipe peut posséder. Lorsque les ingénieurs passent plus de temps à coordonner qu’à coder, le monolithe vous ralentit.

3. Le bug d'un module supprime tout

Une fuite de mémoire dans le code de traitement d'image fait planter l'ensemble de l'application, y compris l'extraction. Une requête de base de données lente dans le module de reporting dégrade les temps de réponse de l'API pour tous les utilisateurs. Dans un monolithe, les modules partagent des ressources. Une défaillance d’un composant se répercute sur tous les autres composants. Si votre chemin de revenus le plus critique (paiement, paiements, API principale) est interrompu par des défaillances de modules moins critiques, c'est un signal clair.

4. La mise à l'échelle d'une fonctionnalité signifie la mise à l'échelle de l'ensemble de l'application

Votre module de transcodage vidéo a besoin de 8x le CPU de votre couche API. Mais ils se déploient comme une seule unité, vous utilisez donc 8x CPU pour l'ensemble de votre application afin de satisfaire les besoins d'un composant. Votre facture d'infrastructure est 5 à 10 fois plus élevée que nécessaire, car vous ne pouvez pas faire évoluer les composants de manière indépendante.

Si vous ressentez régulièrement deux ou plusieurs de ces signaux, il est temps de commencer à penser à l’extraction. Pas une réécriture complète. Extraction.

Signes que vous n'êtes PAS prêt pour les microservices

Avant de commencer à planifier une migration, vérifiez ces cinq conditions. Si l’un d’entre eux s’applique, restez avec votre monolithe.

  • Vous avez moins de 5 ingénieurs.Les microservices résolvent les problèmes de coordination d’équipe. Une équipe de 3 personnes n'a pas de problèmes de coordination ; il dispose d'une chaîne Slack et d'un tableau blanc. Les frais généraux liés à l'exécution d'une infrastructure distribuée consommeront 30 à 40 % de la capacité de votre petite équipe.
  • Vous servez moins de 10 000 utilisateurs.À faible trafic, un seul serveur gère tout confortablement. Les microservices ajoutent de la latence (sauts de réseau entre les services) et de la complexité sans offrir d'avantages d'évolutivité significatifs à ce volume.
  • Vous n'avez aucune expérience DevOps dans l'équipe.Les microservices nécessitent une orchestration de conteneurs, une configuration de maillage de services, une journalisation distribuée et des pipelines de déploiement automatisés. Sans quelqu'un qui a exploité ces systèmes en production, vous passerez des mois à créer une infrastructure plutôt que des fonctionnalités.
  • Vous n’avez aucune surveillance ou observabilité en place.Si vous ne pouvez pas retracer une demande via votre monolithe aujourd'hui, vous ne pourrez certainement pas la retracer sur 10 services demain. Configurez une journalisation structurée, un suivi des erreurs (Sentry) et une surveillance des performances des applications (Datadog, New Relic) avant de diviser quoi que ce soit.
  • Vous n'avez pas défini de limites claires pour les modules dans votre monolithe.Si votre code est un réseau enchevêtré où le module de facturation lit directement la table de session utilisateur et le système de notification écrit dans la base de données des commandes, extraire un service sera un cauchemar. Nettoyez d'abord les limites.

Le chemin de migration : le motif du figuier étrangleur

La plus grosse erreur que commettent les équipes est de tenter une réécriture Big Bang. Ils passent 6 à 12 mois à reconstruire l’intégralité du système sous forme de microservices pendant que le monolithe continue de fonctionner en production. Au moment où la réécriture est « terminée », le monolithe dispose de 6 à 12 mois de nouvelles fonctionnalités que la réécriture n'a pas. La réécriture ne rattrape jamais son retard. Le projet est annulé. L'équipe est démoralisée.

Le motif de figue étrangleur évite complètement cela. Du nom du figuier étrangleur qui pousse autour d’un arbre hôte et le remplace progressivement, cette approche se déroule en trois étapes :

  • Étape 1 :Identifiez un composant à extraire. Acheminez son trafic via une passerelle API ou un proxy.
  • Étape 2 :Construisez le nouveau service aux côtés du monolithe. Les deux fonctionnent simultanément en production. Le proxy achemine le trafic vers le nouveau service pour le composant extrait et vers le monolithe pour tout le reste.
  • Étape 3 :Une fois que le nouveau service gère 100 % de son trafic de manière fiable, supprimez l'ancien code du monolithe. Répétez avec le composant suivant.

Cette approche comporte peu de risques car vous ne remplacez jamais l'ensemble du système en même temps. Si le nouveau service rencontre des problèmes, le proxy renvoie le trafic vers le monolithe. Les utilisateurs ne le remarquent jamais.

Que extraire en premier

Vous avez deux bonnes options pour votre première extraction :

Option A : Le composant qui change le plus souvent.Regardez votre journal git. Quel répertoire a eu le plus de commits au cours des 6 derniers mois ? C'est le composant qui provoque le plus de conflits de déploiement. Son extraction donne à vos équipes une indépendance de déploiement immédiate.

Option B : le composant qui nécessite une mise à l’échelle indépendante.Si votre module de traitement vidéo consomme 10 fois les ressources de votre couche API, son extraction vous permet de faire évoluer (et de payer) chaque composant indépendamment. Les économies de coûts à elles seules peuvent justifier l’effort de migration.

Ne commencez pas par le composant le plus complexe. Ne commencez pas par le composant qui a le plus de dépendances sur d'autres modules. Choisissez quelque chose avec des limites claires, une surface d'API claire et une équipe prête à s'enapproprier de bout en bout. Votre première extraction est un exercice d’apprentissage autant qu’une amélioration architecturale.

Erreurs courantes qui tuent les migrations de microservices

Extraire trop de services trop rapidement

Les équipes sont enthousiasmées après leur première extraction réussie et tentent de tout diviser en même temps. Soudainement, ils exécutent 12 services avec 12 pipelines de déploiement, 12 ensembles de journaux et 12 points de défaillance potentiels. La charge opérationnelle submerge l’équipe. Extrayez un service, exécutez-le en production pendant 4 à 6 semaines, tirez les leçons des défis opérationnels, puis extrayez le suivant.

Le monolithe distribué

Il s'agit du mode de défaillance le plus courant. Vous divisez votre application en 8 services, mais ils partagent tous la même base de données. Ils se déploient tous ensemble car les modifications apportées à un service nécessitent des modifications de schéma qui affectent les autres. Vous bénéficiez de toute la complexité opérationnelle des microservices sans aucun des avantages. Chaque service doit être entièrement propriétaire de ses données. Si deux services ont besoin des mêmes données, ils communiquent via des API ou des événements, et non via des tables partagées.

Pas de maillage de service ni d'observabilité

Exécuter des microservices sans traçage distribué, c'est comme conduire la nuit avec les phares éteints. Vous ne saurez pas qu’un service se dégrade jusqu’à ce que les utilisateurs se plaignent. Vous ne saurez pas quel service a provoqué une panne sans effectuer une recherche manuelle dans plusieurs flux de journaux. Avant d'extraire votre premier service, configurez le traçage distribué, la journalisation centralisée et les points de terminaison de vérification de l'état. Ce n’est pas une infrastructure facultative. C'est un préalable.

Comparaison des coûts : monolithe vs microservices

La différence de coût d’infrastructure entre ces architectures est importante et les équipes la sous-estiment systématiquement.

Catégorie de coûtMonolitheMicroservices
Calcul (serveurs/conteneurs)50 $ - 200 $/mois300 $ à 2 000 $/mois
Orchestration de conteneurs (K8s/ECS)0 $ (pas nécessaire)75 $ - 500 $/mois
Surveillance et observabilité0 $ à 50 $/mois100 $ à 1 000 $/mois
Bases de données (multiples ou simples)15 $ - 100 $/mois100 $ à 1 000 $/mois
Files d'attente de messages/bus d'événements0 $ (pas nécessaire)25 $ - 500 $/mois
Infrastructure mensuelle totale50 $ - 200 $500 $ - 5 000 $

Ces fourchettes reflètent les startups en phase intermédiaire et les entreprises en phase de croissance. Les déploiements à l'échelle de l'entreprise peuvent fonctionner à un niveau plus élevé aux deux extrémités.

Le coût de l'infrastructure est la partie visible. Le coût caché est le temps d’ingénierie. Une équipe exécutant des microservices consacre 20 à 30 % de sa capacité à des tâches opérationnelles : mise à jour des configurations Kubernetes, débogage de la communication interservices, gestion des migrations de bases de données sur plusieurs services et maintenance des pipelines CI/CD. C'est du temps d'ingénierie qui n'est pas consacré aux fonctionnalités qui intéressent vos utilisateurs.

Le juste milieu du « monolithe modulaire »

Il existe une troisième option ignorée par la plupart des articles sur l'architecture : le monolithe modulaire. Vous conservez une seule unité déployable mais appliquez des limites strictes aux modules à l’intérieur de celle-ci.

Chaque module possède ses propres tables de base de données (ou schéma). Les modules communiquent via des API internes bien définies, sans accéder aux tables de base de données des autres ni en appelant des fonctions privées. Le code est organisé de telle sorte que l'extraction d'un module dans un service autonome nécessite de modifier la couche de transport (des appels de fonction en cours vers HTTP/gRPC) sans réécrire la logique métier.

Le monolithe modulaire vous offre la plupart des avantages organisationnels des microservices (propriété claire, développement indépendant au sein des modules, limites imposées) sans le coût opérationnel. Vous déployez un artefact. Vous exécutez un serveur de base de données. Vous recherchez un flux de journaux.

L'architecture de Shopify en est l'exemple le plus connu. Ils exécutent une application Rails monolithique avec des limites de modules strictement appliquées. Lorsqu'un module doit devenir un service (en raison d'exigences d'évolutivité ou de besoins d'indépendance de l'équipe), l'extraction est simple car les limites sont déjà claires.

Pour les équipes de 5 à 30 ingénieurs, le monolithe modulaire est souvent la bonne réponse. Vous bénéficiez de la structure et de la discipline de la réflexion sur les microservices sans payer la taxe d’infrastructure et de fonctionnement.

Ce que Savi recommande

Nous avons construit des monolithes, des monolithes modulaires et des architectures de microservices pour des clients des secteurs de la fintech, du commerce électronique et du SaaS. Voici le playbook que nous suivons :

  • Commencez monolithique.Chaque nouveau produit commence comme un monolithe. La priorité est d’expédier les fonctionnalités, de valider le marché et d’itérer rapidement. La pureté architecturale n'a pas d'importance si personne n'utilise votre produit.
  • Appliquez les limites des modules dès le premier jour.Même dans un monolithe, chaque module doit posséder ses données et exposer une interface claire. Cela ne coûte presque rien au départ et évite des mois de refactorisation plus tard.
  • Configurez l’observabilité dès le début.Journalisation structurée, suivi des erreurs et surveillance de base des performances. Vous en avez besoin, que vous restiez monolithique ou migrez. C'est un enjeu de table.
  • Extrayez les services uniquement lorsque des douleurs spécifiques apparaissent.Conflits de déploiement bloquant les versions. Conflit de ressources entre les modules. Les frais généraux de coordination de l’équipe grugent la capacité d’ingénierie. Ce sont de vrais signaux et non des préoccupations théoriques.
  • Utilisez le modèle de figue étrangleur pour l’extraction.Un service à la fois. Exécutez-le à côté du monolithe. Validez que ça marche. Passez ensuite au suivant. Ne réécrivez jamais un Big Bang.
  • Considérez le monolithe modulaire comme votre architecture à long terme.Pour de nombreux produits, c'est le meilleur des deux mondes. Vous ne passez à de véritables microservices que lorsque la contrainte de déploiement unique du monolithe modulaire devient le goulot d'étranglement.

La meilleure architecture est celle qui permet à votre équipe de proposer les fonctionnalités souhaitées par vos clients. Pour la plupart des entreprises, à la plupart des étapes, il s'agit d'un monolithe bien structuré. Pour certaines entreprises, à certains points d'inflexion, il s'agit d'une extraction ciblée de services spécifiques. Pour très peu d’entreprises, il s’agit d’une architecture complète de microservices.

Ne choisissez pas votre architecture en fonction de ce qu'utilise Netflix ou Uber. Choisissez-le en fonction de la taille de votre équipe, de vos modèles de trafic, de votre fréquence de déploiement et des goulots d'étranglement spécifiques que vous rencontrez aujourd'hui. Pas les goulots d’étranglement que vous pourriez rencontrer dans deux ans.

Questions fréquemment posées

Quand dois-je migrer d’un monolithe vers des microservices ?

Migrez lorsque vous voyez deux ou plusieurs de ces signaux : déployez des conflits bloquent les versions deux fois par semaine, les équipes se succèdent dans des modules partagés, le bug d'un module fait planter l'ensemble de l'application ou la mise à l'échelle d'une fonctionnalité vous oblige à tout faire évoluer. Si vous avez moins de 20 ingénieurs, un monolithe est presque certainement le bon choix.

Combien coûtent les microservices par rapport à un monolithe ?

Un monolithe fonctionne avec 50 à 200 $/mois en infrastructure. Les microservices coûtent entre 500 $ et 5 000 $/mois lorsque vous ajoutez l'orchestration de conteneurs (75 $ à 500 $), plusieurs bases de données (100 $ à 1 000 $), des outils d'observabilité (100 $ à 1 000 $) et des files d'attente de messages (25 $ à 500 $). Les équipes consacrent également 20 à 30 % de leur capacité d'ingénierie à des tâches opérationnelles.

Quel est le modèle de figure étrangleur pour la migration des microservices ?

Le motif de figue étrangleur extrait un service à la fois de votre monolithe. Acheminez le trafic via une passerelle API, créez le nouveau service aux côtés du monolithe et déplacez progressivement le trafic. Si le nouveau service échoue, redirigez le trafic. Cela évite les réécritures Big Bang, qui échouent car la réécriture ne rattrape jamais 6 à 12 mois de nouvelles fonctionnalités monolithiques.

Qu'est-ce qu'un monolithe modulaire et dois-je en utiliser un ?

Un monolithe modulaire est une unité déployable unique avec des limites de modules internes strictes. Chaque module possède ses tables de base de données et communique via des API internes définies. Pour les équipes de 5 à 30 ingénieurs, il offre les avantages organisationnels des microservices (propriété claire, limites renforcées) sans les coûts d'infrastructure de 500 à 5 000 $/mois.

Que dois-je extraire en premier lors du passage aux microservices ?

Extrayez le composant qui change le plus souvent (vérifiez dans votre journal git le répertoire avec le plus de commits en 6 mois) ou le composant nécessitant une mise à l'échelle indépendante (comme un module de traitement vidéo utilisant 10 fois le processeur de votre API). Évitez d’extraire d’abord le composant le plus complexe. Votre première extraction est un exercice d’apprentissage.

Lectures connexes

Vous envisagez une migration ?

Nous avons déplacé les monolithes vers des microservices et construit des monolithes modulaires à partir de zéro. Appel de 30 minutes.

Parlez à notre équipe

Nous contacter

Demarrer une conversation

Parlez-nous de votre projet. Nous vous repondrons sous 24 heures avec un plan clair, un calendrier estime et une fourchette de prix.

Base a

EAU et Inde