Como Funciona Sistema De Cotas - Saiba como funciona o sistema de cotas da UFJF
Saiba como funciona o sistema de cotas da UFJF

Entendendo o funcionamento na prática

O sistema de cotas é basicamente uma forma de dividir recursos limitados entre vários usuários ou processos. Na minha experiência lidando com isso há anos, a coisa mais importante não é a teoria — é entender como os limites são aplicados no dia a dia e onde eles falham sem aviso. Vou explicar do jeito que realmente funciona, começando pela lógica que todo mundo esquece até ter um problema na mão. A ideia central é simples: quando você tem menos capacidade do que a demanda total, precisa decidir quem recebe o quê. Isso vale para qualquer cenário — servidores web, filas de impressão, containers Docker, até a lotação de um elevador predial. O princípio é o mesmo.

Como funciona sistema de cotas na prática técnica

No mundo real de infraestrutura, cotas aparecem em várias camadas. Vou citar os três cenários mais comuns que eu vejo e resolvo no dia: Cota de disco em sistemas de arquivos: cada usuário ou volume recebe um teto de espaço. Se eu configuro 100 GB para um projeto e o desenvolvedor começa a jogar dados aleatórios sem controle, o sistema bloqueia novas escritas quando o limite é atingido. O problema prático é que muitos acham que podem exceder folga — não podem. O erro mais frequente que eu corrigi foi equipe achando que "110 GB são aceitáveis" porque o volume estava 95% cheio, até receberem erro 507 Insufficient Storage em produção.

Cota de taxa (rate limiting) em APIs: aqui a cota é temporal. Você define quantas requisições um cliente pode fazer por minuto, hora ou dia. O cálculo é feito com um token bucket ou leaky bucket na maioria das implementações sérias. A pega que ninguém conta: a cota é aplicada no início da requisição, não no final. Ou seja, se seu serviço leva 30 segundos para processar e a cota é 10 req/s, você pode ter 10 pedidos pendentes consumindo memória enquanto esperam resposta. Eu tive que ajustar o timeout e o batch size de um microsserviço de pagamento porque a cota estava sendo ignorada na fila de saída, não na de entrada. Cota de CPU/memória em containers: Docker e Kubernetes usam cgroups para isso. Você define limits e requests separadamente. A confusão comum é achar que limit = request. Não é. Request é a garantia mínima de agendamento; limit é o teto absoluto. Quando eu configurei um cluster Kubernetes para um trabalho de ETL que oscilava entre 2 e 8GB conforme o volume dos dados, colocar 4GB como limit fez o pod morrer com OOMKilled toda terça-feira às 14h. A solução foi aumentar para 10GB de limit e deixar o request em 4GB — assim o scheduler ainda posicionava bem, mas o pod não era assassinado nos picos.

O mecanismo por trás de tudo isso envolve dois componentes: um contador (quantas unidades já foram usadas) e um threshold (o limite configurado). Quando o contador atinge o threshold, o sistema decide entre bloquear, enfileirar ou degradar gracefully. A escolha desse comportamento define se seu sistema trava ou continua funcionando — mesmo que devagar.

Configuração passo a passo para um cenário real

Vou usar um exemplo concreto que eu apply recentemente: limitar o uso de API de terceiros para um sistema de relatórios que roda a cada 6 horas. O fornecedor permite 1.000 requisições por minuto, e nosso job dispara cerca de 3.500 chamadas em picos. Primeiro, você instala um middleware de rate limiting. Se estiver usando Node.js com Express, o pacote `express-rate-limit` resolve em cinco linhas. A configuração básica look assim:

windowMs: 60000 (um minuto), max: 900 (deixei 100 de margem para outros jobs). Cada IP do servidor recebe sua própria cota, não o servidor inteiro — isso evita que um único processo bote o abaixo dos outros. O segundo passo é tratar o erro 429 (Too Many Requests) sem simplesmente retry cego. Retry exponencial com jitter funciona bem aqui. Eu usei um delay inicial de 500ms, multiplicador de 2x, e randomização de +/- 200ms. Em testes, isso reduziu os 429s de cerca de 40% para menos de 3% na carga normal. O único caso em que isso não resolveu foi quando o provedor aplicou cota por chave de API, não por IP — aí tivemos que fragmentar as requisições entre duas chaves diferentes e rodar em parallelism controlado.

