Tu app aguanta 10 usuarios. ¿Y mil? El scaling cliff y cómo cruzarlo con Claude
Funciona perfecto con 10 usuarios, se arrastra con 100 y con mil se cae al suelo. Eso es el scaling cliff, y las apps hechas con IA le pegan durísimo: el código está optimizado para que funcione, no para que funcione a escala. Aquí están los prompts exactos —para Claude Code o Codex— de las tres cosas que lo arreglan en tu propio código sin que toques una línea, más el load testing que casi nadie hace.
De un vistazo
Qué es el scaling cliff
Los 3 arreglos: indexing, caching, async
Load testing antes de lanzar
Checklist + prompts listos
el cliff · cómo pedirle · indexing · caching · async · load testing · checklist · FAQ
Los prompts exactos para que tu app aguante mil usuarios, no diez
Primero entiendes el problema: por qué una app que vuela con 10 usuarios se cae con mil, y por qué el código que escupe la IA le pega tan fuerte. Luego viene lo accionable: cómo darle estos prompts a tu agente para que de verdad funcionen, y los tres arreglos que aplica en tu propio código —indexing para que las consultas no se mueran cuando crece la data, caching para no computar lo mismo mil veces, y async para que el usuario no espere por correos ni reportes—. Cierra con el paso que casi nadie hace, el load testing (simular mil usuarios y ver dónde truena), un checklist de qué revisar antes de lanzar y una FAQ rápida.
01 el problema
Qué es el scaling cliff (y por qué las apps con IA le pegan durísimo)
El scaling cliff es ese acantilado invisible donde tu app pasa de funcionar perfecto a caerse, sin avisar. No es que vaya bajando de a poco: aguanta, aguanta, y de repente se desploma cuando llega más gente de la que esperabas.
10 usuarios
Todo perfecto. Carga al instante, nada falla. Aquí es donde lanzas feliz.
100 usuarios
Empieza a arrastrarse. Pantallas que tardan, botones que no responden a la primera.
1000 usuarios
Se cae al suelo. Errores, tiempos eternos, usuarios que se van y no vuelven.
¿Por qué les pega tan fuerte a las apps hechas con IA? Porque el código que te genera la inteligencia artificial está optimizado para que funcione, no para que funcione a escala. Hace lo que le pediste con los datos que tenías enfrente (diez registros, tú probando solo), y eso se ve idéntico a algo listo para producción. La diferencia solo aparece cuando llega el volumen. Dos ejemplos clásicos:
- 01
La query que era rápida deja de serlo
Esa consulta a la base de datos que con 100 filas tarda 50 milisegundos, con cien mil filas se va a 30 segundos. El usuario no espera 30 segundos: cierra la pestaña.
- 02
La llamada que se repite en cada carga
Esa llamada que haces en cada carga de página va bien con 10 usuarios. Con mil entrando al mismo tiempo es una espiral de muerte: cada quien dispara la misma cuenta, el servidor se ahoga.
El código no está mal. Nada más no lo diseñaron para escalar. Y la buena noticia: con tres cosas que le dices a tu agente de código —indexing, caching y async— lo dejas listo antes de lanzar, sin que toques una sola línea. Más una cuarta para probar que de verdad aguanta: el load testing. Vamos una por una.
02 antes de empezar
Cómo darle estos prompts a Claude (o Codex) para que de verdad funcionen
Todos los prompts de esta guía están pensados para pegárselos directo a tu agente de código —Claude Code o Codex, da igual cuál uses—. Pero un buen prompt en el agente equivocado no sirve. Estas cuatro reglas hacen la diferencia entre un arreglo real y un “lo intenté pero no cambió nada”.
Ábrelo dentro de la carpeta del proyecto
Tu agente trabaja sobre el código que ve. Préndelo en la raíz del repo para que pueda leer tus archivos, encontrar las queries y editar de verdad, no inventar.
Dale contexto del stack
En cada prompt rellena las {llaves}: qué base de datos usas, qué framework, dónde está hosteado. Sin eso, el agente adivina; con eso, te da el arreglo correcto a la primera.
Un pilar a la vez, no todo junto
No le pidas indexing, caching y async en un solo mensaje. Atáquenlos uno por uno: arregla, revisa, prueba, y luego el siguiente. Es más fácil de revisar y de revertir si algo sale mal.
Pídele que explique antes de editar
Que primero te enseñe qué encontró y qué va a cambiar, y que te muestre el diff. Tú apruebas. Así aprendes el vocabulario (es a propósito) y no metes cambios a ciegas.
Préndelo en la carpeta de tu proyecto y ya estás listo para el primer prompt:
Entra a la carpeta de tu proyecto y prende tu agente
cd ~/ruta/de/tu/proyecto && claude # o: codexTodos los prompts de aquí siguen la misma estructura, porque así es como un prompt deja de ser un deseo y se vuelve una instrucción que el agente puede ejecutar:
qué app es, qué stack usas, qué quieres lograr
los pasos concretos, numerados, que debe hacer
qué NO hacer y qué cuidar (no romper, no exagerar)
en qué forma quieres la respuesta (tabla, lista, código)
Empieza por este. Antes de arreglar nada, pídele el mapa: dónde están los cuatro riesgos y cuál se cae primero. Con eso atacas el resto en orden de impacto.
El prompt de arranque: dame el mapa antes de tocar nada
Empieza por aquí. En vez de arreglar a ciegas, este prompt le pide a tu agente que recorra el proyecto y te diga dónde están los cuatro riesgos de escala, ordenados por lo que se cae primero. Con ese mapa atacas uno por uno con los prompts de cada pilar.
(Claude Code o Codex)
Contexto: estoy preparando esta app para escalar de 10 a mil usuarios. Antes de cambiar código quiero un diagnóstico honesto. Mi stack es {lenguaje/framework}, base de datos {Postgres / MySQL / ...}, hosting {Vercel / AWS / Railway / ...}.
Tarea:
1. Recorre el proyecto y dime dónde están los cuatro riesgos de escala: queries sin índice o con SELECT *, cosas que se computan repetido y no se cachean, operaciones pesadas que corren en vivo (correos, reportes), y si existe o no algo de load testing.
2. Ordena los hallazgos por impacto: qué se cae primero cuando lleguen 100 y luego 1000 usuarios.
3. NO arregles nada todavía. Solo dame el mapa.
Qué quiero de salida: una lista priorizada de [riesgo · archivo · qué pasa al escalar · cuál de los cuatro arreglos lo resuelve], para atacarla uno por uno con los prompts de cada pilar.03 arreglo 1
Indexing: que tus queries sigan rápidas aunque la data crezca
Una query es cada pregunta que tu app le hace a la base de datos (“dame los pedidos de este usuario”). Sin un índice, la base revisa fila por fila hasta encontrar lo que pediste: con 100 filas no se nota, con cien mil tarda una eternidad. Un índice es como el directorio al final de un libro: en vez de leer todas las páginas, va directo a la que importa.
El error típico del código generado con IA es el SELECT * de todo: trae todas las columnas y revisa toda la tabla. Lo que quieres son búsquedas dirigidas, con índice, que sigan rápidas aunque la data crezca. Dile a tu agente que revise tus queries y les meta indexing:
01 · Audítame las queries y mételes los índices que faltan
Tu agente recorre el código, encuentra las consultas más usadas y te dice cuáles harían un scan completo de la tabla cuando crezca la data. Propone los índices exactos que faltan, sin meter uno por cada columna por si acaso.
(Claude Code o Codex)
Contexto: esta app usa {tu base de datos: Postgres / MySQL / SQLite / ...}. Quiero que las consultas sigan rápidas aunque la data crezca de cientos a cientos de miles de filas.
Tarea:
1. Encuentra las consultas a la base de datos que más se ejecutan (las de las pantallas principales y los endpoints más usados).
2. Para cada una, identifica por qué columnas filtra, ordena o hace join.
3. Dime cuáles NO tienen un índice que las cubra y cuáles harían un scan completo de la tabla cuando crezca.
4. Propón los índices que faltan (con el CREATE INDEX exacto) y explica en una línea qué consulta acelera cada uno.
Límites:
- No metas un índice por cada columna "por si acaso": solo los que de verdad usan las consultas reales. Demasiados índices vuelven lentas las escrituras.
- Antes de cambiar nada, enséñame la lista y espera mi OK.
Qué quiero de salida: una tabla [consulta · columnas · índice propuesto · qué acelera], y luego la migración lista para aplicar.02 · Encuéntrame las queries lentas y los N+1
El N+1 es esa consulta que dispara muchas otras dentro de un loop: invisible con 10 filas, mortal con cien mil. Este prompt las caza junto con los SELECT * que traen de más, te las ordena de peor a menos grave y te dice el arreglo concreto.
(Claude Code o Codex)
Contexto: sospecho que hay consultas lentas y problemas de N+1 (una consulta que dispara muchas otras dentro de un loop). Uso {tu ORM / stack: Prisma, Drizzle, ActiveRecord, ...}.
Tarea:
1. Busca los lugares donde se consulta la base de datos dentro de un bucle o de un render de lista (eso suele ser un N+1).
2. Busca los SELECT que traen columnas o filas de más (SELECT * donde solo se usan dos campos, listas sin límite ni paginación).
3. Para los puntos calientes, estima cómo crece el tiempo si la tabla pasa de 100 a 100 000 filas.
Límites:
- No reescribas nada todavía: primero quiero el diagnóstico ordenado de peor a menos grave.
- Marca cada hallazgo como [crítico / medio / menor] y dime el arreglo concreto (eager loading, paginación, seleccionar solo lo necesario, índice).
Qué quiero de salida: lista priorizada de queries problemáticas, con archivo y línea, y el arreglo propuesto para cada una.04 arreglo 2
Caching: no computes lo mismo mil veces
Caching es guardar el resultado de algo caro para no volver a calcularlo. Si mil personas piden el mismo dashboard y los números no cambiaron, no tiene sentido armarlo mil veces desde cero: lo calculas una vez, lo cacheas, y lo sirves rápido a todos.
El truco no es cachear todo, es cachear con cabeza: qué guardar, por cuánto tiempo, con qué llave, y —lo que casi siempre se olvida— cuándo borrarlo para que nadie vea datos viejos. Por eso van dos prompts: primero el agente te diseña la estrategia, luego la implementa.
01 · Diséñame una estrategia de caching (sin meter cache a lo loco)
Antes de cachear, decide qué se cachea, por cuánto, con qué llave y —lo más importante— cuándo se invalida. Una caché sin invalidación es un bug esperando a pasar. Este prompt te entrega esa tabla antes de tocar una línea.
(Claude Code o Codex) Contexto: hay cosas que mi app calcula una y otra vez aunque el resultado casi no cambia. Quiero una estrategia de caching clara antes de empezar a meter cache por todos lados. Tarea: 1. Identifica qué se computa o se consulta repetido y es caro: dashboards, agregados, respuestas de APIs externas, páginas que casi no cambian. 2. Para cada candidato decide: ¿se cachea?, ¿por cuánto tiempo (TTL)?, ¿con qué llave?, y ¿cuándo se invalida (qué evento lo deja viejo)? 3. Recomiéndame dónde vive la caché (memoria del proceso, Redis, caché de CDN/HTTP) según el caso. Límites: - No caches datos que cambian al instante ni cosas de un usuario específico sin meterlas en la llave (no quiero servirle a alguien los datos de otro). - Define SIEMPRE cómo se invalida cada caché. Qué quiero de salida: una tabla [qué se cachea · dónde · TTL · llave · cuándo se invalida], antes de tocar código.
02 · Mete caching a lo que se computa una y otra vez
Con la estrategia ya definida, tu agente implementa la caché de punta a punta: computa una vez, guarda, sirve rápido, y deja la invalidación lista. Te enseña el antes y el después para confirmar que sí sirvió.
(Claude Code o Codex)
Contexto: ya tenemos claro qué vale la pena cachear (de la estrategia anterior). Ahora impleméntalo. Uso {Redis / caché en memoria / lo que tenga disponible}.
Tarea:
1. Implementa la caché para {el cálculo o endpoint específico}: computa una vez, guarda con la llave y el TTL que definimos, y sírvela en las siguientes llamadas.
2. Implementa la invalidación: cuando cambie {el dato que lo afecta}, borra o refresca la entrada.
3. Deja un fallback: si la caché falla o está vacía, que recompute sin romper.
Límites:
- No cambies el comportamiento visible: el usuario debe ver lo mismo, solo más rápido.
- Mídelo: enséñame el antes y el después (tiempo de respuesta o consultas a la base) para confirmar que sirvió.
Qué quiero de salida: el código del cache + la invalidación, y una nota de cuánto bajó el tiempo o la carga.05 arreglo 3
Async: que el usuario no espere por correos ni reportes
Cuando alguien hace algo en tu app, espera respuesta ya. Pero hay tareas que tardan: mandar un correo, generar un reporte, procesar una imagen. Si las haces “en vivo” mientras el usuario espera, lo dejas mirando un spinner —y con mil usuarios a la vez, todo se atasca—.
Async (procesamiento asíncrono) es separar eso: en lugar de hacer la tarea pesada en el momento, la mandas a una cola y la procesas en segundo plano. El usuario recibe un “listo, lo estamos preparando” al instante, y el trabajo pesado ocurre por detrás sin trabar a nadie. Dile a tu agente que mueva las operaciones pesadas y, si hace falta, que te arme la cola:
01 · Pasa las operaciones pesadas a segundo plano
Mandar correos, generar reportes o procesar imágenes no debería dejar al usuario mirando un spinner. Este prompt encuentra esas operaciones que hoy corren en vivo y las saca de la petición: respuesta inmediata, trabajo en segundo plano.
(Claude Code o Codex) Contexto: hay operaciones que dejan al usuario esperando: mandar correos, generar reportes o PDFs, procesar imágenes, llamar APIs lentas. Quiero que pasen a procesamiento asíncrono para que la respuesta sea inmediata. Tarea: 1. Encuentra las operaciones pesadas que hoy corren "en vivo" dentro de la petición del usuario. 2. Para cada una, sácala de la petición: encólala como trabajo en segundo plano y responde de inmediato (por ejemplo "tu reporte se está generando, te avisamos"). 3. Maneja el estado: cómo sabe el usuario que ya terminó (notificación, polling o webhook). Límites: - No metas una cola para todo: solo para lo que de verdad tarda o puede fallar y conviene reintentar. - Cada trabajo debe poder reintentarse sin duplicar el efecto (no mandar el mismo correo dos veces). Qué quiero de salida: la lista de operaciones que conviene mover, y la implementación de la primera de punta a punta (encolar → procesar → avisar).
02 · Móntame la cola de trabajos en segundo plano
La infraestructura que hace posible el async: una cola, un worker que procesa fuera de la petición web, reintentos con espera y un lugar donde caen los trabajos que fallaron. Tu agente elige la herramienta estándar de tu stack y te explica por qué.
(Claude Code o Codex)
Contexto: necesito la infraestructura de cola para procesar trabajos en segundo plano. Uso {tu stack: Node, Python, Ruby, ...}. Elige la herramienta estándar para mi stack ({BullMQ, Celery, Sidekiq, lo que aplique}) y explícame por qué.
Tarea:
1. Configura la cola y un worker que procese los trabajos fuera de la petición web.
2. Mete reintentos con espera progresiva y un lugar donde caen los trabajos que fallaron de plano (dead-letter), para no perderlos.
3. Deja un trabajo de ejemplo funcionando de punta a punta para que yo lo copie como molde.
Límites:
- Mantenlo simple: nada de microservicios ni colas extra que no necesito todavía.
- Explícame en lenguaje claro cómo prendo el worker en local y en producción.
Qué quiero de salida: la cola configurada, un worker corriendo, un job de ejemplo y las instrucciones para levantarlo.06 la prueba
Load testing: encuentra los cliffs antes que tus usuarios
Indexing, caching y async arreglan el código. El load testing es lo que comprueba que de verdad sirvió. Es la parte que casi nadie hace, y por eso casi todos se enteran del cliff el día del lanzamiento, en vivo, con usuarios reales mirando.
Load testing es tráfico simulado: en lugar de “lanzamos y vemos qué pasa”, finges mil usuarios entrando al mismo tiempo y mides qué aguanta. La herramienta estándar y open source para esto es k6. Tu agente arma el script, sube la carga poco a poco y te dice exactamente dónde truena —para que truene en la prueba, no en producción—.
Nota: si dejas que tu agente corra la prueba, necesita el servidor arriba (apuntando a staging, no a producción) y la corrida tarda unos minutos. Es normal: está simulando tráfico real.
01 · Móntame load testing con k6
El paso que casi nadie hace. Tu agente arma un script de k6 que pega a tus rutas como un usuario real y sube la carga poco a poco: 10, 100, 500, 1000 usuarios. Con un umbral de qué es aceptable para que la prueba pase o falle sola.
(Claude Code o Codex)
Contexto: quiero correr load testing antes de lanzar para encontrar dónde se cae mi app. Uso k6. Las rutas más importantes son {tu home, login, el endpoint que más se usa, el checkout, ...}.
Tarea:
1. Crea un script de k6 que pegue a esas rutas como lo haría un usuario real (no solo el home: el flujo completo).
2. Configura escenarios que suban la carga poco a poco: 10, 100, 500 y 1000 usuarios simultáneos.
3. Define qué es "aceptable" (por ejemplo: 95% de las respuestas por debajo de 500 ms, 0% de errores) para que la prueba pase o falle sola.
Límites:
- Apunta SIEMPRE a un entorno de pruebas o staging, nunca a producción con usuarios reales encima.
- Usa datos realistas (cuentas de prueba para el login, búsquedas variadas, no siempre la misma).
Qué quiero de salida: el script de k6 listo, el comando para correrlo y cómo leo el reporte.02 · Simula mil usuarios y dime exactamente dónde truena
Que truene en la prueba, no en producción. Esta corrida sube hasta mil usuarios simultáneos y te dice a cuántos empieza a degradarse, qué recurso se satura primero y —clave— qué arreglo de los cuatro lo resuelve.
(Claude Code o Codex)
Contexto: ya tengo el script de k6. Ahora quiero la corrida y el diagnóstico. Mi app vive en {tu hosting: Vercel, AWS, Railway, ...} y la base de datos en {Postgres en ...}.
Tarea:
1. Corre la prueba subiendo hasta 1000 usuarios simultáneos.
2. Encuentra el punto donde empieza a degradarse: a cuántos usuarios suben los tiempos, dónde aparecen errores, qué recurso se satura primero (base de datos, CPU, memoria, conexiones).
3. Relaciona cada cuello de botella con un arreglo concreto: ¿es falta de índice?, ¿falta de caché?, ¿algo pesado que debería ser async?, ¿pocas conexiones a la base?
Límites:
- No me des solo el número final: quiero saber QUÉ se rompió primero y por qué.
- Si tú corres la prueba, recuérdame tener el server arriba; la corrida tarda unos minutos.
Qué quiero de salida: el reporte de la corrida, el cliff (a cuántos usuarios truena), el recurso que se satura y la lista de arreglos en orden de impacto.07 paso a paso
Checklist: qué revisar antes de lanzar
Esta es la lista que el video no alcanza a dar. Antes de abrir tu app al mundo, recórrela de arriba a abajo: cada punto que no puedas marcar es un cliff esperándote. Al lado de cada uno está el pilar (y su prompt) que lo resuelve.
- 01
Las queries de tus pantallas más usadas tienen índice por las columnas que filtran u ordenan.
Indexing - 02
Ya no hay SELECT * ni listas sin paginación en el código caliente.
Indexing - 03
Revisaste que no haya N+1 (consultas dentro de loops o renders de listas).
Indexing - 04
Lo que se computa una y otra vez sin cambiar (dashboards, agregados) está cacheado.
Caching - 05
Cada caché tiene definido cuándo se invalida; ninguna sirve datos viejos.
Caching - 06
Las operaciones pesadas (correos, reportes, exports) no bloquean al usuario.
Async - 07
Tienes una cola con reintentos y un lugar donde caen los trabajos que fallan.
Async - 08
Corriste load testing con datos realistas (cien mil filas, no diez) apuntando a staging.
Load testing - 09
Sabes a cuántos usuarios truena tu app y qué recurso se satura primero.
Load testing - 10
Repetiste el load test después de los arreglos y el cliff se movió más arriba.
Load testing
Si marcaste las diez, tu app no nada más funciona: aguanta. Y lo mejor es que no escribiste una línea de código para lograrlo, solo le diste los prompts correctos a tu agente.
08 dudas
Preguntas rápidas
¿Necesito saber programar para usar esto?
No. Le pegas los prompts a tu agente, él recorre el código y hace los cambios; tú revisas que tengan sentido y pruebas que la app siga funcionando. Lo importante es entender el qué (índice, caché, async), no escribir el cómo.
¿Funciona con cualquier base de datos?
Sí. Los ejemplos asumen PostgreSQL porque es lo más común, pero el mismo prompt aplica a MySQL, SQLite o lo que uses: solo rellena la {llave} con tu base de datos y el agente se adapta.
¿Claude o Codex?
Los dos. Los prompts son agnósticos: están escritos para que funcionen igual en Claude Code o en Codex. Usa el que ya tengas abierto y pégalos tal cual.
¿Esto lo hago antes o después de construir la app?
Sobre lo ya construido, justo antes de lanzar o cuando empieces a sentir que se arrastra. No optimices de más al principio: primero que funcione, luego que aguante. Pero no lo dejes para el día que ya tienes mil usuarios encima.
¿Cuántos usuarios va a aguantar mi app entonces?
Eso te lo dice el load test, no la intuición. Por eso es el paso que cierra todo: simulas la carga, ves dónde truena, arreglas y vuelves a probar. El número real sale de la prueba, no de adivinar.
Guía de la comunidad
Esta entrada es el pack de prompts que prometí en el video del scaling cliff: las tres cosas que le dices a tu agente para que tu app aguante a escala —indexing, caching y async— más el load testing que casi nadie hace. La guía vive en la bóveda de tododeia. Si algo cambia en las herramientas, aquí abajo está la fuente de verdad.
Documentación de k6 (load testing)
La herramienta open source para simular tráfico real. Aquí está el reference de scripts, escenarios y métricas para montar tu primera prueba de carga.
Índices en PostgreSQL (docs oficiales)
Qué es un índice, cuándo ayuda y cuándo estorba. La fuente de verdad cuando tu agente te proponga meter indexing y quieras entender qué hizo.
EXPLAIN ANALYZE — encuentra la query lenta
El comando que te dice exactamente cuánto tarda una consulta y por qué. Es lo que tu agente usa por debajo para cazar los cuellos de botella.
Caché con Redis
El almacén en memoria más usado para cachear: computas una vez, lo guardas aquí y lo sirves rápido. Útil cuando aterrizas la estrategia de caching.
Comandos de Claude Code
Para manejar a tu agente como pro mientras arregla el código
3 errores con IA
Los tropiezos típicos al construir apps con inteligencia artificial
5 skills clave
Las skills que todo el que construye con Claude debería tener
¿Por dónde empezar hoy?
Prende tu agente en la carpeta de tu proyecto y copia el prompt de arranque para que te dé el mapa de tus cuatro riesgos. Con esa lista en mano, ataca el primero con el Pilar 1 (indexing) y baja por la guía. Antes de lanzar, no te saltes el checklist.