Cómo limitar el uso de la IA en tu app para no pagar de más
Cómo poner límites por usuario, topes de tokens y un presupuesto global a las funciones con IA de tu app, dónde aplicarlos y qué mostrar al usuario.
Read in English →
Para que un solo usuario no dispare tu factura de IA, aplica los límites en tu servidor y por usuario con sesión: un tope de peticiones por minuto, una cuota diaria o mensual de peticiones o tokens, un tamaño máximo para cada prompt y cada respuesta, y un presupuesto global que apague la función antes de llegar al límite del proveedor. Los límites que solo existen en el navegador, o solo en el panel del proveedor, no te protegen: el primero se salta fácil y el segundo corta a todos a la vez.
En esta guía verás qué límites importan, dónde va cada uno, una forma simple de contar el uso en una base de datos Postgres como Supabase y cómo avisarle al usuario sin que parezca que la función está rota.
¿Por qué las funciones con IA necesitan sus propios límites?
Una petición normal casi no te cuesta nada. Una llamada a un modelo de IA cuesta dinero cada vez, y el precio crece con lo largo de la entrada y de la respuesta. Eso cambia el riesgo. Un script que aprieta tu botón de "resumir" en bucle, un usuario que pega un libro entero en la caja o un error de tu propio frontend que reintenta sin parar pueden generar una factura en pocas horas.
OWASP lo incluye como "Unbounded Consumption" (consumo sin límites) en su Top 10 para aplicaciones con modelos de lenguaje: dejar que los usuarios provoquen un uso caro y sin control del modelo. También es un problema de seguridad, porque es la forma más barata de dañar a un negocio pequeño: hacerlo pagar.
¿Qué límites conviene poner?
Piensa en capas. Cada una atrapa algo que las otras dejan pasar.
| Límite | Qué evita | Forma típica |
|---|---|---|
| Exigir sesión | Scripts anónimos usando tu función | Rechazar peticiones sin sesión válida |
| Peticiones por minuto por usuario | Bucles, doble clic, reintentos en cadena | Un número pequeño por minuto |
| Cuota diaria o mensual por usuario | Una cuenta que gasta mucho más que su plan | Peticiones o tokens por período, según plan |
| Tope de entrada | Textos enormes que encarecen cada llamada | Máximo de caracteres o tokens aceptados |
| Tope de salida | Respuestas larguísimas | El parámetro de máximo de tokens de salida del modelo |
| Concurrencia por usuario | Muchas llamadas en paralelo | Una o dos en curso por usuario |
| Presupuesto global | Todo a la vez, incluidos tus errores | Apagar la función cerca de un gasto diario |
| Límite estricto del proveedor | La última barrera si todo falla | Tope mensual en el panel del proveedor |
Los números dependen de tus márgenes. Parte de lo que vale para ti un usuario de cada plan al mes y calcula cuántas llamadas paga eso. Si cobras por uso, en cobro por uso con Stripe vemos cómo medirlo del lado de la facturación.
¿Dónde se aplican los límites?
En el servidor, en la misma función que guarda la clave de IA y hace la llamada. El navegador puede mostrar un contador, pero no puedes confiar en que lo respete: cualquiera puede llamar a tu endpoint directamente.
El orden dentro de esa función importa:
- Verifica la sesión y toma el ID del usuario de ella, nunca del cuerpo de la petición.
- Revisa el límite por minuto y la cuota. Si alguno se pasó, termina ahí.
- Revisa el tamaño de la entrada. Recházala o recórtala antes de pagar por ella.
- Llama al proveedor con un máximo de salida explícito.
- Registra lo que se usó (peticiones, y tokens si el proveedor los devuelve).
Si la clave de IA todavía está en tu frontend, arregla eso primero: un límite en tu función no sirve de nada si la clave se puede usar sin pasar por ella. Lo explicamos en clave de API expuesta en el frontend.
¿Cómo cuento el uso de cada usuario?
Necesitas un contador que cada llamada actualice sin errores, aunque lleguen dos peticiones en el mismo instante. Hay dos opciones comunes:
- Un almacén tipo Redis, como Upstash, que trae ayudas listas para limitar peticiones y es rápido para ventanas por minuto. La documentación de Supabase tiene un ejemplo de rate limiting en Edge Functions con Upstash Redis.
- Una tabla en tu propia base de datos. Más lenta que Redis pero sencilla, y suficiente para cuotas diarias o mensuales.
Una cuota diaria mínima en Postgres se ve así:
create table public.ai_usage (
user_id uuid not null references auth.users (id) on delete cascade,
day date not null default current_date,
requests int not null default 0,
primary key (user_id, day)
);
alter table public.ai_usage enable row level security;
-- Sin políticas: solo el código del servidor con la clave secreta usa esta tabla.
Tu función de servidor suma y lee el contador en una sola sentencia, para que dos llamadas simultáneas no puedan colarse las dos por debajo del límite:
insert into public.ai_usage (user_id, day, requests)
values ($1, current_date, 1)
on conflict (user_id, day)
do update set requests = public.ai_usage.requests + 1
returning requests;
Si el número devuelto supera lo que el usuario tiene permitido por día, responde con un error en lugar de llamar al modelo. Agrega una columna tokens si prefieres limitar por costo y no por cantidad.
¿Qué ve el usuario cuando llega al límite?
Un mensaje claro, no un error genérico. Responde desde tu función con el estado HTTP 429 Too Many Requests, con un encabezado Retry-After para los límites de corto plazo, y muestra algo concreto:
- Para el límite por minuto: "Vas un poco rápido. Prueba otra vez en unos segundos".
- Para la cuota diaria o mensual: cuánto usó, cuándo se reinicia y, si vendes planes, qué incluye el siguiente.
Muestra lo que le queda antes de que se acabe. Una línea como "te quedan 12 de 50 hoy" evita la mayoría de los correos a soporte. Las cuotas por plan combinan bien con revisar el plan en el servidor, que vemos en limitar funciones por plan en un SaaS.
¿Cómo pongo un interruptor general de seguridad?
Los límites por usuario no ayudan si hay un error en tu código o si alguien crea muchas cuentas nuevas para aprovechar la cuota gratis. Agrega un control más antes de cada llamada: el gasto total del día (o los tokens totales) sumando a todos los usuarios. Cuando pase el umbral que elijas, apaga la función para los usuarios gratis, o para todos, y mándate una alerta.
Detrás de eso, pon un límite mensual estricto en el panel del proveedor. Es una herramienta tosca, porque corta todo el tráfico de IA de golpe, así que tómalo como la última barrera, no como el plan. La parte de costos (caché, modelos más baratos, prompts más cortos) está en controlar el costo de la IA en tu app.
¿Cómo pruebo que los límites funcionan?
- Llama a la función sin sesión: debe negarse.
- Llámala muchas veces seguidas desde una cuenta: debe saltar el límite por minuto.
- En un entorno de pruebas, baja tu propia cuota a un número pequeño y agótala.
- Manda una entrada más grande que el tope y confirma que se rechaza antes de llamar al proveedor.
- Después de las pruebas, revisa la página de uso del proveedor para confirmar que las llamadas rechazadas no costaron nada.
Respuestas rápidas
¿Basta con el límite de gasto del proveedor? No. Protege tu bolsillo, pero apaga la función para todos a la vez, incluidos tus clientes que pagan.
¿Los visitantes sin cuenta deberían usar la IA? Solo con un límite muy pequeño por IP y un CAPTCHA, o directamente no. Las cuentas hacen que los límites se puedan aplicar.
¿Limito peticiones o tokens? Las peticiones son más fáciles de explicar al usuario. Los tokens se parecen más a tus costos. Muchas apps limitan peticiones por minuto y tokens por mes.
¿Mi herramienta de IA puede agregarlo? Puede escribir el código, pero revisa que el límite corra en el servidor, antes de la llamada a la IA, y que use el ID del usuario que viene de la sesión.
¿Quieres que alguien más lo revise?
El chequeo de salud gratis muestra lo que tu app publicada expone desde afuera. Si quieres que una persona revise cómo están protegidos tus endpoints de IA y agregue los límites, eso entra en nuestros planes de mantenimiento o en una revisión de seguridad de Supabase; también puedes preguntarnos directamente.


