Cuota

Datos Y Formatos Security Notes Jan 9, 2025 JAVASCRIPT
limits usage billing resource-management

Definition

Una cuota es un límite duro en la cantidad total de recursos que puedes consumir de una API dentro de un período de tiempo definido - típicamente medido en solicitudes por día, capacidad de almacenamiento, horas de cómputo o transferencia de datos. A diferencia del rate limiting (que controla qué tan rápido haces solicitudes), las cuotas controlan cuánto puedes usar en total. Piensa en rate limiting como límites de velocidad en una autopista, mientras que las cuotas son el total de millas que puedes conducir este mes.

Las cuotas sirven múltiples propósitos empresariales y técnicos. Previenen el agotamiento de recursos (un usuario no puede consumir toda la capacidad disponible), habilitan modelos de precios escalonados (usuarios gratuitos obtienen 1,000 solicitudes/día, usuarios premium obtienen 1 millón), y hacen los costos predecibles tanto para proveedores como consumidores. Cuando llegas a tu cuota, se acabó hasta el siguiente período de reinicio - no hay encolamiento ni throttling, solo una parada dura.

La distinción clave: rate limiting protege la estabilidad del sistema en tiempo real (previniendo caídas del servidor), mientras que las cuotas protegen la asignación de recursos a largo plazo y habilitan modelos de negocio. Podrías tener un rate limit de 100 solicitudes por segundo pero una cuota de 1 millón de solicitudes por mes. Puedes hacer ráfagas rápidas (dentro de los límites de tasa) pero no puedes exceder tu asignación total.

Example

API de Google Maps: El tier gratuito incluye 28,000 cargas de mapas por mes. Una vez que llegas a 28,000, todas las solicitudes subsiguientes retornan un error hasta el próximo mes. Esta cuota previene facturas inesperadas y asegura que la infraestructura de Google se distribuya equitativamente entre clientes.

AWS Lambda: Podrías tener una cuota de 1,000 ejecuciones concurrentes y 75 GB de almacenamiento total de código. Intentar desplegar un 76º GB falla inmediatamente. La cuota asegura que AWS puede planificar capacidad y previene costos desbocados.

API de OpenAI: GPT-4 podría tener una cuota de $100 de crédito por mes en una cuenta gratuita. Cada solicitud consume tokens (cuesta dinero), y cuando llegas a $100, las solicitudes fallan hasta que actualices o llegue el próximo mes. Esto te protege (de facturas sorpresa) y a OpenAI (del abuso).

API de GitHub: Usuarios autenticados obtienen 5,000 solicitudes por hora. Después de 5,000, recibes 403 Forbidden con un mensaje indicando cuándo se reinicia tu cuota. Esto es tanto un rate limit (ventana horaria) como una cuota (tope duro en solicitudes totales).

API de Stripe: Planes gratuitos podrían tener una cuota de 100 transacciones de modo de prueba por día. Una vez que llegas a 100, no puedes crear más cargos de prueba hasta mañana. Esto previene abuso de infraestructura de prueba gratuita.

Almacenamiento en la Nube: Dropbox te da 2 GB de cuota de almacenamiento gratis. Puedes subir archivos tan rápido como quieras (rate limit), pero una vez que llegas a 2 GB, las subidas fallan hasta que borres archivos o actualices.

Analogy

El Plan de Datos del Teléfono Celular: Tienes 10 GB de datos por mes. Puedes usarlos tan rápido como permita tu conexión LTE (rate limiting), pero una vez que llegas a 10 GB, o te reducen a velocidades 2G o te cortan completamente (cuota excedida). El próximo mes, tu cuota se reinicia a 10 GB.

La Membresía del Gimnasio: Un gimnasio económico podría limitarte a 50 visitas por mes. Puedes ir cada día (tasa: 1 visita/día), pero después de 50 visitas, estás bloqueado hasta el próximo mes. La cuota protege al gimnasio del hacinamiento mientras ofrece precios asequibles.

El Buffet Todo-Lo-Que-Puedas-Comer con un Giro: Imagina un buffet que te permite visitarlo 5 veces por hora (rate limit) pero tiene una cuota total de 20 platos por día. Puedes cargar rápido dentro de los límites de tasa, pero después de 20 platos, terminaste sin importar el tiempo que quede.

