LLM Gateway Design: Rate Limiting, Caching e Fallback para Múltiplos Providers | Lemon.dev
LLM Gateway Design: O Padrão de Resiliência para Aplicações de IA
Sua aplicação chama openai.chat.completions.create() diretamente. Amanhã, a OpenAI sofre uma queda de serviço ou aumenta o preço em 10x. O que acontece com seu produto? Se você está acoplado a um único provedor de LLM, você quebra junto. Este é o cenário que motiva a adoção de um LLM Gateway: uma camada de abstração que gerencia múltiplos providers, adiciona controle de tráfego, cache inteligente e fallback automático.
O Problema: Vendor Lock-In e a Fragilidade de Dependência Única
Integrar diretamente com a OpenAI, Anthropic ou Google pode parecer rápido no início, mas cria uma dívida técnica perigosa. Quando o provider primário enfrenta downtime, rate limiting agressivo ou degradação de desempenho, sua aplicação sofre na mesma proporção. Além disso, mudar de provedor exige reescrever chamadas, adaptar SDKs e testar novamente toda a integração.
Um LLM Gateway resolve isso ao abstrair a comunicação com diferentes LLMs por trás de uma interface unificada. Em vez de chamar uma API específica, sua aplicação envia requisições para o gateway, que decide para onde rotear com base em regras de rate limiting, cache e fallback.
Componentes Essenciais de um LLM Gateway
1. Rate Limiting: Respeite os Teto dos Provedores
Toda API de LLM tem um teto – e ele quase nunca é o que você imagina. Os provedores não vendem chamadas ilimitadas; eles vendem cotas por minuto, medidas em requisições e em tokens. Quando seu tráfego atinge esse teto, a API começa a devolver 429 Too Many Requests. O primeiro reflexo de quase todo time é tentar de novo imediatamente, em todas as chamadas que falharam ao mesmo tempo – é o pior cenário, pois gera uma enxurrada de retries que piora a situação.
Boas práticas de rate limiting:
- Token Bucket ou Sliding Window: controle a taxa de requisições por segundo com base no limite do provider.
- Filas de prioridade: para requisições críticas (ex: chat em tempo real) vs. requisições em lote (ex: sumarização de documentos).
- Exponential Backoff com Jitter: quando um 429 ocorre, aguarde um tempo crescente e aleatório antes de tentar novamente.
Exemplo de configuração:
rate_limiting:
provider: openai
requests_per_minute: 60
tokens_per_minute: 100000
strategy: sliding_window
retry_policy:
max_attempts: 3
backoff: exponential
jitter: true
2. Caching: Reduza Custos e Latência
Muitas chamadas a LLMs são repetitivas – por exemplo, respostas a perguntas frequentes ou geração de conteúdo padrão. Cachear respostas idênticas (ou semanticamente equivalentes) reduz drasticamente o consumo de tokens e o custo financeiro.
Tipos de cache recomendados:
- Cache de requisição exata: chave = hash da mensagem + parâmetros. Útil para prompts fixos.
- Cache semântico: usa embeddings para identificar perguntas similares e retornar respostas em cache sem chamar o LLM novamente.
- Cache de fallback: mesmo que a requisição primária falhe, se houver uma resposta em cache (ainda que desatualizada), pode ser melhor do que nenhuma resposta.
Cuidados: defina TTL apropriado para cada tipo de conteúdo. Evite cache em dados sensíveis ou dinâmicos.
3. Fallback: Roteamento Inteligente entre Providers
Quedas de provedores acontecem. OpenAI, Anthropic e Google todos já experimentaram downtime, rate limiting severo e desempenho degradado. Fallbacks garantem que sua aplicação continue funcionando, roteando automaticamente para um provider alternativo quando o primário falha – e seus usuários não percebem a diferença.
Estratégias de fallback comuns:
- Primário-Secundário-Terciário: tenta OpenAI, se falha vai para Anthropic, se falha vai para Google.
- Round-robin ponderado: distribui carga entre provedores com base em custo, latência ou disponibilidade.
- Prioridade por caso de uso: use um modelo mais barato para tarefas simples e um mais caro apenas quando necessário.
Exemplo de lógica de fallback:
graph TD
A[Requisição] --> B{OpenAI disponível?}
B -->|Sim| C[Executa na OpenAI]
B -->|Não| D{Anthropic disponível?}
D -->|Sim| E[Executa na Anthropic]
D -->|Não| F[Retorna erro ou cache]
Fallbacks também devem considerar fallbacks dentro do mesmo provider (ex: GPT-4 → GPT-3.5-turbo) para evitar 429.
Implementando um Gateway Leve com Código
Um gateway não precisa ser um microsserviço complexo. Uma classe em TypeScript ou Python pode gerenciar múltiplos providers com essas funcionalidades:
class LLMGateway {
private providers: LLMProvider[];
private cache: CacheStore;
private rateLimiter: RateLimiter;
async complete(prompt: string, options?: CompletionOptions): Promise<LLMResponse> {
// 1. Verifica cache semântico
const cached = await this.cache.get(prompt);
if (cached) return cached;
// 2. Seleciona provider com base nas regras de fallback
for (const provider of this.getPriorityProviders()) {
if (!this.rateLimiter.canSend(provider)) continue;
try {
const response = await provider.complete(prompt);
await this.cache.set(prompt, response);
return response;
} catch (error) {
if (error.status === 429 || error.status >= 500) {
// registra falha e tenta próximo provider
logFailure(provider, error);
continue;
}
throw error; // erros não recuperáveis: sobe
}
}
throw new Error('All providers failed');
}
}
Conclusão: Por Que Você Precisa de um Gateway Hoje
O ecossistema de LLMs está evoluindo rápido, com novos modelos e provedores surgindo constantemente. Preços mudam, APIs são descontinuadas, e falhas de infraestrutura são inevitáveis. Um LLM Gateway não é apenas um luxo técnico – é uma necessidade estratégica para qualquer aplicação de IA em produção.
Os três pilares – rate limiting, caching e fallback – formam a base de uma arquitetura resiliente, que reduz custos, melhora a experiência do usuário e elimina o vendor lock-in. Implemente-o antes que o próximo downtime do seu provedor favorito tire seu serviço do ar.
"Se você não controla a camada de acesso ao LLM, o LLM controla você."