Tous les quelques ans, l'industrie logicielle redécouvre une vérité ancienne : les décisions d'architecture ne sont pas définitives, et les modifier coûte cher. Le chapitre actuel de cette histoire récurrente est la migration du monolithe vers les microservices, un parcours qui a produit autant de succès que d'histoires d'avertissement.

Chez Globe Software Solutions, nous avons accompagné plusieurs clients dans cette transition, des jeunes pousses qui ont dépassé leur architecture initiale aux grandes entreprises avec des systèmes vieux de décennies. La leçon la plus importante : l'objectif n'est pas les microservices. L'objectif est une architecture système qui sert vos besoins actuels et à court terme. Parfois cela signifie des microservices. Parfois un monolithe bien structuré. Souvent quelque chose entre les deux.

Cadre de décision : faut-il vraiment migrer ?

Avant d'aborder comment migrer, il faut se demander si vous devez le faire. Les microservices résolvent des problèmes précis. Si vous n'avez pas ces problèmes, la migration créera de la complexité sans apporter de valeur.

Migrez si :

Restez sur le monolithe si :

« Si vous ne savez pas construire un monolithe bien structuré, vous ne savez pas construire des microservices. Les microservices ne corrigent pas une discipline d'ingénierie défaillante ; ils l'amplifient. »

Le pattern Strangler Fig : migrer sans big bang

Pour les organisations qui décident de migrer, nous recommandons presque systématiquement le pattern Strangler Fig, du nom du figuier tropical qui enveloppe et remplace progressivement l'arbre hôte. L'idée est simple : au lieu de réécrire le monolithe de zéro, vous extrayez progressivement les fonctionnalités vers de nouveaux services tandis que le monolithe continue de servir le trafic de production.

Phase 1 : poser les fondations

Avant d'extraire un seul service, mettez en place l'infrastructure requise par les microservices :

Ce travail de fond n'est pas glamour, mais le négliger est la cause la plus fréquente d'échec des migrations. Les équipes extraient quelques services, découvrent qu'elles ne peuvent pas déboguer les problèmes inter-services, et soit reviennent au monolithe soit restent indéfiniment dans un état hybride pénible.

Phase 2 : identifier le premier candidat à l'extraction

Le candidat idéal pour commencer est un module qui :

Bons candidats courants : systèmes de notification, modules de reporting, pipelines de traitement de fichiers, fonctionnalité de recherche. Mauvais candidats courants : l'authentification utilisateur (trop couplée) et la logique métier centrale (trop risquée pour un premier essai).

Phase 3 : créer la couture

Avant d'extraire le code, créez une interface propre dans le monolithe qui isole la fonctionnalité cible. Cette « couture » est une frontière API interne : toute communication avec le module cible passe par une interface définie, et non par des appels de fonction directs ou un accès base partagée.

Cette étape est cruciale et souvent ignorée. Si vous extrayez du code sans avoir d'abord établi une interface propre, vous découvrirez des dizaines de dépendances cachées — via la base de données, des caches mémoire partagés, des chemins de fichiers — qui rendront l'extraction bien plus complexe que prévu.

Phase 4 : extraire et faire tourner en parallèle

Avec la couture en place, construisez le nouveau service et routez le trafic vers lui, d'abord en mode shadow (réception sans servir le trafic de production), puis progressivement en déploiement canary. Gardez l'implémentation du monolithe comme repli. Ne désactivez la version du monolithe qu'après que le nouveau service ait fait ses preuves en production pendant une période significative — nous recommandons au moins quatre semaines.

Phase 5 : répéter et affiner

Chaque extraction vous apprend quelque chose sur les frontières de domaine, les capacités opérationnelles et la préparation de l'équipe. La deuxième extraction est toujours plus fluide que la première, et à la quatrième ou cinquième, cela devient une routine.

Le problème des données

La partie la plus difficile de toute migration monolithe vers microservices, ce sont les données. Les monolithes partagent typiquement une base unique, et démêler cet état partagé est là que se trouve la plus grande complexité.

Nous suivons une approche en trois étapes :

  1. Séparation logique d'abord. Avant de séparer physiquement les bases, imposez une séparation logique : le code de chaque domaine ne peut accéder qu'à ses propres tables, via sa propre couche d'accès aux données. Cela fait remonter les requêtes cross-domain cachées.
  2. Répliquer, ne pas migrer. Utilisez la capture des changements de données (CDC) pour répliquer les données du service extrait vers une nouvelle base, en gardant les deux synchronisées pendant la transition. Cela évite une migration de données unique et risquée.
  3. Accepter la cohérence à terme. Dans un monde microservices, certaines données qui étaient auparavant immédiatement cohérentes (car dans une seule base) deviendront à cohérence à terme. Identifiez où c'est important et mettez en œuvre les patterns adaptés : sagas pour les transactions distribuées, pattern outbox pour la publication d'événements fiable, transactions de compensation pour la gestion des échecs.

Anti-patterns que nous rencontrons souvent

Le monolithe distribué. Des services qui doivent être déployés ensemble, qui partagent une base, ou qui ne peuvent pas fonctionner sans appels synchrones à plusieurs autres services. Vous avez toute la complexité opérationnelle des microservices sans en avoir les bénéfices.

L'extraction prématurée. Extraire des services avant que les frontières de domaine soient claires, ce qui mène à des services bavards avec des dépendances circulaires qu'il faut ensuite fusionner à nouveau.

Ignorer le réseau. Dans un monolithe, les appels de fonction sont rapides et fiables. Dans les microservices, chaque appel traverse une frontière réseau qui peut échouer, être lente ou renvoyer des résultats inattendus. Les services doivent être conçus pour l'échec réseau dès le départ : retries, circuit breakers, timeouts et dégradation gracieuse.

Sous-investir dans l'observabilité. Dans un monolithe, vous pouvez souvent comprendre le parcours d'une requête en lisant une stack trace. Dans les microservices, une seule requête utilisateur peut toucher quinze services. Sans tracing distribué, le débogage devient du tâtonnement.

Un calendrier réaliste

Les clients demandent souvent combien de temps dure une migration. La réponse honnête dépend de la taille et de la complexité du monolithe, mais voici un ordre de grandeur :

L'idée clé : c'est un marathon, pas un sprint. Prévoyez une livraison incrémentale de valeur à chaque étape plutôt qu'une date de fin big bang lointaine.

Vous envisagez une migration du monolithe vers les microservices ? Nous pouvons vous aider à évaluer si c'est la bonne décision et accompagner la transition avec un minimum de perturbation. Commençons par en discuter.