Pruebas de capacidad: cómo saber cuántos usuarios soporta tu aplicación
Antes de una campaña comercial, el lanzamiento de una funcionalidad o un período de alta demanda, una pregunta suele aparecer demasiado tarde: ¿cuántos usuarios soporta realmente la aplicación? La respuesta no se obtiene observando únicamente cuántas solicitudes por segundo procesa una API. Una plataforma puede aceptar muchas peticiones simples y, al mismo tiempo, degradarse cuando los usuarios ejecutan un flujo de negocio que consulta varias tablas, reserva inventario, procesa pagos o publica eventos.
Una prueba de capacidad permite responder esa pregunta con un escenario controlado. Para que sea útil, debe partir de un flujo crítico, representar un comportamiento de usuario razonable, incluir las dependencias relevantes y establecer de antemano qué se considera una degradación inaceptable.
Qué es una prueba de capacidad y qué decisión ayuda a tomar
Una prueba de capacidad busca identificar cuánta carga puede sostener un sistema manteniendo los niveles de servicio definidos por el negocio y la operación. No se trata solamente de encontrar el número máximo de usuarios antes de que ocurra un error, sino de determinar cuál es el límite operativo aceptable.
Ese límite depende de varios factores:
- El flujo que ejecutan los usuarios.
- La proporción entre lecturas, escrituras y operaciones costosas.
- Los tiempos de respuesta esperados para cada operación.
- La tasa de errores y timeouts tolerable.
- La capacidad de bases de datos, colas, servicios externos y otros componentes.
- La posibilidad de escalar durante el evento de alta demanda.
Por eso, la capacidad no es una propiedad fija de la aplicación. Puede cambiar después de una modificación en el código, un cambio de infraestructura, una nueva consulta a la base de datos o una variación en el comportamiento de los usuarios.
Capacidad, carga y estrés no significan lo mismo
Estos términos suelen utilizarse como sinónimos, aunque representan objetivos diferentes:
- Prueba de carga: verifica cómo se comporta el sistema bajo una carga esperada o representativa. Ayuda a validar tiempos de respuesta, errores y consumo de recursos.
- Prueba de capacidad: busca determinar hasta qué nivel puede operar el sistema cumpliendo los criterios definidos. El resultado debería relacionar una carga con un nivel de servicio y un límite operativo.
- Prueba de estrés: lleva el sistema más allá de su operación normal para observar cómo falla, cómo se recupera y si el impacto queda contenido.
Una prueba de estrés puede revelar el punto de ruptura, pero ese punto no necesariamente debe convertirse en la capacidad anunciada. Operar cerca de la saturación deja poco margen para variaciones de tráfico, tareas en segundo plano o fallos parciales.
Comienza por un flujo de negocio crítico, no por requests por segundo
El primer paso es elegir qué comportamiento debe representar la prueba. En un e-commerce podría ser el flujo de búsqueda de un producto, consulta de detalle, agregado al carrito e inicio del checkout. En una plataforma SaaS podría incluir el inicio de sesión, la carga de un panel, una operación sobre una entidad y la generación de una notificación.
El flujo debe ser lo suficientemente representativo para ejercer los componentes que pueden convertirse en cuellos de botella. Probar únicamente un endpoint de consulta puede ocultar problemas que aparecen cuando el usuario mantiene una sesión, escribe datos, inicia una transacción o dispara procesamiento asíncrono.
Define el escenario de usuario
Documenta el flujo antes de construir el script de prueba. Una definición útil debería incluir:
- Acciones que realiza el usuario y su orden.
- Endpoints, pantallas o comandos involucrados.
- Tiempo de espera entre acciones, si corresponde.
- Porcentaje relativo de cada recorrido cuando existen varios flujos.
- Operaciones que deben completarse correctamente para considerar exitoso el escenario.
También es importante distinguir entre usuarios concurrentes y solicitudes por segundo. Los usuarios concurrentes representan sesiones o recorridos activos. Las solicitudes por segundo son una consecuencia del comportamiento de esas sesiones. Dos escenarios con igual concurrencia pueden generar cargas muy distintas si uno realiza más llamadas o incluye operaciones más costosas.
Prepara datos y dependencias que representen la operación real
Una prueba con datos artificiales o demasiado pequeños puede producir conclusiones engañosas. Las consultas, índices, cachés y planes de ejecución pueden comportarse de otra forma cuando aumenta el volumen de información o cuando muchos usuarios acceden a los mismos recursos.
El conjunto de datos debería considerar, según el caso:
- Usuarios y roles con permisos similares a los reales.
- Productos, cuentas, órdenes o entidades con relaciones representativas.
- Estados que obliguen a recorrer las mismas reglas de negocio.
- Distribución entre datos muy consultados y datos poco frecuentes.
- Escenarios de éxito y respuestas esperadas para operaciones inválidas.
La prueba también debe declarar qué dependencias participan. Entre ellas pueden estar una base de datos, un sistema de identidad, un proveedor de pagos, un servicio de correo, un broker de eventos, una API de terceros o un almacenamiento de objetos.
Dependencias reales, simuladas o controladas
No siempre conviene ejecutar una prueba contra servicios externos reales. Puede haber restricciones de costo, límites de uso, efectos secundarios o falta de control sobre su capacidad. En esos casos, una simulación puede ser apropiada, pero debe conservar características relevantes como latencia, errores, límites y comportamiento de reintentos.
La decisión debe quedar documentada. Una prueba que simula el proveedor de pagos no demuestra la capacidad completa del checkout; demuestra la capacidad de la aplicación bajo el comportamiento simulado de ese proveedor. Si una dependencia externa es crítica, conviene realizar validaciones específicas o pruebas controladas adicionales.
Diseña la carga y el criterio de degradación
Una prueba de capacidad no debería comenzar directamente con la carga máxima imaginada. Es preferible construir una progresión que permita observar cuándo cambian los indicadores del sistema:
- Un nivel inicial para validar que el escenario funciona.
- Incrementos graduales de concurrencia o de volumen.
- Un período suficiente para observar estabilidad y no solo una respuesta momentánea.
- Una etapa de reducción para evaluar la recuperación.
- Opcionalmente, una fase de estrés para analizar el comportamiento más allá del límite operativo.
El criterio de degradación debe definirse antes de ejecutar la prueba. Puede incluir un tiempo de respuesta máximo para operaciones críticas, una tasa de errores, un nivel de saturación sostenido o una combinación de señales.
Por ejemplo, el límite podría establecerse cuando el flujo de checkout deja de cumplir su objetivo de tiempo de respuesta, cuando aumentan los errores de persistencia o cuando la cola de trabajo crece sin capacidad de recuperación. No es necesario que todos los componentes estén al cien por ciento de utilización para declarar una degradación: un servicio dependiente puede convertirse en el límite mucho antes.
Un ejemplo de escenario para un e-commerce
Supongamos un flujo compuesto por búsqueda, consulta de detalle, agregado al carrito y comienzo del checkout. La prueba puede modelar distintas proporciones de usuarios: algunos abandonan después de consultar productos, otros agregan artículos y una parte llega al checkout.
El escenario debería comprobar más que la disponibilidad de cada endpoint. También debe verificar que:
- Los resultados corresponden a los datos solicitados.
- El carrito conserva su estado durante el recorrido.
- Las reglas de inventario se aplican correctamente.
- Las operaciones no generan duplicados por reintentos.
- Los eventos publicados no se acumulan indefinidamente.
El objetivo no es inventar una cantidad de usuarios, sino descubrir qué nivel de concurrencia puede sostener ese flujo bajo las condiciones y los criterios acordados.
Mide la aplicación y la infraestructura al mismo tiempo
Los resultados de la prueba deben combinar métricas técnicas y de negocio. Un tiempo de respuesta elevado indica que existe un problema, pero no explica por sí solo dónde se origina.
Métricas de la aplicación
- Tiempo de respuesta por operación y por percentiles, no solo el promedio.
- Tasa de errores, timeouts y respuestas rechazadas.
- Solicitudes completadas y operaciones de negocio exitosas.
- Duración de consultas y llamadas a dependencias.
- Longitud y tiempo de espera en colas.
- Reintentos, circuit breakers y respuestas degradadas.
Métricas de infraestructura
- Uso de CPU y memoria de los servicios.
- Presión de memoria, pausas del recolector y saturación de workers cuando aplique.
- Conexiones y latencia de la base de datos.
- Uso del pool de conexiones.
- Operaciones de lectura y escritura de almacenamiento.
- Red, balanceadores, réplicas y escalado de contenedores.
La observabilidad debe permitir correlacionar una transacción con sus llamadas internas. Sin trazas, logs estructurados o métricas por componente, es fácil concluir que “la API es lenta” cuando el verdadero problema está en una consulta, un pool agotado o una dependencia que responde con demora.
También conviene observar la estabilidad después de reducir la carga. Un sistema puede responder correctamente durante el incremento, pero dejar tareas pendientes, conexiones abiertas o recursos sin liberar.
Identifica el punto de saturación y valida el margen operativo
El punto de saturación aparece cuando aumentar la carga produce una degradación desproporcionada o sostenida. Algunas señales frecuentes son:
- El tiempo de respuesta crece aunque la tasa de solicitudes se mantenga estable.
- La cola de mensajes o trabajos pendientes aumenta sin vaciarse.
- El pool de conexiones permanece agotado.
- La base de datos eleva su latencia o comienza a rechazar operaciones.
- Los contenedores escalan, pero el componente dependiente no acompaña ese crecimiento.
- Aumentan los timeouts y reintentos, generando todavía más carga.
La capacidad operativa debería ubicarse antes de ese punto, con un margen que contemple variaciones de tráfico y tareas no incluidas en la prueba. Ese margen no puede definirse de forma universal: depende de la previsibilidad de la demanda, la velocidad de escalado, la criticidad del flujo y el costo de una degradación.
Si el sistema escala horizontalmente, la prueba debe confirmar que el escalado mejora realmente la capacidad. Añadir instancias no resuelve un cuello de botella en una base de datos, un límite de conexiones, un proveedor externo o un recurso compartido.
Errores frecuentes al preparar una prueba de capacidad
- Probar solo endpoints aislados: un endpoint rápido no representa necesariamente un flujo de negocio completo.
- Usar datos irreales: tablas pequeñas o una distribución uniforme pueden ocultar problemas de consultas y caché.
- Confundir concurrencia con tráfico: la misma cantidad de usuarios puede producir diferentes tasas de solicitudes.
- Medir únicamente el promedio: los promedios pueden ocultar una experiencia deficiente para una parte de los usuarios.
- Ignorar las dependencias: una prueba interna puede sobreestimar la capacidad si no considera identidad, pagos, mensajería o almacenamiento.
- No validar la corrección funcional: respuestas rápidas pero incorrectas no representan capacidad útil.
- Ejecutar la prueba sin criterios previos: sin una definición de degradación, los resultados quedan sujetos a interpretaciones.
- Realizar una única ejecución: los resultados pueden verse afectados por cachés, calentamiento, datos o condiciones transitorias.
La prueba tampoco debería ejecutarse directamente sobre producción sin un plan de seguridad, límites de impacto y coordinación con los equipos responsables. Un entorno de validación puede ser más adecuado, siempre que su arquitectura y configuración permitan extrapolar los resultados con cuidado.
Cómo convertir el resultado en una decisión operativa
El resultado final debería ser más preciso que “la aplicación soporta muchos usuarios”. Debe expresar una relación entre escenario, carga, condiciones y nivel de servicio.
Una conclusión útil puede documentar:
- Qué flujo se ejecutó y con qué distribución de usuarios.
- Qué datos y dependencias participaron.
- Qué nivel de concurrencia o volumen se alcanzó.
- Qué tiempos de respuesta y tasa de errores se observaron.
- Qué componente limitó la capacidad.
- Qué criterio determinó la degradación.
- Qué margen se recomienda conservar antes de un evento de alta demanda.
- Qué acciones podrían ampliar la capacidad o reducir el riesgo.
Estas acciones pueden incluir optimizar una consulta, ajustar pools, revisar el uso de caché, procesar una parte del flujo de forma asíncrona, limitar funcionalidades no críticas, mejorar el escalado o negociar límites con un proveedor. Cada alternativa tiene trade-offs: más caché puede introducir problemas de invalidación; más reintentos pueden aumentar la carga; más réplicas pueden trasladar la saturación a la base de datos.
La prueba de capacidad también debería integrarse al ciclo de entrega cuando el flujo sea crítico. No todas las ejecuciones necesitan reproducir una validación completa, pero las regresiones relevantes de latencia, errores o consumo deberían detectarse antes de un cambio importante.
Conclusión: la capacidad se define con evidencia y criterios claros
Saber cuántos usuarios soporta una aplicación requiere mucho más que observar requests por segundo. Es necesario modelar un flujo de negocio, preparar datos representativos, entender las dependencias, medir aplicación e infraestructura y definir qué señal marca una degradación inaceptable.
La decisión importante no es encontrar el máximo teórico, sino establecer una capacidad operativa que pueda sostenerse con margen y que esté respaldada por evidencia. Antes de asumir que tu plataforma soportará el próximo pico, define cómo medirás su capacidad, qué flujo vas a probar y qué señal marcará el límite. Cuando el análisis requiera revisar arquitectura, observabilidad o estrategia de pruebas, una evaluación técnica especializada puede ayudar a convertir los resultados en un plan de mejora concreto.
