SystimaNX
Tous les articles
ArchitectureMicroservicesDevOps

Étrangler un monolithe : décomposition sans bloquer la livraison

Routage en façade, contextes bornés et extraction incrémentale—des étapes concrètes pour décoller des capacités du monolithe.

S
SystimaNX
9 avril 202612 min de lecture
Étrangler un monolithe : décomposition sans bloquer la livraison

Les réécritures big-bang finissent rarement. Le motif « strangler fig » garde le monolithe en ligne pendant que de nouvelles capacités poussent en périphérie, routées par une façade fine (API gateway, reverse proxy ou routeur de fonctionnalités) qui envoie le trafic vers l’ancien ou le nouveau.

Commencez par une couture déjà isolée logiquement—reporting, notifications, tarification—même si le code vit encore dans un seul dépôt. Extrayez derrière une interface que le monolithe appelle en synchrone, puis basculez vers HTTP ou des événements asynchrones une fois le service stable.

Les données sont le point dur. Préférez les réplicas en lecture et la capture de changements pour les lectures lourdes ; pour les écritures, anticipez transactions de compensation et clés d’idempotence. Les phases de double écriture sont risquées—gardez-les courtes et instrumentées.

Gardez un rythme de déploiement : chaque extraction doit être livrable derrière des drapeaux. Lancez en obscurité les nouveaux chemins, comparez latence et budgets d’erreur, puis augmentez progressivement le pourcentage de trafic.

La topologie des équipes suit : une équipe slice verticale possède le service extrait de bout en bout pendant que l’équipe monolithe maintient les adaptateurs de compatibilité jusqu’au basculement. Standards de code et observabilité partagés réduisent les surprises d’intégration.

Sachez arrêter d’étrangler : tout module ne mérite pas un service. Parfois des frontières de monolithe modulaire et une propriété claire suffisent jusqu’à ce que la charge ou l’échelle organisationnelle impose une séparation plus fine.

Un exemple concret : extraire les notifications en premier

Les notifications sont un premier candidat classique, et pour de bonnes raisons : c'est généralement du fire-and-forget, il y a peu d'appelants, et un bug dégrade en douceur—un email manqué est gênant, un paiement manqué est une urgence business. Nous commençons typiquement par encapsuler le code de notification existant derrière une interface à l'intérieur même du monolithe, avant même qu'un service n'existe, pour que chaque point d'appel passe par une seule couture. Ce refactoring seul, sans nouvelle infrastructure, prend souvent une semaine et fait remonter tous les appelants cachés que personne ne se rappelait—un job batch, un script d'admin, un webhook qui appelait tous le mailer directement.

Une fois la couture propre, montez le nouveau service et faites router par la façade un seul chemin d'appel à faible risque—les emails de réinitialisation de mot de passe, disons, plutôt que la newsletter marketing. Faites tourner les deux implémentations en parallèle pendant deux semaines, en comparant les logs de livraison, avant de basculer quoi que ce soit de plus critique. La tentation est de déclarer victoire après le premier cutover réussi et de précipiter tous les autres points d'appel en un sprint ; résistez. Chaque point d'appel a une sémantique de retry légèrement différente, et ceux que vous migrez en dernier le sont pour une raison—ce sont généralement ceux que personne ne comprend encore complètement.

Surveillez les budgets de latence de près pendant cette phase. Un appel synchrone qui était auparavant un appel de fonction in-process devient un saut réseau, et si le monolithe était déjà proche de son propre SLO de latence, ajouter 5 à 15 ms de surcoût gRPC ou HTTP par notification peut faire basculer un parcours de paiement hors budget si les notifications se trouvaient, par accident, sur le chemin critique. C'est souvent le moment où l'équipe découvre qu'un appel de notification bloquait une réponse qu'il n'avait aucune raison de bloquer, et l'extraction force une correction qui aurait dû être faite des années plus tôt.

Les pièges qu'on revoit sans cesse

L'erreur la plus coûteuse est d'extraire un service autour d'une table de base de données plutôt qu'autour d'une capacité métier. Les équipes regardent le schéma du monolithe, voient une table `orders` bien nommée, et supposent que c'est la couture. Mais la logique de tarification, les vérifications de stock et les déclencheurs de fulfillment qui touchent tous cette table appartiennent souvent à des bounded contexts entièrement différents. Extraire selon les lignes de tables plutôt que selon les lignes de capacités déplace juste le couplage d'appels de fonction in-process vers une transaction distribuée sur le réseau—strictement pire, puisque c'est maintenant une transaction distribuée sans aucun des outils pour la raisonner.

