main content
< Volver a blog sobre aplicaciones móviles

Escalabilidad aplicación web a medida desde el día uno

Cómo planificar la escalabilidad de tu aplicación web a medida desde el primer día

Un viernes por la tarde, el CTO de una startup mandó un mensaje al canal de incidencias: "la base de datos al 98% de CPU, pedidos perdiéndose". Dos semanas antes habían celebrado multiplicar por cinco las altas mensuales. La misma decisión que hizo despegar el negocio —un esquema relacional sin réplicas, sesiones en memoria, todo en un servidor— se había convertido en el techo del producto.

Esta historia se repite cada semana en alguna empresa española. Casi siempre con el mismo origen: nadie pensó en escalar cuando todavía costaba poco hacerlo. Aquí va una guía honesta sobre cómo planificar la escalabilidad de tu aplicación web a medida desde el primer día, sin sobrediseño ni negligencia.

Por qué dejarlo "para cuando haga falta" sale carísimo

"Primero lancemos, luego escalamos." Suena pragmático, pero ignora una ley conocida desde los setenta: el coste de cambiar una decisión arquitectónica crece de forma exponencial con el tiempo. Lo que un viernes te cuesta una tarde, dieciocho meses después te cuesta un trimestre.

Pongamos un ejemplo concreto. Un Postgres con un esquema mal normalizado aguanta perfectamente 500 usuarios concurrentes. A los 50.000, las consultas que antes tardaban 20 ms tardan 4 segundos, los índices ya no caben en memoria y la migración a un modelo particionado implica downtime, dual writes y un mes de noches mal dormidas.

Lo mismo pasa con el acoplamiento entre módulos, con dónde guardas la sesión del usuario o con cómo gestionas el caché. Cada una de esas elecciones, tomada sin pensar en crecer, acaba siendo un ancla.

Cómo se manifiesta la deuda arquitectónica

No hablamos de código feo. Hablamos de cosas que matan velocidad de equipo:

  • Módulos tan acoplados que no puedes desplegar el de facturación sin tocar el de usuarios.
  • Una base de datos monolítica que no admite sharding sin reescribir la mitad del ORM.
  • Llamadas directas a la API de un proveedor —pasarela de pagos, mensajería, CRM— sin capa de abstracción, así que cambiarlo es un proyecto en sí mismo.
  • Infraestructura clavada a un proveedor cloud sin posibilidad de mover cargas a otro o ir a un esquema híbrido.

La regla empírica que manejamos los que llevamos años en esto: arreglar un fallo arquitectónico en producción cuesta entre 10 y 100 veces más que haberlo resuelto en la pizarra.

Principios que de verdad sostienen una arquitectura escalable

No hay receta única. Pero sí hay brújulas. Estas tres son las que más nos ahorran disgustos en proyectos reales de aplicación web a medida.

Separar responsabilidades sin tirarse a microservicios

El error más común que veo es confundir "arquitectura escalable" con "microservicios desde el día uno". Mal. Un equipo de cuatro personas no necesita orquestar quince contenedores en Kubernetes; necesita un monolito modular bien dibujado.

Un monolito modular tiene la simplicidad operativa de un único despliegue, pero por dentro los dominios viven en módulos con interfaces explícitas. Nada de compartir tablas entre módulos. Nada de imports cruzados a antojo. Cuando dentro de dos años el módulo de búsqueda necesite Elasticsearch y un equipo dedicado, lo extraes sin abrir la caja torácica del sistema.

Diseñar para escalar horizontalmente

Escalar verticalmente —añadir CPU o RAM a la misma máquina— tiene techo físico y un precio que crece de forma poco amable. Escalar horizontalmente —añadir más instancias del mismo servicio detrás de un balanceador— es prácticamente ilimitado, pero exige decisiones desde el principio:

  • Stateless siempre que se pueda. La sesión no vive en la memoria del proceso; vive en Redis o en un JWT firmado. Si reinicias una instancia, no se cae nadie.
  • Balanceador delante, sí, pero pensado: health checks reales, draining limpio en despliegues, sticky sessions solo cuando no hay alternativa.
  • Asume consistencia eventual donde puedas permitírtelo. No todos los datos necesitan ser fuertes consistentes; un contador de "me gusta" no es un saldo bancario.

La base de datos: la decisión más cara de revertir

Si solo te llevas una idea de este artículo, que sea esta. La elección del motor de datos condiciona el resto. Mis criterios prácticos:

  • Postgres por defecto para cualquier cosa transaccional. Aguanta lo que le eches, escala vertical sin problemas hasta cifras serias, y horizontalmente con réplicas de lectura, particionamiento por rangos o herramientas como Citus.
  • NoSQL (MongoDB, DynamoDB, Cassandra) cuando el modelo es realmente flexible, las escrituras son masivas y la consistencia fuerte no es crítica. Logs, eventos, feeds.
  • Híbrido es lo más habitual en producción: Postgres para el núcleo, Redis para caché y sesiones, S3 para blobs, y a veces un Elastic o un ClickHouse para búsqueda y analítica.

Lo importante no es acertar al 100% el día uno —no vas a acertar—, sino aislar el acceso a datos detrás de repositorios o casos de uso para que mañana puedas mover una entidad de Postgres a DynamoDB sin tocar la lógica de negocio.

Lo que sí merece la pena hacer desde el día uno

Eventos para desacoplar

Cuando un usuario completa un pedido, ocurren cinco cosas: se cobra, se actualiza el stock, se manda email, se notifica a logística, se registra en analítica. Si esas cinco cosas viven en la misma función síncrona, el primer fallo de la pasarela tira el pedido entero.

