5 points par GN⁺ 2025-12-14 | 2 commentaires | Partager sur WhatsApp
  • 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

 
yangeok 2025-12-16

J’ai l’impression que tout découper et normaliser comporte aussi des risques.

 
GN⁺ 2025-12-14
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 que tu dis se tient, mais en pratique la situation est bien plus complexe
      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é
    • C’est facile à dire, mais en pratique cela crée facilement des bugs subtils ou des incompatibilités entre services
      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
    • Le fait de devoir mettre à niveau une bibliothèque partout ne signifie pas forcément un mauvais couplage
      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
    • Le concept même de bibliothèque partagée couple fortement tous les services
      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
    • Donc il faudrait réécrire le code de logging dans chacun des 140 services ?
      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

    • Mon expérience est exactement l’inverse. J’ai travaillé 10 ans chez SendGrid, où nous sommes passés de 12 à 500 personnes, et cela a été possible grâce à une architecture orientée services
      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

    • Beaucoup d’équipes manquent de discipline technique
      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
    • J’ai travaillé sur le projet Twilio, et c’était vraiment le chaos
      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
    • La loi de Conway se vérifie une fois de plus
      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

    • Dans une entreprise précédente, nous avons implémenté cela nous-mêmes
      Avec Bazel, nous gérions l’arbre de dépendances et utilisions bazel query pour trouver les cibles impactées puis lancer automatiquement les tests
      Nous 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
    • L’idée que « passer des microservices au monolithe a fait disparaître les problèmes » me dérange
      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

    • « Si un logiciel résout un seul problème métier, alors il est logique de le regrouper en un seul microservice »
      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
    • Ce genre de rationalisation me donne finalement l’impression d’un palliatif pour masquer les limites du runtime
      Dans des environnements comme Beam, JVM, Rust ou Go, ce problème est déjà résolu
    • Je me demande à quoi correspond concrètement cette limite de quantité de code qu’une boucle d’événements peut absorber
      Est-ce un problème de cache CPU ?
    • Je me demande vraiment si, à grande échelle, on utilise encore Node.js ou Python
      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

    • Nous avons connu un problème similaire, mais nous l’avons résolu en donnant à chaque équipe un environnement de développement indépendant
      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

    • Je me demande s’ils sont depuis revenus aux microservices
    • Je trouve un peu dommage de remonter un article vieux de 7 ans. Dans le monde de la tech, c’est déjà de l’histoire ancienne
  • 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