Deuxième piège : les fenêtres de double écriture qu'on laisse ouvertes indéfiniment parce que « ça marche très bien comme ça ». Chaque semaine où un chemin de double écriture reste actif est une semaine où une panne partielle peut faire diverger silencieusement les deux stores de données, et personne ne s'en aperçoit jusqu'à ce qu'un client signale que le total de sa commande ne correspond pas à ce que voit le support. Fixez une date d'expiration ferme à toute phase de double écriture avant de la démarrer, avec un propriétaire responsable soit de terminer le basculement, soit d'étendre explicitement la date par écrit—une double écriture sans fin est une dette technique qui s'accumule d'une façon réellement difficile à détecter uniquement à partir des dashboards.

Troisième piège : traiter la façade comme une décision de routage ponctuelle plutôt que comme une pièce d'infrastructure durable. La façade elle-même a besoin de la même rigueur que n'importe quel autre service en production—ses propres SLO, sa propre astreinte, sa propre planification de capacité. Nous avons vu des migrations en strangler fig s'enliser pendant des mois parce que la façade devenait le nouveau point unique de défaillance et que personne n'avait budgété le temps de la durcir, puisque sur le papier ce n'était « que du routage ».

Autre piège lié : croire que l'extraction est terminée une fois le trafic entièrement basculé. L'ancien chemin de code dans le monolithe doit être supprimé, pas commenté ou laissé derrière un flag définitivement désactivé. Nous avons vu du code de repli « temporaire » survivre deux ans parce que le supprimer semblait risqué et que personne ne possédait le ticket de nettoyage. Planifiez la suppression comme faisant partie du plan d'extraction lui-même, avec la même priorité que le cutover, et traitez un chemin de code mort qui traîne comme un constat ouvert lors de la prochaine revue d'architecture plutôt que comme une curiosité.

Le coût mérite aussi un suivi explicite pendant cette phase. Un service fraîchement extrait est souvent sur-provisionné par prudence—deux réplicas deviennent quatre, une petite base devient plus grosse par précaution. C'est une couverture raisonnable à court terme, mais elle doit être révisée avec de vraies métriques de production au bout d'un mois, pas laissée comme une taxe permanente sur la migration. Les équipes qui sautent cette étape sont souvent surprises, six mois plus tard, de constater que le service soi-disant plus simple coûte plus cher à faire tourner que la tranche du monolithe qu'il a remplacée.

Enfin, mettez-vous d'accord à l'avance sur ce qui justifierait d'arrêter carrément une migration, pas seulement sur la façon de mener la prochaine extraction. Si une tranche se révèle plus enchevêtrée que prévu—transactions partagées sur trois tables, job de reporting avec une dépendance dure à un état in-process—il est moins coûteux de refermer proprement la couture dans le monolithe que de forcer le passage avec un service qui demandera des pompiers en continu. Traiter une extraction stoppée comme une décision de rollback plutôt que comme un échec personnel garde tout le programme crédible la prochaine fois que vous proposez d'extraire autre chose.

Les équipes qui réussissent bien cet exercice partagent souvent une habitude : elles racontent la migration publiquement, dans un changelog visible par toute l'organisation d'ingénierie, pas seulement par l'équipe qui fait l'extraction. Une courte note hebdomadaire—ce qui a bougé, quel pourcentage de trafic a basculé, ce qui a cassé et comment ça a été détecté—transforme un effort de plusieurs trimestres en quelque chose que le reste de l'entreprise peut suivre et en qui elle peut avoir confiance, plutôt qu'une boîte noire qui cause de temps en temps un incident inexpliqué.

À lire aussi : conseil DevOps, études de cas et ressources.

Un exemple concret : extraire d'abord les notifications

Les notifications sont souvent le premier module extrait, et pour de bonnes raisons : c'est généralement du fire-and-forget, avec peu d'appelants, et un bug s'y dégrade en douceur — un e-mail manqué est fâcheux, un paiement manqué est une urgence métier. Nous commençons typiquement par envelopper le code de notification existant dans une interface à l'intérieur du monolithe, avant même qu'un quelconque service n'existe, afin que chaque point d'appel passe par une seule couture. Ce seul refactoring, sans nouvelle infrastructure, prend souvent une semaine et révèle chaque appelant caché que personne ne se rappelait — un job batch, un script d'admin, un gestionnaire de webhook qui appelaient tous directement le mailer.