El Saldo de Tiempo Libre Pagado (PTO): Acumulas 15 días de vacaciones por año (tu cuota). Puedes tomarlos cuando quieras dentro de la política de la empresa (límites de tasa en días consecutivos libres), pero una vez que has usado los 15, no puedes tomar más hasta el próximo año cuando tu cuota se reinicie.

Code Example

// Rastreo de cuota del lado del servidor con Redis
import Redis from 'ioredis';
const redis = new Redis();

async function checkQuota(userId, quotaLimit, windowSeconds) {
  const key = `quota:${userId}:${Math.floor(Date.now() / 1000 / windowSeconds)}`;
  const currentUsage = await redis.get(key);

  if (currentUsage && parseInt(currentUsage) >= quotaLimit) {
    // Cuota excedida
    const ttl = await redis.ttl(key);
    return {
      allowed: false,
      remaining: 0,
      resetIn: ttl,
      message: `Cuota excedida. Se reinicia en ${ttl} segundos.`
    };
  }

  // Incrementar uso
  const newUsage = await redis.incr(key);

  // Establecer expiración en primer uso
  if (newUsage === 1) {
    await redis.expire(key, windowSeconds);
  }

  return {
    allowed: true,
    remaining: quotaLimit - newUsage,
    resetIn: await redis.ttl(key),
    usage: newUsage
  };
}

// Middleware Express.js
async function quotaMiddleware(req, res, next) {
  const userId = req.user?.id || req.ip;
  const userTier = req.user?.tier || 'free';

  // Diferentes cuotas por tier
  const quotas = {
    free: { limit: 1000, window: 86400 },    // 1,000/día
    pro: { limit: 100000, window: 86400 },   // 100,000/día
    enterprise: { limit: 10000000, window: 86400 } // 10M/día
  };

  const { limit, window } = quotas[userTier];
  const result = await checkQuota(userId, limit, window);

  // Establecer headers de cuota
  res.setHeader('X-Quota-Limit', limit);
  res.setHeader('X-Quota-Remaining', result.remaining);
  res.setHeader('X-Quota-Reset', Date.now() + (result.resetIn * 1000));

  if (!result.allowed) {
    return res.status(429).json({
      error: 'quota_exceeded',
      message: result.message,
      limit: limit,
      resetAt: new Date(Date.now() + result.resetIn * 1000).toISOString()
    });
  }

  next();
}

// Uso
app.use(quotaMiddleware);

app.get('/api/data', async (req, res) => {
  // Este endpoint está protegido por cuota
  res.json({ data: 'Your data' });
});

Diagram

graph TB
    subgraph User["Usuario / Cliente API"]
        U[Hace Solicitudes API]
    end

    subgraph Gateway["API Gateway / Middleware"]
        Q[Verificador de Cuota]
        T[Detección de Tier]
        R[Redis / BD]
    end

    subgraph Quotas["Tiers de Cuota"]
        F["Tier Gratuito
1,000 req/día"] P["Tier Pro
100,000 req/día"] E["Enterprise
10,000,000 req/día"] end subgraph Backend["API Backend"] B[Procesar Solicitud] D[(Base de Datos)] end U -->|Solicitud + API Key| Q Q --> T T -.Verificar Tier.-> F T -.Verificar Tier.-> P T -.Verificar Tier.-> E Q -->|Verificar Uso| R R -->|Actual: 850/1000| Q Q -->|Bajo Cuota| B Q -->|Cuota Excedida| X[429 Quota Exceeded
X-Quota-Reset: timestamp] B --> D B -->|Éxito + Headers
X-Quota-Remaining: 149| U style Q fill:#ffe6e6 style R fill:#e6f3ff style X fill:#ffcccc style F fill:#f0f0f0 style P fill:#e6ffe6 style E fill:#e6e6ff

Security Notes

SECURITY NOTES

CRÍTICO - …

Configuración y Validación:

  • Las cuotas son esenciales para prevenir ataques de agotamiento de recursos y costos desbocados.
  • Siempre aplicar cuotas del lado del servidor; nunca confiar en uso reportado por el cliente.
  • Implementar cuotas en múltiples niveles: por usuario, por API key, por organización y global.
  • Rastrear uso de cuota en almacenamiento persistente (base de datos o Redis) para sobrevivir reinicios del servidor.
  • Registrar violaciones de cuota para detectar patrones de abuso.

