Contadores de janela fixa
Um estacionamento com cinco vagas e uma cancela. A cada trinta segundos a cancela reabre e as vagas ficam livres de novo.
Isso é um contador de janela fixa, o algoritmo de rate limiting mais simples que existe. Conte requisições dentro de uma janela de duração fixa, recuse tudo que passar do limite, e reinicie a contagem quando a janela terminar.
Observando uma janela se encher
Um limite de cinco requisições por janela de trinta segundos:
| Tempo | O que chega | Contagem | Resultado |
|---|---|---|---|
| 0s | 1 requisição | 1 | Aceita |
| 5s | 2 requisições | 3 | Aceita |
| 15s | 2 requisições | 5 | Aceita, e a cancela desce |
| 25s | 1 requisição | 5 | Rejeitada, a janela está cheia |
| 30s | Janela 2 abre | 0 | A contagem reinicia |
O estado envolvido são dois valores: em que ponto da janela você está e a contagem até agora. Nada é carregado da janela anterior.
Essa simplicidade é o atrativo inteiro. Barato para armazenar, barato para verificar, e difícil de gerar confusão.
Isso é o algoritmo sendo direto, não injusto. Ele não tem noção de "quase", só de "dentro desta janela" ou não.
O estouro na fronteira
Agora observe duas janelas consecutivas, com o mesmo limite de cinco a cada trinta segundos:
| Tempo | Janela | Requisições | Contagem acumulada |
|---|---|---|---|
| 50s | 2 | 2 | 4 |
| 55s | 2 | 2 | 6, então 5 aceitas |
| 60s | 3 abre | 2 | 2 |
Olhe para o relógio, não para as janelas. Entre 50 e 60 segundos, sete requisições foram aceitas.
O limite era cinco a cada trinta segundos, e sete chegaram em dez.
Nada funcionou mal. Requisições no fim da janela dois e no início da janela três estão em janelas diferentes, então nenhuma contagem passou de cinco. O algoritmo fez exatamente o que foi programado para fazer.
Esse é o problema da fronteira da janela, e é a fraqueza definidora dessa abordagem. No pior caso, um cliente envia o limite total imediatamente antes de um reset e o limite total imediatamente depois, passando o dobro do limite em um instante.
Dê um passo atrás e olhe para um trecho de tempo real que cruza a fronteira, e o limite nunca foi realmente aplicado ali.
Coloque em prática
Uma API permite 10 requisições por janela de 60 segundos, alinhada ao relógio, de forma que as janelas começam no início de cada minuto.
- Um cliente envia 10 requisições às 12:00:59 e mais 10 às 12:01:01. Quantas são aceitas, e o limite foi quebrado?
- Um cliente envia todas as 10 às 12:00:00. O que acontece com a requisição dele às 12:00:30?
- Você precisa garantir que nenhum cliente receba mais de 10 requisições em qualquer intervalo de 60 segundos. Uma janela fixa consegue fazer isso?
Compare suas respostas
1. Todas as 20 são aceitas, e nenhuma regra foi quebrada. As primeiras dez caem na janela das 12:00 e as segundas dez na das 12:01, então nenhuma contagem passou de 10.
Vinte requisições chegaram em dois segundos. Isso é o estouro na fronteira, e não exigiu nada mais sofisticado do que perceber quando o minuto vira.
2. Rejeitada. A janela está cheia e ainda faltam trinta segundos para ela terminar. O serviço está completamente ocioso e o cliente mesmo assim espera, que é a seca que vem junto com a rajada.
3. Não. Não com uma janela fixa, em nenhum limite. Qualquer intervalo de tempo real que cruze uma fronteira pode carregar até o dobro do limite, e isso é uma propriedade de dividir o tempo em blocos fixos, não um problema de ajuste fino.
Conseguir essa garantia significa medir contra uma janela que se move junto com a requisição, em vez de um bloco preso a um calendário, que é o assunto do próximo capítulo.
Para onde isso vai a seguir
Janelas fixas são baratas, simples, e erradas por até um fator de dois na fronteira. Se isso importa depende do que o endpoint faz.
Antes de consertar isso, vale a pena construir uma. Construindo um rate limiter transforma esse algoritmo em um middleware Express funcional, com os headers que um cliente precisa para se comportar bem.

