Cuando la Plataforma Tuvo que Soportar 20× Más Tráfico
Impacto
~20× más capacidad de usuarios
Durante la pandemia, la demanda y las campañas promocionales empezaron a llevar nuestra infraestructura mucho más allá de lo que soportaba un backend monolítico de instancia única. En vez de migrar a Kubernetes o reescribir la infraestructura, distribuí el tráfico con múltiples instancias detrás de Apache como balanceador de carga y distribución a nivel DNS en el frontend, multiplicando por 20 la capacidad de usuarios en un período muy corto.
Durante la pandemia nos encontramos con un problema que muchas startups descubren de golpe cuando su producto empieza a crecer: la demanda explotó. Hasta ese momento, nuestra infraestructura había sido suficiente para el tráfico habitual de la plataforma, pero el crecimiento sumado a campañas promocionales que podían generar picos enormes en cuestión de minutos empezó a llevarla mucho más allá de los niveles para los que había sido diseñada. El problema era especialmente delicado porque el backend era esencialmente un monolito: cada instancia tenía una capacidad limitada de procesamiento y de conexiones concurrentes, y podíamos seguir escalando verticalmente, pero eventualmente llegábamos a un límite físico y económico. Tampoco teníamos en ese momento una infraestructura basada en Kubernetes ni un sistema de autoscaling preparado para reaccionar automáticamente ante esos picos. Necesitábamos resolverlo rápido, y sin convertir una emergencia de performance en una reescritura completa de la infraestructura.
Escalar horizontalmente con lo que ya teníamos
La primera decisión fue cambiar la forma en la que distribuíamos el tráfico. En vez de intentar que una única instancia soportara toda la carga, levantamos múltiples instancias de la API, tanto en AWS como en servidores que ya teníamos disponibles internamente, y usamos Apache como balanceador de carga para distribuir las solicitudes entre ellas. La idea era simple: si una instancia soportaba una cantidad determinada de tráfico, varias instancias en paralelo nos daban considerablemente más capacidad total sin tener que modificar la aplicación de inmediato.
Distribuir también el tráfico del frontend
El frontend tenía su propia particularidad: nuestra infraestructura web estaba desplegada en AWS, así que necesitábamos distribuir también esas solicitudes entre distintos servidores. Implementamos una estrategia de distribución a nivel DNS para dirigir el tráfico hacia diferentes destinos, de modo que dejó de depender de un único punto de entrada. No era una plataforma de infraestructura completamente elástica, pero no necesitábamos construir una para resolver el problema inmediato: necesitábamos comprar capacidad rápido y de forma controlada.
Resolver primero el problema real
Una de las decisiones más importantes fue no intentar resolver en ese momento todos los problemas arquitectónicos que eventualmente íbamos a tener. No migramos todo a Kubernetes, no reescribimos el backend, no convertimos la plataforma en una arquitectura completamente distribuida. Construimos una capa de distribución alrededor de la infraestructura que ya teníamos, lo que transformó un problema de capacidad de una instancia en un problema de distribución de carga entre varias, y pudimos hacerlo en un período muy corto.
Resultado
La estrategia funcionó: con una serie de configuraciones relativamente chicas conseguimos aumentar aproximadamente 20× la capacidad de usuarios que la plataforma podía soportar respecto a la configuración original. Esto fue especialmente importante durante las campañas promocionales, donde podíamos pasar de tráfico normal a picos enormes prácticamente de golpe, y la infraestructura distribuía esa carga entre los servidores disponibles. La plataforma mantuvo buena performance durante uno de los períodos de mayor crecimiento y demanda que habíamos tenido.
Lo que aprendí
Este fue uno de esos problemas donde la solución técnicamente más sofisticada no era necesariamente la correcta. En retrospectiva, probablemente podríamos haber diseñado una infraestructura mucho más compleja y automatizada, pero el problema que teníamos delante no era construir la infraestructura perfecta: era evitar que la plataforma colapsara mientras la demanda crecía exponencialmente. La solución fue pragmática, relativamente económica y rápida de implementar, y nos dio algo que necesitábamos en ese momento: tiempo. Tiempo para que el producto siguiera creciendo y para después pensar en una evolución más profunda de la infraestructura. Para mí, este caso sigue representando una idea importante al trabajar con sistemas en producción: la buena ingeniería no siempre consiste en construir la arquitectura más avanzada, sino en encontrar el cambio más chico capaz de resolver un problema enorme.