En Hibot Chat migramos más de 8 microservicios legacy de Java (Spring Boot) a Go con arquitectura limpia. Éramos tres desarrolladores, tardamos cuatro meses y en ningún momento apagamos el servicio: Java y Go convivieron en producción hasta el último endpoint.
Por qué endpoint por endpoint
Migrar un servicio completo de una vez obliga a validar todo su comportamiento en un solo salto. Migrar endpoint por endpoint reduce cada cambio a una superficie pequeña: un contrato de entrada, un contrato de salida y la lógica entre ambos. Si algo fallaba, el alcance del problema era un endpoint, no un servicio entero.
- Entender la implementación en Java: qué validaba, qué casos borde cubría y qué esperaban sus consumidores.
- Reescribirla en Go con arquitectura limpia, respetando exactamente el mismo contrato.
- Ponerla en producción mientras el resto del servicio seguía en Java.
- Medir y pasar al siguiente endpoint.
Lo difícil no fue escribir Go
La parte más costosa fue el análisis: entender cómo funcionaba el código existente para migrar la lógica tal cual, sin romper nada. Una migración no es el momento de corregir reglas de negocio de las que dependen otros sistemas; cualquier cambio de comportamiento, por bien intencionado que sea, es un bug para quien consume la API.
Cómo medimos la mejora
Comparamos la latencia media de las APIs críticas antes y después de migrarlas, con las métricas que ya teníamos en Prometheus y Grafana. El resultado fue una reducción de alrededor del 35 %: de 800 ms a 520 ms en promedio.
Lecciones
- Migrar por endpoint convierte una reescritura grande en muchos cambios pequeños y reversibles.
- El análisis del código existente es la mayor parte del trabajo; escribir el código nuevo es lo rápido.
- «Tal cual» es un requisito, no una sugerencia: la migración y los cambios de negocio van por separado.
- Sin una línea base medida antes de empezar, no hay forma de demostrar la mejora.