5 puntos por GN⁺ 2025-12-14 | 2 comentarios | Compartir por WhatsApp
  • Twilio Segment operó una arquitectura de microservicios con cientos de servicios, pero cambió a un servicio único (monolítico) debido a la complejidad y a la carga de mantenimiento
  • Al principio separó cada API de destino para lograr aislamiento de fallas y escalabilidad, pero al superar los 140 servicios, el overhead operativo se disparó
  • La gestión de múltiples repositorios y bibliotecas compartidas se volvió difícil, y durante las pruebas y los despliegues surgían problemas que afectaban al conjunto de los servicios
  • Para resolverlo, introdujo el sistema Centrifuge y una estructura de monorepo, y creó Traffic Recorder para automatizar las pruebas
  • Como resultado, la velocidad de desarrollo y la estabilidad mejoraron considerablemente, y Twilio Segment mantiene la estructura monolítica por productividad y eficiencia operativa

Adopción de microservicios y sus límites

  • Twilio Segment adoptó una arquitectura de microservicios para su infraestructura de datos de clientes, diseñada para que cada servicio orientado a un propósito procesara eventos de forma independiente
    • Enviaba datos a cientos de destinos del lado del servidor (por ejemplo, Google Analytics, Optimizely, etc.)
    • Al principio usaba una sola cola, pero cuando un destino fallaba se producía head-of-line blocking, lo que generaba retrasos generales
  • Para resolverlo, configuró un servicio y una cola separados para cada destino, logrando aislamiento de fallas y escalado independiente
  • Sin embargo, a medida que aumentó el número de servicios, la complejidad operativa y el costo de mantenimiento crecieron con rapidez, lo que derivó en menor velocidad de desarrollo y mayor tasa de defectos

Problemas de los repositorios individuales y las bibliotecas compartidas

  • Cada destino usaba un formato de API distinto, por lo que hacía falta código de transformación personalizado
    • Al principio se gestionaba en un solo repositorio, pero como los fallos en pruebas afectaban a todo, se optó por la separación de repositorios
  • Después, al agregarse más de 50 destinos nuevos, surgieron más de 50 repositorios
    • Se introdujeron bibliotecas compartidas para funciones comunes, pero crecieron los problemas de versiones inconsistentes y la carga de despliegue
  • Como los patrones de carga variaban entre servicios, era difícil configurar el autoescalado, y en algunos casos los operadores tenían que ajustarlo manualmente

Transición al monolito e introducción de Centrifuge

  • Se decidió integrar más de 140 servicios en un solo servicio
    • Para reemplazar las colas individuales, se desarrolló el sistema Centrifuge, que envía todos los eventos a un único servicio
    • Más adelante, Centrifuge evolucionó hasta convertirse en la infraestructura backend de Connections de Twilio Segment
  • Con la transición a una estructura de servicio único se logró reducir la carga operativa y simplificar la respuesta ante fallas

Monorepo y automatización de pruebas

  • Todo el código de destinos se fusionó en un solo repositorio, unificando en una sola versión más de 120 dependencias
    • Se simplificó la gestión de versiones y mejoró la eficiencia del mantenimiento
  • Para automatizar las pruebas se introdujo Traffic Recorder
    • Registra y reproduce solicitudes y respuestas HTTP reales para eliminar la dependencia de redes externas
    • La velocidad de las pruebas pasó de varios minutos a milisegundos, con una mejora importante en estabilidad
  • Disminuyó la tasa de fallos en pruebas y mejoró notablemente la productividad de los desarrolladores

Efectos y trade-offs de la estructura monolítica

  • Tras integrar todo en un solo servicio, la velocidad de despliegue y la eficiencia de desarrollo mejoraron mucho
    • En un año, la cantidad de mejoras en bibliotecas compartidas aumentó de 32 a 46
    • Un solo ingeniero puede desplegar en cuestión de minutos
  • También mejoró la eficiencia operativa, ya que incluso ante aumentos bruscos de carga puede absorberse con un gran pool de workers
  • Sin embargo, existen desventajas como la dificultad para aislar fallas, la menor eficiencia de caché y el riesgo al actualizar dependencias
    • Parte de esas pérdidas se compensa con la simplicidad operativa y la mejora de productividad

Conclusión

  • Los microservicios resolvieron problemas iniciales de rendimiento, pero no eran adecuados para la expansión a gran escala y las actualizaciones masivas
  • La transición a un monolito mejoró tanto la estabilidad operativa como la velocidad de desarrollo
  • Para que la transición sea exitosa, son indispensables un sistema de pruebas sólido y la aceptación de los trade-offs
  • Aunque Twilio Segment todavía mantiene microservicios en parte de su infraestructura, considera que para los destinos del lado del servidor el monolito es una estructura más adecuada

