Motor de disponibilidad de alto rendimiento
Arquitectura y optimización del algoritmo de disponibilidad de una plataforma B2B de reservas turísticas, atendiendo picos del orden de 5 millones de peticiones por hora.
Contexto
Sidetours es una plataforma B2B de reservas de experiencias turísticas. El componente crítico no era el proceso de reserva en sí, sino todo lo que ocurre antes: la consulta de disponibilidad.
Cada búsqueda de un cliente se traduce en un abanico de comprobaciones —fechas, cupos, precios, condiciones por proveedor— y ese abanico se multiplica por cada operador conectado. En picos de operación, el algoritmo de disponibilidad llegaba a atender del orden de 5 millones de peticiones por hora, sosteniendo una media de entre 1.000 y 1.500 reservas diarias.
El punto de partida
Buena parte del sistema era PHP legacy y vanilla, escrito por distintas personas a lo largo de los años. La tentación evidente en ese escenario es proponer una reescritura completa. En una plataforma que está facturando cada día, esa propuesta casi nunca sobrevive al contacto con la realidad: es cara, es larga y durante el proceso no aporta nada al negocio.
El enfoque fue el contrario: medir primero, tocar solo lo que duele.
Qué se hizo
Identificar el camino crítico real. Antes de optimizar nada, había que saber dónde se iba el tiempo. No en la parte del código que parecía más fea, sino en la que aparecía en el perfil de ejecución bajo carga real. Rara vez coinciden.
Cachear la disponibilidad, no la respuesta. La disponibilidad cambia con frecuencia, pero no uniformemente: hay combinaciones de fecha y producto que se consultan cientos de veces por minuto y otras que no se consultan nunca. Cachear a nivel de respuesta completa desaprovecha eso; cachear la unidad de disponibilidad permite reutilizarla entre consultas distintas.
Reducir el trabajo por petición antes que acelerar el trabajo. La optimización con mejor retorno no fue hacer las consultas más rápidas, sino dejar de hacer las que no hacían falta: descartar pronto combinaciones imposibles, agrupar comprobaciones al mismo proveedor y evitar recalcular lo que no había cambiado.
Modernizar por partes, sin parar la operación. Cada bloque crítico se fue aislando detrás de una frontera clara, de forma que se pudiera reescribir por dentro sin que el resto del sistema se enterase. El código legacy no desaparece de golpe: se arrincona.
Infraestructura
Para absorber los picos, la plataforma se apoyaba en autoescalado horizontal sobre AWS y en replicación de base de datos master-slave, separando la carga de lectura —que es la abrumadora mayoría en un motor de disponibilidad— de las escrituras del proceso de reserva. Delante, Nginx como reverse proxy y Redis absorbiendo todo lo que no tenía por qué llegar a la base de datos.
Lo que me llevé
Que en sistemas de alto rendimiento el trabajo interesante casi nunca es el algoritmo en sí, sino decidir qué no ejecutar. Y que en una base legacy la habilidad que más se valora no es reescribir bien, sino saber convivir con lo que hay mientras lo mejoras.