Caso de estudio · Fincaraiz.com.co · 2019 a 2022
De monolito a microservicios, sin detener una plataforma de 5 millones de visitas.
Como CTO de Fincaraiz.com.co, uno de los principales portales inmobiliarios de Colombia, lideré la migración de un monolito ASP.NET heredado a microservicios con Django y React sobre Kubernetes. Migramos en cuatro niveles detrás de un API Gateway con Kong, mantuvimos sincronizados los datos viejos y nuevos con AWS Lambda y reconstruimos la búsqueda para que entendiera cómo la gente realmente nombra los lugares. La plataforma nunca se cayó, siguió igual de rápida y los costos de hosting y mantenimiento bajaron 50%.
La situación
Fincaraiz.com.co es uno de los principales portales inmobiliarios de Colombia, parte del grupo Adevinta en ese momento. Más de 5 millones de personas lo visitaban cada mes para buscar lotes, apartamentos, casas y locales comerciales, y los agentes publicaban y actualizaban inmuebles todos los días.
Todo eso funcionaba sobre un monolito ASP.NET heredado, servido con Windows IIS en instancias virtuales de Amazon EC2, con Microsoft SQL Server para los datos y Apache Solr para la búsqueda. Se habían acumulado cuatro problemas:
- Un monolito difícil de cambiar. Todo estaba muy acoplado, así que cada despliegue ponía en riesgo todo el sitio, y los servidores se parchaban a mano.
- Costos altos. Las máquinas virtuales y las licencias de Microsoft encarecían el hosting y el mantenimiento.
- Una búsqueda por palabras clave, no por intención. La configuración de Solr no manejaba bien la variedad de búsquedas inmobiliarias, con tipos de inmueble muy distintos.
- Ubicaciones imprecisas. La gente busca con nombres informales de barrios, apodos locales y frases conversacionales. El buscador no entendía la mayoría.
Y una restricción por encima de todo: el sitio tenía que seguir funcionando. Sin caídas, sin inconsistencias de datos, sin picos de latencia y sin perder posiciones en buscadores.
El objetivo
- Reemplazar el monolito por servicios en Django y React que el equipo pudiera cambiar y desplegar de forma independiente.
- Salir del software con licencia y de los servidores administrados a mano para reducir costos.
- Mantener el sitio arriba todo el tiempo, para usuarios y agentes.
- Mantener los Core Web Vitals iguales o mejores que el sitio anterior, y la publicación de inmuebles en su referencia de 30 minutos.
- Lograr que la búsqueda entendiera lo que la gente quiere decir, incluida la forma en que nombra los lugares.
El enfoque: cuatro niveles, una capa a la vez
Reescribir todo de una vez nunca fue una opción. Usé el patrón strangler fig: construir el sistema nuevo alrededor del viejo, mover el tráfico por partes y retirar el monolito cuando nada dependa de él. Para hacerlo manejable, dividí el trabajo en cuatro niveles, y cada uno hacía posible el siguiente.
| Nivel | Antes | Después |
|---|---|---|
| 1. Plataforma | EC2 con máquinas virtuales, Windows IIS, parches manuales | Contenedores Docker en Kubernetes, NGINX, CI/CD automatizado |
| 2. Entrada e identidad | El tráfico iba directo al monolito | Kong API Gateway enruta cada solicitud, Keycloak para identidad y acceso |
| 3. Datos y búsqueda | Microsoft SQL Server, Apache Solr | PostgreSQL para transacciones, Elasticsearch para búsqueda, Lambda sincronizando ambos mundos |
| 4. Servicios y frontend | Un solo código en ASP.NET | Servicios en Django por dominio de negocio, frontend en React |
Arquitectura durante la migración
Nivel 1: una plataforma para el sistema nuevo
Antes de mover código, los servicios nuevos necesitaban dónde correr. Reemplazamos las máquinas virtuales de EC2 administradas a mano por contenedores Docker orquestados con Kubernetes, cambiamos Windows IIS por NGINX como servidor web y proxy inverso, y pusimos pipelines de CI/CD automatizados antes de cada despliegue. Desplegar pasó de ser un evento riesgoso y manual a algo rutinario, y el nuevo stack usaba menos recursos para más tráfico.
Nivel 2: una sola puerta de entrada, una sola identidad
Después pusimos Kong API Gateway delante de ambos sistemas. Desde entonces, cada solicitud pasaba por un solo punto que decidía si respondía el sistema viejo o el nuevo. Eso nos permitió mover el tráfico ruta por ruta, y devolver una ruta al sistema viejo si algo se veía mal. Keycloak dio a ambos sistemas una sola capa compartida de identidad y acceso.
Nivel 3: datos y búsqueda, siempre sincronizados
Movimos los datos transaccionales de Microsoft SQL Server a PostgreSQL, lo que mejoró la integridad y el rendimiento y eliminó el costo de licencias. La búsqueda pasó de Apache Solr a Elasticsearch, hecho para lecturas rápidas y de alto volumen. PostgreSQL manejaba lo que tenía que ser correcto; Elasticsearch, lo que tenía que ser rápido.
Lo más difícil fue operar dos sistemas al mismo tiempo. Funciones de AWS Lambda basadas en eventos copiaban cada cambio entre los almacenes viejos y nuevos en tiempo real, así que nunca se contradecían mientras los servicios se migraban uno por uno. Un inmueble publicado en cualquiera de los dos lados seguía apareciendo en la misma ventana de 30 minutos de antes.
Nivel 4: servicios por dominio y un frontend nuevo
Con la plataforma, el gateway y los datos listos, dividimos el monolito en servicios Django, uno por dominio de negocio, con un frontend en React. Cada servicio asumió su parte del sitio detrás de Kong, un dominio a la vez. El trabajo pesado, como publicar inmuebles en gran volumen, pasó a tareas en segundo plano con Celery y RabbitMQ, para que un pico de cargas de agentes no volviera lento el sitio para todos.
Una búsqueda que entiende cómo la gente nombra los lugares
Pasar la búsqueda a Elasticsearch también fue la oportunidad de hacerla más inteligente. Fue trabajo temprano con IA, años antes de la ola actual de IA generativa.
- Consultas en lenguaje natural. Agregamos comprensión de lenguaje natural, para que la búsqueda leyera la intención de una consulta conversacional en lugar de depender de filtros.
- Un mapa de todo el país. Adquirimos datos cartográficos y de malla vial de Colombia: ciudades, municipios, barrios y puntos de referencia.
- Nombres oficiales y apodos locales. Relacionamos los nombres oficiales con los nombres informales y alias que la gente realmente usa, y convertimos límites y zonas de interés en polígonos geográficos y vectores dentro de Elasticsearch.
Un ejemplo: "Zona T" es como mucha gente llama a una zona de Bogotá, pero ningún mapa oficial usa ese nombre. La búsqueda lo resolvía así:
Ejemplo: de un apodo local a un barrio oficial
La búsqueda pasó de comparar palabras a entender lugares.
Lo que salió mal: el inicio de sesión único
No todas las decisiones funcionaron. Keycloak era la idea correcta, una sola capa de identidad para ambos sistemas, pero era nuevo para el equipo y está construido en Java, que estaba fuera de nuestras habilidades principales. Encontramos problemas de integración que no habíamos previsto, y los vacíos en la documentación los hicieron lentos de resolver. Esa parte del proyecto tomó seis veces más de lo estimado.
En herramientas críticas, que el equipo las conozca y el soporte que tengan importan tanto como sus funcionalidades.
Hicimos una sesión abierta de lecciones aprendidas en lugar de buscar culpables, y agregamos un paso de evaluación para herramientas críticas: ¿el equipo conoce el stack?, ¿qué tan buena es la documentación y la comunidad?, ¿a quién llamamos cuando falle?
Liderar a 30 ingenieros en el proceso
- Propiedad para los seniors. Diseñé la arquitectura de alto nivel y les di a los ingenieros senior la propiedad total de implementarla. Eso hizo crecer la capacidad de liderazgo dentro del equipo y evitó que yo fuera un cuello de botella.
- Scrum en todas las áreas. Llevamos Scrum más allá de ingeniería y acordamos una sola Definición de Terminado y un solo formato de sprint review, para que producto, ingeniería y negocio vieran el mismo avance.
- Meter las manos cuando importaba. Cuando el nuevo stack abrumó al equipo, lo aprendí lo bastante rápido para desbloquear a la gente directamente, hasta que tuvieron confianza por su cuenta.
- Hacer crecer a las personas. Acompañé a un ingeniero junior para que asumiera un módulo crítico y defendiera sus decisiones de diseño, como PostgreSQL en lugar de NoSQL. Lo promovieron a nivel medio a los cinco meses.
Resultados
| Medida | Antes | Después |
|---|---|---|
| Costo de hosting y mantenimiento | Máquinas virtuales y licencias de Microsoft | 50% menos |
| Disponibilidad durante la migración | n/a | 100%, sin caídas |
| Despliegues | Parches manuales, alto riesgo | CI/CD automatizado, en contenedores |
| Largest Contentful Paint | Menos de 3 s | Menos de 3 s, con un sistema más complejo |
| Tiempo de publicación de inmuebles | 30 minutos | 30 minutos, con dos sistemas en paralelo |
| Búsqueda | Palabras clave en Apache Solr | Lenguaje natural y coincidencia geográfica en Elasticsearch |
| Servidor web | Windows IIS en EC2 | NGINX en Kubernetes, menos recursos, más capacidad |
| APIs REST en el nuevo backend | n/a | Más de 15, con 25% menos latencia |
Lo que llevaría a la próxima migración
- Construir primero la plataforma y el gateway. Después, cada movimiento es una decisión de enrutamiento que se puede deshacer.
- Reservar tiempo real para mantener dos sistemas sincronizados. Es la parte más difícil y la que protege al negocio.
- Elegir herramientas que el equipo ya conoce para todo lo crítico en seguridad.
- Medir desde el primer día lo que sienten los usuarios, como la velocidad de la página, para que "sin regresiones" sea un número y no una esperanza.
Recibe mis próximos casos y artículos en la Búsqueda de Google.