La capacidad útil es el trabajo que termina dentro del contrato de latencia y corrección. Aceptar todas las solicitudes y responder cuando el cliente ya abandonó puede consumir más recursos sin prestar más servicio. Backpressure comunica presión hacia el productor; la admisión decide qué trabajo puede entrar.
El punto de partida es medir el cuello de botella y distinguir lecturas, reservas, cobros y procesos de fondo. Una única cifra de RPS no describe sus costes ni su prioridad.
Un presupuesto con unidades
Supóngase un pico hipotético de boletaje: doce mil lecturas de catálogo y dos mil solicitudes de reserva por segundo. No es capacidad de ningún proveedor. Si se admite un flujo estable de quinientas reservas por segundo y cada una ocupa, en promedio, doscientos milisegundos dentro de una frontera medida, habrá unas cien reservas en curso en esa frontera.
El cálculo es tasa por tiempo: 500/s × 0.2s = 100. La relación sirve para promedios de un sistema estable con límites bien definidos. No transforma el p99 en concurrencia exacta ni demuestra que la base soporte esa carga. Un benchmark con distribución de datos, locks, escrituras y fallos reales valida el presupuesto.
La capacidad se prepara con margen antes del pico. El tiempo de arrancar instancias, llenar cachés y establecer conexiones también importa.
Admitir antes de saturar
Se aplica un límite de trabajo concurrente o tasa que respete las dependencias. La política puede asignar presupuestos por ruta y actor, priorizar confirmaciones sobre exploración y preservar una cuota para recuperación. Rechazar pronto puede mantener más trabajo útil que acumular espera indefinida.
Un Rate Limiter controla una dimensión de consumo; no reemplaza necesariamente la admisión por concurrencia. Un trabajo largo y otro corto pueden ocupar el mismo número de requests con costes distintos.
La respuesta comunica si el cliente puede volver a intentar y con qué contrato. No ofrece un plazo exacto si el servidor no lo conoce. Clientes y SDKs deben respetar el presupuesto, sin convertir un rechazo en una avalancha inmediata de nuevos intentos.
Colas finitas y edad del trabajo
Una cola absorbe una diferencia temporal entre entrada y finalización. Si la entrada supera sostenidamente la salida, crece hasta alcanzar un límite o perder utilidad. La cantidad de mensajes, bytes y edad representan restricciones distintas.
Como ejemplo hipotético, entrada de tres mil tareas por segundo y finalización de dos mil durante sesenta segundos agregan sesenta mil tareas. Si después entran mil por segundo y la finalización mantiene dos mil, el drenaje ideal tarda otros sesenta segundos. Reintentos, costes variables y pausas alteran ese cálculo.
Message Queues necesita políticas para capacidad, vencimiento, duplicados y recuperación. Una cola no garantiza que un hold siga vigente al procesarlo. Antes del efecto se valida otra vez su autoridad y plazo.
Una frontera de presión explícita
El diagrama separa esperar de conceder una operación. La cola virtual representa admisión y no posee el inventario.
--- config: look: handDrawn --- flowchart TD incoming["Pico de solicitudes"] --> admission["Admisión<br/>Presupuesto por ruta y actor"] admission -->|"Capacidad disponible"| workers["Trabajo concurrente acotado"] admission -->|"Espera aceptable"| queue["Cola finita<br/>Edad y plazo"] admission -->|"Presupuesto agotado"| reject["Rechazo temprano<br/>Reintento acotado"] queue --> workers workers --> database["Base autoritativa<br/>Capacidad medida"] database -->|"Latencia, carga y errores"| admission
La señal de carga puede reducir admisión, pero el controlador también necesita estabilidad: umbrales, ventanas y recuperación gradual acordes a la medición. Oscilar entre abrir todo y cerrar todo traslada la inestabilidad al cliente.
Conexiones no equivalen a capacidad SQL
El presupuesto considera la suma de pools de todas las instancias. Diez pods con máximo de veinte conexiones pueden pedir doscientas, además de workers, administración y otros servicios. Son máximos configurados del ejemplo; no justifican crear esa cantidad sin medir actividad y límites del motor.
Un pool reutiliza conexiones y puede acotar espera. RDS Proxy puede agrupar conexiones, encolar o rechazar según límites, pero no añade CPU, I/O ni elimina contención de locks en PostgreSQL. Estado de sesión y pinning pueden reducir la reutilización efectiva.
Aumentar pods o pools mientras la base ya está saturada puede empeorar el problema. Consultas, índices y transacciones cortas se revisan antes de distribuir más carga. Sharding es otra decisión con costes, no una respuesta automática a cualquier pico.
Fallos, reintentos y equidad
Un timeout no libera inmediatamente todo el trabajo remoto. Si cada capa reintenta, una petición puede convertirse en muchas operaciones. Backoff con jitter, límites de intentos y una única capa responsable cuando sea viable reducen amplificación, sin sustituir idempotencia.
Cuando Redis o una caché fallan, un fallback ilimitado puede enviar todo el pico a la base. Caching requiere un presupuesto de degradación. Algunas lecturas admiten datos viejos; una reserva firme sigue validándose en su autoridad.
La equidad necesita una identidad y una política: límites por actor, protección contra acaparamiento y capacidad para usuarios nuevos o recuperación. FIFO no demuestra equidad si un único productor ocupa casi toda la cola.
Verificar trabajo útil
La prueba reproduce ráfagas, una dependencia lenta, caché fría y reintentos concurrentes. Mide operaciones completadas a tiempo, rechazos, edad de cola, conexiones activas, contención y latencia p95/p99 por ruta.
El sistema de boletaje debe conservar una sola venta válida incluso al rechazar o demorar trabajo. Un buen resultado mantiene invariantes y recuperación observables; una gráfica de RPS alta con clientes expirados no demuestra disponibilidad útil.
Referencias: load shedding para evitar sobrecarga, presupuestos de reintentos y capacidades de RDS Proxy.