Monitoreo y Protección:

  • Usar ventanas deslizantes para cuotas para prevenir abuso de ráfaga en límites de ventana.
  • Implementar alertas basadas en cuota para detectar patrones de consumo inusuales.
  • Proveer rutas claras de actualización cuando usuarios llegan a cuotas legítimamente.
  • Nunca exponer detalles de implementación de cuota (claves de almacenamiento, algoritmos) en mensajes de error.
  • Considerar implementar cuotas suaves (advertencias al 80%) antes de cuotas duras (bloqueo al 100%).
  • Proteger endpoints de verificación de cuota del abuso con rate limiting.

Best Practices

  1. Cuotas Escalonadas: Ofrecer múltiples niveles de suscripción con diferentes cuotas (gratuito, pro, enterprise). Esto habilita crecimiento del negocio mientras protege recursos del tier gratuito.

  2. Comunicación Clara: Mostrar a usuarios su uso actual y cuota restante en respuestas de API y dashboards. A nadie le gustan errores de cuota sorpresa.

  3. Degradación Elegante: Al acercarse a límites de cuota, advertir a usuarios por adelantado (ej., “Has usado el 90% de tu cuota”) en lugar de bloquear abruptamente al 100%.

  4. Headers de Cuota: Incluir información de cuota en cada respuesta de API:

    • X-Quota-Limit: Cuota total
    • X-Quota-Remaining: Cuota restante
    • X-Quota-Reset: Cuándo se reinicia la cuota (timestamp Unix)
  5. Ventanas Deslizantes: Usar cuotas de ventana deslizante (últimos 30 días) en lugar de meses calendario fijos para prevenir abuso de límites (usuarios maximizando en día 30, luego de nuevo en día 1).

  6. Cuotas Granulares: Diferentes operaciones tienen diferentes costos. Aplicar cuotas separadas para operaciones costosas (llamadas a modelos de IA, procesamiento de video) vs. baratas (obtener datos en caché).

  7. Permiso de Ráfaga: Considerar permitir ráfagas cortas por encima de la cuota si el promedio está bajo cuota. Esto suaviza patrones de uso picos.

  8. Arrastre de Cuota: Para tiers pagados, considerar permitir que la cuota no utilizada se traslade al próximo período (hasta un límite) para aumentar satisfacción del cliente.

Common Mistakes

Sin Visibilidad de Cuota: Los usuarios no deberían tener que adivinar su estado de cuota. Siempre exponer uso actual en respuestas de API y proveer un dashboard.

Ventanas de Calendario Fijas: Reiniciar cuotas a medianoche del 1º crea un exploit - usuarios pueden maximizar el último día del mes y de nuevo el primer día.

Sin Límites Suaves: Bloquear usuarios exactamente al 100% de la cuota sin advertencia crea mala UX. Advertir al 80% y 90%.

Rastreo de Cuota del Lado del Cliente: Nunca confiar en que clientes rastreen su propio uso de cuota. Los clientes maliciosos mentirán.

Cuota Por Solicitud en Lugar de Recurso: Contar solicitudes es fácil pero injusto. Descargar 1 KB no debería contar igual que procesar un video de 5 GB.

Sin Persistencia de Cuota: Almacenar cuota en memoria significa que los reinicios del servidor resetean el uso. Siempre usar almacenamiento persistente (BD, Redis).

Cuotas Idénticas para Todos los Usuarios: Usuarios gratuitos y clientes enterprise no deberían compartir la misma cuota. Implementar cuotas escalonadas basadas en nivel de suscripción.

Sin Ruta de Actualización: Cuando usuarios legítimos llegan a cuotas, ofrecer una ruta clara para actualizar. De lo contrario, encontrarán un competidor.

Cuota en Autenticación: Tener cuidado al aplicar cuotas a endpoints de login/signup. Demasiado restrictivo y usuarios legítimos no pueden acceder a tu servicio.

Standards & RFCs

Standards & RFCs
2)- IETF draft-ietf-httpapi-ratelimit-headers - RateLimit Header Fields for HTTP
4)- [OpenAPI](https://reference.apios.info/es/terms/openapi/) Specification - Documenting quota limits in API specs