- Après avoir exploité une architecture composée de centaines de microservices, Twilio Segment a basculé vers un service unique (monolithique) en raison de la complexité et de la charge de maintenance
- Au départ, l’entreprise avait séparé chaque API de destination afin d’assurer l’isolation des pannes et la scalabilité, mais le nombre de services a dépassé 140, ce qui a fait exploser l’overhead opérationnel
- La gestion de multiples repositories et bibliothèques partagées est devenue difficile, et les phases de test et de déploiement finissaient par affecter l’ensemble des services
- Pour résoudre ces problèmes, l’entreprise a introduit le système Centrifuge et une structure en monorepo, tout en créant Traffic Recorder pour automatiser les tests
- Résultat : la vitesse de développement et la stabilité se sont nettement améliorées, et Twilio Segment conserve aujourd’hui une architecture monolithique pour maximiser la productivité et l’efficacité opérationnelle
Adoption des microservices et limites
- Twilio Segment a adopté une architecture microservices pour son infrastructure de données client, en concevant des services indépendants capables de traiter les événements selon leur finalité
- Les données étaient envoyées vers des centaines de destinations côté serveur (par ex. Google Analytics, Optimizely, etc.)
- Au début, un unique queue était utilisé, mais une panne sur une destination spécifique provoquait des ralentissements globaux via un problème de head-of-line blocking
- Pour corriger cela, l’entreprise a mis en place un service et une queue distincts pour chaque destination, obtenant ainsi une meilleure isolation des pannes et une scalabilité indépendante
- Mais à mesure que le nombre de services augmentait, la complexité opérationnelle et le coût de maintenance ont fortement progressé, entraînant un ralentissement du développement et une hausse du taux de défauts
Les problèmes des repositories séparés et des bibliothèques partagées
- Chaque destination utilisait un format d’API différent, ce qui nécessitait du code de transformation personnalisé
- Initialement, tout était géré dans un repository unique, mais comme un échec de test affectait l’ensemble, l’équipe a choisi de séparer les repositories
- Avec l’ajout ultérieur de plus de 50 nouvelles destinations, cela a conduit à la création de plus de 50 repositories
- Des bibliothèques partagées ont été introduites pour les fonctions communes, mais les divergences de version et la charge liée aux déploiements se sont accrues
- Les profils de charge variant selon les services, il était difficile de régler l’autoscaling, ce qui obligeait parfois les opérateurs à intervenir manuellement
Passage au monolithique et adoption de Centrifuge
- L’entreprise a décidé de fusionner plus de 140 services en un seul
- Pour remplacer les queues individuelles, elle a développé le système Centrifuge, qui achemine tous les événements vers un service unique
- Centrifuge a ensuite évolué pour devenir l’infrastructure backend de Connections chez Twilio Segment
- Le passage à une architecture en service unique a permis de réduire la charge opérationnelle et de simplifier la gestion des incidents
Monorepo et automatisation des tests
- Tout le code des destinations a été fusionné dans un seul repository, et plus de 120 dépendances ont été unifiées sur une version unique
- La gestion des versions a été simplifiée et l’efficacité de maintenance améliorée
- Pour automatiser les tests, l’entreprise a introduit Traffic Recorder
- L’outil enregistre puis rejoue de vraies requêtes/réponses HTTP, supprimant la dépendance au réseau externe
- La durée des tests est passée de plusieurs minutes à quelques millisecondes, avec un net gain de stabilité
- Le taux d’échec des tests a diminué et la productivité des développeurs s’est fortement améliorée
Effets et compromis de l’architecture monolithique
- Après la fusion dans un service unique, la vitesse de déploiement et l’efficacité de développement se sont nettement améliorées
- En un an, le nombre d’améliorations apportées aux bibliothèques partagées est passé de 32 à 46
- Un seul ingénieur peut désormais déployer en quelques minutes
- L’efficacité opérationnelle s’est également améliorée : même en cas de forte hausse de charge, celle-ci peut être absorbée par un grand pool de workers
- Il reste toutefois des inconvénients, comme la difficulté d’isoler les défauts, la baisse de l’efficacité du cache et le risque lié aux mises à jour de dépendances
- Une partie de ces pertes est compensée par la simplicité opérationnelle et le gain de productivité
Conclusion
- Les microservices ont permis de résoudre les problèmes de performance initiaux, mais ils sont moins adaptés à la montée en charge à grande échelle et aux mises à jour groupées
- Le retour au monolithique a permis d’améliorer à la fois la stabilité opérationnelle et la vitesse de développement
- Pour réussir une telle transition, il est indispensable de disposer d’un système de test robuste et d’accepter les compromis associés
- Twilio Segment continue d’utiliser des microservices pour une partie de son infrastructure, mais considère que pour les destinations côté serveur, l’architecture monolithique est plus adaptée
2 commentaires
J’ai l’impression que tout découper et normaliser comporte aussi des risques.
Avis Hacker News
En rassemblant le code de toutes les destinations dans un seul repo, ils ont pu fusionner le tout en un service unique
Résultat : la productivité de développement s’est fortement améliorée. Il n’est plus nécessaire de déployer plus de 140 services à chaque modification d’une bibliothèque partagée
Un seul ingénieur peut désormais déployer en quelques minutes
Si un changement de bibliothèque impose de redéployer tous les services, alors ce ne sont pas de vrais services, mais un monolithe distribué
L’idée même de devoir synchroniser de force une bibliothèque partagée sur l’ensemble des services ne correspond pas à la philosophie d’une architecture orientée services
Ce n’est pas tant « un redéploiement global à chaque mise à jour de bibliothèque » qu’un système de build et de déploiement partagé à la Amazon
Les bibliothèques proviennent d’une source unique gérée centralement, et si les versions divergent, il faut tout migrer à cause des problèmes de compatibilité
Lorsqu’une faille de sécurité impose de retirer une version précise, un redéploiement global devient nécessaire, mais les avantages de cette gestion centralisée sont bien plus importants
Ce type de système reste classé comme microservices, tout en fonctionnant comme un environnement partagé du point de vue des coûts et de l’efficacité opérationnelle
Appeler ça un monolithe distribué me paraît exagéré
Quand on adopte le modèle microservices, le risque au déploiement augmente, même si cela ne se voit pas au début
Par exemple, si on corrige un bug dans une bibliothèque liée à l’argent, on finit concrètement par se demander s’il faut redéployer tous les services
Une bibliothèque vulnérable doit être remplacée partout, indépendamment de la conception du système
Dans ce genre de cas, une architecture monolithique est même plus simple à gérer
Dans de vrais microservices, on s’échange des messages et on utilise du JSON
Il devrait suffire de connaître l’API, pas le code. C’est ainsi que chacun peut déployer et faire évoluer son service indépendamment
Utiliser un module partagé n’est-il pas plus raisonnable ?
Dans ma précédente entreprise, tout tournait en microservices, et celle d’avant utilisait du serverless sur AWS
Dans les deux cas, la communication entre services était le principal problème. Il était difficile de synchroniser les contrats, et les déploiements étaient complexes
Au début, on avançait vite, puis avec le temps la complexité a explosé. On est entrés dans une culture du développement par peur, avec beaucoup trop de réunions
Mon entreprise actuelle est en monolithe, et c’est bien plus simple à gérer. Les types sont clairs, et le refactoring est facile
Il est fascinant de voir des agents IA construits sur notre propre plateforme s’améliorer eux-mêmes à l’intérieur de la base de code
Le seul inconvénient est le temps de build plus long, mais avec les progrès de la toolchain, j’attends des déploiements 10 fois plus rapides d’ici 2026
Ma conclusion, c’est que le monolithe nous a permis de croître et de monter en charge beaucoup plus vite
Dans un monolithe, la séparation des préoccupations finit toujours par se dégrader, et le couplage entre équipes devient très fort
La vraie vitesse et la vraie capacité à passer à l’échelle n’existent que lorsque les équipes sont séparées
Il a fallu 2 ans, 50 équipes et plus de 150 personnes pour passer de l’ORM aux DTO
Sans les microservices, ce type de transformation complexe aurait été impossible
À lire cet article, le cœur du problème ne semble pas être le choix technique microservices vs monolithe,
mais la qualité et la structure de l’organisation d’ingénierie
Le dépôt de code et la structure des tests reflètent exactement le niveau de l’organisation
S’il n’y a personne pour dire « ne faisons pas ça », la complexité explose
Il faut un leader ayant l’autorité nécessaire pour que l’équipe puisse s’arrêter et réfléchir
Quand un problème d’API survenait, personne n’analysait la cause ; on corrigeait juste les données puis on fermait le ticket
Même quand le même problème se répétait, la cause racine n’était pas traitée
Rien qu’en entretien, on peut déjà prédire en partie la structure du codebase d’une entreprise
Il ne s’agit pas vraiment d’un retour au monolithe, mais plutôt toujours d’une architecture SOA
C’est simplement que le périmètre du service est devenu plus large
Si une seule équipe gère 140 services, la SOA sert à faire grandir l’équipe, pas à faire grandir les services
Si une seule équipe gère toutes les bibliothèques partagées, on obtient des désalignements de versions et de la confusion autour des API
Au final, la structure de l’organisation détermine l’architecture. Une seule équipe a fusionné les éléments pour réduire la complexité
Ce n’est pas un « monolithe », mais un niveau de service redimensionné de manière appropriée à l’échelle de l’équipe
Je pense que ce type de structure est l’idéal. Quand l’équipe grandit, il faut à nouveau scinder
Je ne suis pas un partisan des microservices, mais la fausse dichotomie entre « monorepo vs microservices » saute aux yeux
Trop d’outils supposent une relation 1:1 entre service et repo
Pourtant, on peut tout mettre dans un seul repo tout en déployant indépendamment
J’aimerais voir des plateformes comme GitHub traiter des dossiers comme des services autonomes
Avec Bazel, nous gérions l’arbre de dépendances et utilisions
bazel querypour trouver les cibles impactées puis lancer automatiquement les testsNous avions créé un workflow intégré à GitHub Actions pour bloquer les PR
Cela fonctionnait bien, mais il a fallu plusieurs mois pour le mettre en place
Le vrai problème venait surtout du manque d’exploitation et d’outillage — CI, autoscaling, système d’astreinte : tout était insuffisant
Les deux approches peuvent échouer
Dans des environnements comme Node.js ou Python, il existe une limite à la quantité de code qu’une boucle d’événements peut absorber
J’ai déjà vu 6 à 8 personnes gérer 200 services, et 80 personnes gérer un seul monolithe
Les microservices sont pratiques pour les petits changements, mais compliquent les changements globaux,
et le monolithe produit l’effet inverse
Au final, ce qui compte, ce n’est pas l’architecture, mais l’abstraction, les tests et la manière de découpler
Le critère du “micro” n’est pas la technique, mais l’unité métier
En dessous de ce seuil, on tombe dans le nanoservice
Dans des environnements comme Beam, JVM, Rust ou Go, ce problème est déjà résolu
Est-ce un problème de cache CPU ?
Je pensais qu’on utilisait plutôt Go, Java ou C#
Dans la plupart des entreprises, les microservices étaient plutôt à l’origine de 90 % des problèmes
En dehors de très grandes organisations comme AWS, Google ou Netflix, ce n’est pas forcément adapté
Il est déjà difficile de découper un système en unités composables ; y ajouter des frontières réseau est une mauvaise idée
Je pense que la prochaine tendance sera de quitter React et les SPA pour un retour au serveur
Dire qu’ils sont passés aux microservices parce que « les tests cassaient souvent » ressemble à une approche complètement à l’envers
Réorganiser toute la structure du codebase parce que les tests cassent paraît étrange
En séparant les VM et la configuration CI/CD par équipe, les conflits de tests ont disparu
L’inconvénient, c’est qu’on ne détecte pas immédiatement les conflits entre fonctionnalités, mais comme la propriété du code était claire, cela ne posait pas de gros problème
Une demande a été faite pour ajouter [2018] au titre
Ils disent avoir séparé les repo parce que « quand les tests cassaient, il fallait aussi modifier du code non lié »,
mais il y avait probablement d’autres solutions possibles, comme changer la manière d’exécuter les tests ou autoriser les déploiements manuels
La séparation des repo n’était pas la seule réponse possible