Une fois la couture propre, nous montons le nouveau service et faisons router par la façade un unique chemin d'appel à faible risque — les e-mails de réinitialisation de mot de passe, par exemple, plutôt que la newsletter marketing. Nous faisons tourner les deux implémentations en parallèle pendant deux semaines, en comparant les journaux de livraison, avant de basculer quoi que ce soit de plus sensible. La tentation est de déclarer victoire après le premier basculement réussi et de précipiter tous les autres points d'appel en un seul sprint ; il faut y résister. Chaque point d'appel a une sémantique de retry légèrement différente, et ceux migrés en dernier le sont pour une raison — ce sont généralement ceux que personne ne comprend encore complètement.

Surveillez de près les budgets de latence pendant cette phase. Un appel synchrone qui était auparavant un appel de fonction en mémoire devient désormais un saut réseau, et si le monolithe était déjà proche de son propre SLO de latence, ajouter 5 à 15 ms de surcharge gRPC ou HTTP par notification peut faire basculer un parcours de commande hors budget si les notifications se trouvaient par accident sur le chemin critique. C'est souvent le moment où les équipes découvrent qu'un appel de notification bloquait une réponse qu'il n'avait aucune raison de bloquer, et l'extraction force une correction qui aurait dû intervenir des années plus tôt.

Pièges fréquents que nous observons régulièrement

L'erreur la plus coûteuse est d'extraire un service autour d'une table de base de données plutôt qu'autour d'une capacité métier. Les équipes regardent le schéma d'un monolithe, voient une table `orders` proprement nommée, et supposent que c'est la couture. Mais la logique tarifaire, les vérifications de stock et les déclencheurs d'exécution qui touchent tous cette table appartiennent souvent à des contextes bornés entièrement différents. Extraire selon les lignes de table plutôt que les lignes de capacité déplace simplement le couplage d'appels de fonction en mémoire vers une transaction distribuée sur un réseau — strictement pire, car c'est désormais une transaction distribuée sans aucun des outils pour la raisonner.

Deuxièmement : les fenêtres de double écriture laissées ouvertes indéfiniment parce que « ça fonctionne bien ». Chaque semaine où un chemin de double écriture reste actif est une semaine où une panne partielle peut faire diverger silencieusement les deux magasins de données, et personne ne le remarque jusqu'à ce qu'un client se plaigne que le total de sa commande ne correspond pas à ce que voit le support. Fixez une date d'expiration ferme à toute phase de double écriture avant de la démarrer, avec un responsable redevable soit de finaliser le basculement, soit de prolonger explicitement la date par écrit — une double écriture sans fin est une dette technique qui se compose d'une manière réellement difficile à détecter depuis de simples tableaux de bord.

Troisièmement : traiter la façade comme une décision de routage ponctuelle plutôt que comme un composant d'infrastructure durable. La façade elle-même a besoin de la même rigueur que tout autre service en production — ses propres SLO, sa propre rotation d'astreinte, sa propre planification de capacité. Nous avons vu des migrations en strangler fig s'enliser pendant des mois parce que la façade était devenue le nouveau point de défaillance unique et que personne n'avait budgété le temps de la durcir, car sur le papier elle n'était « que du routage ».

Un piège connexe : supposer que l'extraction est terminée une fois le trafic entièrement basculé. L'ancien chemin de code dans le monolithe doit être supprimé, pas simplement commenté ou laissé derrière un flag définitivement désactivé. Nous avons vu du code de repli « temporaire » survivre deux ans parce que le supprimer semblait risqué et que personne ne possédait le ticket de nettoyage. Planifiez la suppression comme partie intégrante du plan d'extraction lui-même, avec la même priorité que le basculement, et traitez un chemin de code mort persistant comme un constat ouvert lors de la prochaine revue d'architecture plutôt que comme une curiosité.

Le coût mérite aussi d'être suivi explicitement pendant cette phase. Un service nouvellement extrait est souvent surprovisionné par prudence — deux répliques deviennent quatre, une petite base de données devient plus grande par précaution. C'est une couverture à court terme raisonnable, mais elle doit être révisée avec de vraies métriques de production sous un mois, pas laissée comme une taxe permanente sur la migration. Les équipes qui sautent cette étape sont souvent surprises, six mois plus tard, de découvrir pourquoi le service extrait plus simple coûte plus cher à faire fonctionner que la tranche de monolithe qu'il a remplacée.

Questions fréquentes

Prêt à transformer votre infrastructure ?

Discutons de la façon dont nous pouvons vous aider à mettre en œuvre ces stratégies dans votre organisation.

Réserver une consultation
Étrangler un monolithe : décomposition sans bloquer la livraison | SystimaNX Blog