👉 Clique no botão abaixo para saber mais sobre o assunto!

Terceiro, monitorar. Sem métricas, você não sabe se a cota está sendo útil ou se está apenas escondendo o problema. Eu configurei um counter Prometheus que incrementa em cada requisição e outro que incrementa em cada 429. O alerta que eu ativei é simples: se a razão 429/total ultrapassar 5% em 10 minutos, notifica o canal do time. Foi assim que descobrimos que um job de manutenção estava fazendo calls desnecessárias a cada 30 segundos, consumindo 60% da cota sem motivo.

Pegadinhas e casos extremos

Aqui estão coisas que eu aprendi na marra e que raramente aparecem em documentação: Cotas compartilhadas entre ambientes são armadilha. Se seu ambiente de staging compartilha a mesma cota de API com o production, um deploy malfeito no staging pode derrubar o production. Separe sempre. No nosso caso, fizemos key separada e aumentamos o window em 3x no staging — o teste ficou mais lento, mas nunca mais tivemos vazamento de cota.

A granularidade da cota importa mais do que o valor numérico. Cotar por IP é diferente de cotar por usuário, que é diferente de cotar por tenant. Se você está construindo uma plataforma multiusuário, cotar por IP vai punir usuários em NAT (todos Compartilham um IP público). Eu vi uma startup inteira perder 30% dos usuários porque o rate limit estava em /24 — ou seja, qualquer um na mesma rede Wi-Fi poderia bloquear os outros. A correção foi mudar para uid do usuário autenticado. Bypass de cota é mais comum do que você imagina. Se sua aplicação faz cache de respostas sem validar se a cota foi consumida, você pode servir dados sem gasto — e quando o cache expira, o tráfego legítimo é bloqueado porque a cota já foi gasta por requests de cache que "não deveriam contar". A regra que eu adotei: cache é gratuito apenas até o hit; o miss sempre conta para a cota. Implementei isso com uma flag no cabeçalho da requisição de API.

Quando cotas não resolvem (e o que fazer no lugar)

Sistema de cotas é solução para problema de capacidade, não para problema de arquitetura. Se seu código faz N requisições quando faria 1, nenhuma cota vai te salvar — ela só vai atrasar o colapso. Eu vi timesintroduzirem rate limiting em cima de um batch job que deveria ser refatorado, e perder duas semanas debugando timeouts que na verdade eram loop infinito. Alternativas que funcionam melhor em cenários específicos:

Backpressure: em vez de bloquear, o consumidor retransmite um sinal de pausa para o produtor. É o padrão do Reactive Streams (CompletableFuture, RxJava, Project Reactor). Funciona muito bem quando a fonte de dados é conhecida e há fluxo contínuo — é o que eu uso em pipelines de streaming de logs. Circuit breaker: quando a taxa de erro sobe acima de um threshold (geralmente 50% em 10 segundos), o circuit abre e todas as chamadas falham imediatamente sem tentar. Isso protege contra cascata de falhas, mas não protege contra abuso legítimo de tráfego. Use circuit breaker junto com rate limiter, não no lugar.

Autoscaling baseado em cota: em vez de fixar o limite, você escala a capacidade. Kubernetes HPA com metricas de QPS por pod faz isso automaticamente. É a abordagem certa quando o tráfego é sazonal e previsível — horário comercial versus madrugada, por exemplo. O downside é custo: você paga pelo recurso ocioso durante períodos de baixa. O system de cotas é ferramenta útil, mas como toda ferramenta, serve para o problema certo. Se você tem recursos finitos e demanda variável, cotas dão previsibilidade. Se você tem demanda imprevisível e recursos flexíveis, autoscaling é melhor. Se você tem ambos, use os dois em camadas — cota como rede de segurança, autoscaling como resposta normal.