La alternativa: emitir un evento OrderCompleted y dejar que cada servicio lo consuma a su ritmo. Internamente puedes empezar con un bus en memoria, y cuando el tráfico lo pida pasas a RabbitMQ, Kafka o SQS sin reescribir la lógica. Los consumidores escalan independientemente, los picos de tráfico se absorben en la cola, y añadir un nuevo comportamiento es añadir un consumidor más, no tocar el flujo existente.

No hace falta montar event sourcing completo el primer día. Sí hace falta que los flujos críticos estén pensados con esta mentalidad.

Caché en capas

El caché es la palanca de escalado más barata que existe. La estrategia que recomendamos casi siempre tiene tres pisos:

  • CDN (Cloudflare, CloudFront, Fastly) delante de todo lo que sea estático y de las respuestas de API cacheables. Esto te quita tráfico de encima antes de que llegue a tu infraestructura.
  • Redis o Memcached para resultados de queries caras, datos de referencia y sesiones. Patrón cache-aside con TTLs sensatos.
  • Caché en la propia base de datos: query cache, vistas materializadas para los informes que se consultan cada cinco minutos.

Aviso: un caché que sirve datos obsoletos es peor que no tener caché. Define la política de invalidación antes que la de almacenamiento. Si no sabes cuándo se invalida, no lo cachees.

Si te suena que esto es justo el momento en el que tu proyecto está y necesitas a alguien que haya tomado estas decisiones antes en producción, podemos sentarnos a revisar tu arquitectura sin compromiso y trazar contigo una hoja de ruta realista.

Observabilidad antes que features bonitos

No puedes escalar lo que no puedes medir. Y "medir" no es entrar por SSH a leer logs. Desde el primer despliegue:

  • Métricas de rendimiento por endpoint: p50, p95, p99, throughput, tasa de error. Prometheus + Grafana, o Datadog si prefieres pagar a alguien para que te lo dé hecho.
  • Logs estructurados en JSON, agregados en un único sitio (Loki, ELK, CloudWatch). Si tu log dice "error en el módulo X" sin contexto, no es un log, es una nota suelta.
  • Trazabilidad distribuida con OpenTelemetry. Cuando un día tengas seis servicios y una petición se pierda entre ellos, agradecerás haberlo puesto al principio.

Errores que aparecen una y otra vez

Optimización prematura no es lo mismo que diseño prematuro

Implementar sharding para 100 usuarios es ridículo. Definir desde el día uno los límites entre módulos, elegir un motor de datos coherente y dejar la sesión fuera del proceso, no lo es. El diseño establece la estructura; la optimización resuelve cuellos concretos cuando aparecen. Confundir ambas cosas lleva a equipos paralizados durante meses optimizando lo que nadie usa.

Ignorar los límites del proveedor cloud

Cada cloud tiene techos: conexiones por RDS, tamaño máximo de payload en API Gateway, throttling de DynamoDB, cuotas regionales de EC2. Diseñar sin conocerlos lleva a sorpresas a las tres de la madrugada. Documenta los límites relevantes, implementa circuit breakers con Resilience4j o Polly, retry con backoff exponencial y, sobre todo, prueba los modos de fallo antes de descubrirlos en producción.

No tener una estrategia de migraciones de esquema

El esquema va a cambiar. Siempre. Lo que separa a un equipo profesional de uno que improvisa es tener migraciones versionadas con Flyway, Liquibase, Alembic o las nativas del framework, y la disciplina absoluta de nunca tocar el esquema a mano en producción. Nunca.

Caso real: de 1.000 a 100.000 usuarios sin reescribir

Tomemos una plataforma de reservas para una cadena hotelera mediana. En fase inicial, con 1.000 usuarios concurrentes, basta con un monolito modular en Postgres, una instancia detrás de un balanceador y un CDN delante de los estáticos.

A los 10.000 usuarios la cosa cambia: añades dos réplicas de lectura de Postgres y rediriges las consultas de disponibilidad a ellas; metes Redis con cache-aside para el catálogo de hoteles; escalas horizontalmente el backend a cuatro instancias detrás del balanceador. Todo esto se hace en una sprint, no en un trimestre.

A los 100.000 la arquitectura evoluciona de verdad: extraes el módulo de búsqueda como servicio independiente con Elasticsearch, desacoplas el procesamiento de pagos con una cola SQS, montas un API Gateway que centralice autenticación, rate limiting y enrutamiento. El módulo de notificaciones se vuelve un consumidor más de eventos.

Lo crucial: nada de esto exige reescribir el núcleo. Las decisiones del primer día —monolito modular, estado fuera del proceso, eventos para flujos críticos, repositorios bien aislados— prepararon el camino.

Cómo elegir al partner técnico adecuado

Planificar la escalabilidad de una aplicación web a medida requiere algo que no se aprende en blogs: haberse comido los problemas antes en sistemas reales. Cuando evalúes a una consultora, pregunta por casos concretos. Qué decisiones tomaron el primer día y cuáles se arrepienten de no haber tomado. Las respuestas vagas son señal de alarma.

Conclusiones

La escalabilidad no es una fase del proyecto. Es una propiedad que se diseña desde el primer día con decisiones conscientes: módulos con responsabilidades claras, estado fuera del proceso, caché en capas con invalidación pensada, observabilidad de serie y una estrategia de datos honesta sobre lo que aguanta cada motor.

El coste de hacerlo bien desde el principio es marginal. No hacerlo se paga con intereses, justo cuando el negocio empieza a ir bien. La diferencia entre una aplicación que acompaña el crecimiento y otra que lo frena se decide antes de escribir la primera línea de código.

Contacta con nosotros
Fila 1