Índice do artigo
Resposta rápida
Rate limiting impede que uma origem consuma toda a capacidade de um endpoint. Em Flask atrás de Nginx, confirme como o IP real chega à aplicação, escolha uma chave de cliente e use armazenamento compartilhado quando houver mais de um processo. Ao exceder o limite, responda 429 Too Many Requests e, quando fizer sentido, Retry-After.
Veja a infraestrutura: VPS para Redis no Brasil para colocar este projeto no ar.
Defina o que está sendo protegido
Login, envio de formulário, webhook e consulta pública têm perfis diferentes. Um limite global pode proteger o servidor e ao mesmo tempo bloquear usuários legítimos. Separe por rota e, quando possível, por identidade autenticada; para endpoints anônimos, combine IP com outros sinais sem registrar dados além do necessário.
Proxy e IP real
O proxy deve encaminhar headers de origem, mas a aplicação só deve confiar neles quando a cadeia de proxies confiáveis estiver configurada. Confiar em qualquer X-Forwarded-For permite que o cliente falsifique o IP e contorne o limite. Documente quantos proxies existem e use a configuração apropriada do framework/deployment.
Exemplo de aplicação
Uma biblioteca de rate limiting para Flask pode usar Redis como backend. O desenho conceitual é:
limiter.limit("30 per minute")(rota_publica)
O valor é ilustrativo, não uma recomendação universal. Teste com carga controlada e escolha janela, burst e mensagem conforme o endpoint. Em múltiplos workers, memória local não é suficiente para um limite global.
Valide o comportamento
for i in $(seq 1 35); do
curl -s -o /dev/null -w '%{http_code}\n' https://api.exemplo.com/publica
done
Confirme a sequência de 2xx e 429, headers de resposta, logs sem segredo e retorno após a janela. Faça o teste em homologação ou em uma rota segura, nunca contra o checkout real.
Evite efeitos colaterais
Não aplique o mesmo limite a healthchecks internos, callbacks confiáveis e usuários autenticados sem análise. Use listas de exceção pequenas e auditáveis. Rate limit não substitui validação de payload, autenticação, timeout ou fila para tarefas demoradas.
Uma VPS com observabilidade ajuda a diferenciar ataque, pico legítimo e gargalo de banco. Veja os planos de VPS.
Checklist
- [ ] Endpoint e objetivo do limite definidos.
- [ ] Proxy confiável configurado.
- [ ] Backend compartilhado quando necessário.
- [ ]
429e retry testados. - [ ] Logs e métricas não expõem dados sensíveis.
FAQ
Rate limit deve ficar no Nginx ou Flask?
Pode existir em ambos: proxy para proteção ampla e aplicação para regras de negócio. Evite duplicar limites sem entender o efeito.
429 significa que a API caiu?
Não. É uma resposta deliberada de excesso de requisições.
Métricas mínimas
Conte requisições permitidas e limitadas por rota, identidade e status. Meça também tempo de espera e erros do backend. Uma queda de 429 pode significar que o limite está alto demais, não que a experiência melhorou. Um aumento pode ser ataque, cliente mal configurado ou mudança de comportamento. Não registre o telefone, token ou corpo completo como chave de diagnóstico; use identificadores minimizados e políticas de retenção compatíveis com o negócio.
📦 Template n8n: Agente de IA com WhatsApp + Evolution API
Baixe o arquivo JSON pronto para importar: Webhook configurado, tratamento de remetente, nó de OpenAI e disparo via Evolution API.
Comentários (7)
Excelente discussão sobre arquitetura limpa e separação de responsabilidades. Já adotei como padrão para os novos projetos.
Esse pattern realmente simplificou meu código! Refatorei um módulo inteiro seguindo essa abordagem e ficou muito mais manutenível. Em qual parte do artigo você recomenda focar para quem está começando em produção?
Muito bom ver boas práticas de código em português! Implementei os testes unitários como sugeriu e a cobertura subiu consideravelmente.
Excelente explicação sobre async/await e concorrência! Tinha várias promessas encadeadas e agora o código está limpo e legível.
Muito bom ver boas práticas de código em português! Implementei os testes unitários como sugeriu e a cobertura subiu de 30% para 85%.
As dicas de debug foram essenciais para encontrar um memory leak no meu aplicativo. O heap snapshot mostrou exatamente o problema.
Excelente explicação sobre async/await! Tinha várias promessas encadeadas que viraram um callback hell, agora está limpo e funcional.