2 comentarios

 
yangeok 2025-12-16

Creo que fragmentarlo y normalizarlo todo conlleva cierto riesgo.

 
GN⁺ 2025-12-14
Comentarios en Hacker News
  • Al reunir el código de todos los destinos en un solo repo, pudieron fusionarlo en un único servicio
    Como resultado, la productividad de desarrollo mejoró mucho. Ahora ya no hace falta desplegar más de 140 servicios cada vez que se modifica una librería compartida
    Un solo ingeniero puede desplegar en cuestión de minutos
    Si hay que volver a desplegar todos los servicios por un cambio en una librería, entonces no se trata de servicios reales, sino de un monolito distribuido
    La idea misma de tener que sincronizar a la fuerza una librería compartida en todos los servicios no encaja con la filosofía de una arquitectura de servicios

    • Lo que dices tiene sentido, pero en la práctica es una situación mucho más compleja
      Esto se parece más a un sistema compartido de build y despliegue al estilo Amazon que a “volver a desplegar todo con cada actualización de librería”
      Se toman librerías de una única fuente centralizada, y si las versiones difieren, todos tienen que migrar por problemas de compatibilidad
      Cuando hay que retirar una versión específica por una vulnerabilidad de seguridad, sí hace falta volver a desplegar todo, pero los beneficios de la gestión centralizada son mucho mayores
      Este tipo de sistema sigue clasificándose como microservicios, pero en costos y eficiencia operativa funciona como un entorno compartido
      Llamarlo monolito distribuido es una interpretación exagerada
    • Es fácil decirlo, pero en la práctica es muy fácil provocar bugs sutiles o incompatibilidades entre servicios
      Cuando sigues el patrón de microservicios, el riesgo de despliegue aumenta, aunque al principio no se note
      Por ejemplo, si corriges un bug en una librería relacionada con dinero, en la realidad terminas preguntándote si no deberías volver a desplegar todos los servicios
    • Que haya que actualizar una librería en todo el sistema no significa necesariamente que exista un acoplamiento incorrecto
      Una librería con una vulnerabilidad de seguridad debe reemplazarse por completo sin importar el diseño del sistema
      En casos así, una arquitectura monolítica incluso puede ser más fácil de manejar
    • El concepto mismo de librería compartida hace que todos los servicios queden fuertemente acoplados
      Si fueran microservicios de verdad, deberían intercambiar mensajes y usar JSON
      Bastaría con conocer la API, no el código. Solo así se pueden desplegar y escalar de forma independiente
    • ¿Entonces estás diciendo que habría que volver a escribir el código de logging en cada uno de los 140 servicios?
      ¿No tiene más sentido usar módulos compartidos?
  • En mi empresa anterior, todo corría como microservicios, y en la de antes de esa usábamos AWS serverless
    En ambos casos, la comunicación entre servicios era el mayor problema. Era difícil sincronizar los contratos, y los despliegues también eran complejos
    Al principio nos movíamos rápido, pero con el tiempo la complejidad explotó. Surgió el desarrollo basado en el miedo y había demasiadas reuniones
    Mi empresa actual usa una arquitectura monolítica y es mucho más fácil de manejar. Los tipos son claros y el refactoring es sencillo
    Es interesante ver agentes de IA construidos sobre nuestra propia plataforma mejorándose solos dentro del codebase
    La única desventaja es el tiempo de build, pero con las mejoras en la toolchain esperamos despliegues 10 veces más rápidos para 2026
    Mi conclusión es que, gracias a la arquitectura monolítica, pudimos crecer y escalar mucho más rápido

    • Mi experiencia es exactamente la contraria. Trabajé 10 años en SendGrid, escalando de 12 a 500 personas, y eso fue posible gracias a una arquitectura de servicios
      En una arquitectura monolítica siempre se rompía la separación de responsabilidades y había mucho acoplamiento entre equipos
      La verdadera velocidad y la escalabilidad solo fueron posibles cuando los equipos estaban separados
      Para pasar de ORM a DTO se necesitaron 2 años, 50 equipos y más de 150 personas
      Un trabajo complejo así habría sido imposible sin microservicios
  • Al leer este texto, parece que el verdadero núcleo del problema no es la elección técnica entre microservicios vs. monolito,
    sino la calidad y estructura de la organización de ingeniería
    El repositorio de código y la estructura de pruebas reflejan exactamente el nivel de la organización

    • A muchos equipos les falta disciplina técnica
      Si no hay nadie capaz de decir “eso no lo hagamos”, la complejidad explota
      Tiene que existir un líder con autoridad para que el equipo pueda detenerse y pensar
    • Trabajé en el proyecto de Twilio y de verdad era un desastre
      Cuando había problemas de API, no analizaban la causa raíz; solo corregían los datos y cerraban el ticket
      Aunque el mismo problema se repitiera, nunca resolvían la causa fundamental
    • La ley de Conway vuelve a demostrarse una vez más
      Incluso con solo hacer entrevistas, puedes predecir hasta cierto punto la estructura del codebase de una empresa
  • Esto no parece realmente una transición a monolito, sino que sigue siendo una arquitectura SOA
    Solo aumentó el alcance de los servicios
    Si un solo equipo administra 140 servicios, entonces SOA es una estructura para escalar equipos, no para escalar servicios
    Cuando un solo equipo administra todas las librerías compartidas, aparecen desajustes de versiones y confusión en las APIs
    Al final, la estructura organizacional determina la arquitectura. Un solo equipo integró todo para reducir la complejidad
    Esto no es “monolítico”, sino un nivel de servicio ajustado adecuadamente al tamaño del equipo
    Me parece que esta estructura es la más ideal. Si el equipo crece, entonces habría que volver a separarlo

  • No soy un defensor de los microservicios, pero me llama la atención la falsa dicotomía entre “monorepo vs. microservicios”
    Demasiadas herramientas asumen una relación 1:1 entre servicio y repo
    Pero puedes tener todo en un solo repo y aun así desplegar de forma independiente
    Sería bueno que en lugares como GitHub se pudiera tratar cada carpeta como un servicio independiente

    • En mi empresa anterior implementamos eso nosotros mismos
      Gestionábamos el árbol de dependencias con Bazel y usábamos bazel query para encontrar los targets afectados y ejecutar pruebas automáticamente
      También armamos un workflow conectado con GitHub Actions para bloquear PRs
      Funcionó bien, pero llevó varios meses construirlo
    • Me molesta la frase “pasamos de microservicios a monolito y desaparecieron los problemas”
      El problema real era la falta de operación y herramientas — CI, autoescalado y sistema de guardias, todo era insuficiente
  • Ambos enfoques pueden fracasar
    En entornos como Node.js o Python, hay un límite en la cantidad de código que el event loop puede manejar
    He visto a 6~8 personas administrar 200 servicios, y también a 80 personas administrar un solo monolito
    Los microservicios son convenientes para cambios pequeños, pero dificultan los cambios globales,
    mientras que el monolito es lo contrario
    Al final, lo importante no es la arquitectura, sino la abstracción, las pruebas y la forma de desacoplar

    • “Si es software que resuelve un solo problema de negocio, entonces corresponde agruparlo en un solo microservicio
      El criterio de “micro” no es técnico, sino una unidad de negocio
      Si lo divides más allá de eso, se convierte en nanoservicios
    • Este tipo de racionalización al final se siente como un parche temporal para tapar las limitaciones del runtime
      En entornos como Beam, JVM, Rust o Go, es un problema ya resuelto
    • Me da curiosidad cuál sería exactamente la unidad del límite de código que puede manejar un event loop
      ¿Es un problema de caché de CPU?
    • Me pregunto si realmente usan Node.js o Python en entornos de gran escala
      Yo pensaba que normalmente se usaba Go, Java o C#
  • En la mayoría de las empresas, los microservicios fueron más bien la causa del 90% de los problemas
    A menos que seas una organización gigante como AWS, Google o Netflix, no parecen encajar
    Ya es difícil dividir un sistema en unidades componibles, así que agregar además fronteras de red es una tontería
    Creo que la próxima tendencia será alejarse de React o las SPA y volver a un enfoque centrado en el servidor

  • Que se hayan pasado a microservicios porque “las pruebas se rompían seguido” suena como un enfoque demasiado al revés
    Es raro cambiar por completo la estructura del codebase solo porque las pruebas fallen

    • Nosotros tuvimos un problema parecido, pero lo resolvimos dando a cada equipo un entorno de desarrollo independiente
      Al separar por equipo las VMs y la configuración de CI/CD, desaparecieron los conflictos en las pruebas
      La desventaja es que no detectas de inmediato los choques entre funcionalidades, pero como la propiedad del código estaba clara, no fue un gran problema
  • Hubo una petición para agregar [2018] al título

    • Me pregunto si ahora habrán vuelto otra vez a microservicios
    • Me parece medio raro volver a subir un texto de hace 7 años. En el mundo de la tecnología ya es prácticamente historia antigua
  • Dicen que separaron el repo porque “si una prueba fallaba, había que modificar incluso código no relacionado”,
    pero parece que también pudo haber habido otras soluciones, como cambiar la forma de ejecutar las pruebas o permitir despliegues manuales
    Separar el repo no era la única solución