Terceiro de cinco posts sobre gateway de IA. Antes: por que existe e como montar. Depois: onde o modelo local entra.
Resumo
- Overhead do LiteLLM: ≈ 10 ms no p50 sequencial, ≈ 45 ms com 10 conexões. Salto de rede do Docker isolado antes, em 0,43 ms.
- Contra uma chamada real de modelo, que leva de centenas de milissegundos a alguns segundos, isso é ruído. Contra um modelo local rápido, é dominante.
- OpenRouter não é alternativa ao gateway. O arranjo certo é declará-lo como provedor dentro dele.
- Se 10 ms são inaceitáveis para o seu caso, a resposta é Bifrost, não LiteLLM — e o motivo é o GIL.
1. Por que medir isso importa
A decisão de pôr uma camada entre a aplicação e o modelo costuma ser discutida em termos de governança, e tem bons argumentos por esse lado. Mas ela adiciona um salto no caminho de produção, e ninguém publica quanto esse salto custa.
Isso importa porque a resposta muda conforme o destino. Somar 10 ms a uma chamada de 2 segundos é 0,5%. Somar 10 ms a uma chamada de 80 ms para um modelo local é 12%. A mesma camada é irrelevante num caso e cara no outro.
2. O método
O problema de medir overhead de proxy é que a latência do provedor domina tudo e esconde o que você quer ver. Se eu medisse contra a API da OpenAI, estaria medindo a internet.
Então coloquei o LiteLLM na frente de um upstream local compatível com OpenAI que responde em 0,36 ms. Ele é instantâneo de propósito: assim a diferença entre os dois caminhos é o custo da camada, e nada mais.
Antes disso, isolei a rede. Rodando de dentro do container até o upstream, o salto de rede do Docker deu 0,43 ms no p50. Sem esse controle, qualquer número que aparecesse depois poderia ser NAT do Docker em vez de processamento do proxy.
3. Os números
3.1 Latência ponta a ponta
| cenário | caminho | p50 | p95 | p99 | máx |
|---|---|---|---|---|---|
| sequencial | direto | 0,36 ms | 0,45 ms | 0,56 ms | 0,55 ms |
| sequencial | via LiteLLM | 10,4 ms | 51,5 ms | 53,2 ms | 55,8 ms |
| 10 conexões | direto | 2,38 ms | 3,66 ms | 4,73 ms | — |
| 10 conexões | via LiteLLM | 47,0 ms | 57,0 ms | 63,4 ms | — |
3.2 O que sobra depois de descontar o rig
| medida | valor | o que é |
|---|---|---|
| upstream local, resposta | 0,36 ms | o piso: um servidor que só serializa JSON |
| salto de rede do Docker | 0,43 ms | container → host, medido de dentro |
| overhead do proxy, p50 sequencial | ≈ 10 ms | a diferença que sobra, e é o número do título |
| degradação do caminho direto sob carga | 6,6× | isto é o rig saturando, não o proxy |
3.3 Como ler cada linha
| linha | sustenta o quê |
|---|---|
| sequencial p50 | sim — uma requisição por vez, nada disputando CPU |
| sequencial p95/p99 | parcialmente — a cauda vem da política de retry, não da camada |
| 10 conexões, qualquer percentil | não isoladamente — mede proxy e rig ao mesmo tempo |
Condições: imagem main-stable, 4 workers, config padrão com retry ligado, gerador de carga no mesmo host, máquina de desenvolvimento Linux. Uma execução, sem replicação — por isso os números estão arredondados para dois algarismos, e não faz sentido citá-los com mais precisão que essa.
4. Como ler o resultado
Uma chamada real de modelo leva de centenas de milissegundos a alguns segundos. Somar 10 ms nisso é ruído — aparece num gráfico de latência, não aparece para o usuário.
A conta muda em dois casos:
- Modelo local rápido. Se você roteia para um Qwen ou Llama pequeno que responde em 80 ms, a camada vira mais de um oitavo do tempo total.
- Volume alto com margem apertada. Dez milissegundos por requisição, em milhões de requisições, viram CPU e viram conta.
Nos dois casos a resposta não é abrir mão da camada. É trocar de camada.
5. Se 10 ms são demais
O LiteLLM é escrito em Python, então o throughput por processo esbarra no GIL. O número da seção 3 é consequência direta disso, não um defeito de implementação.
As opções, e o critério de cada uma:
- LiteLLM — MIT, mais de 100 provedores atrás de um endpoint compatível com OpenAI, chave virtual, teto por time, fallback, painel. Escolha por cobertura. É o mais completo em compatibilidade e o mais direto de operar.
- Bifrost — escrito em Go, feito para overhead mínimo e throughput alto. Menos cobertura de provedor. Escolha por latência. Se os 10 ms te incomodam de verdade, é para cá que você vai.
- Portkey — o gateway virou Apache 2.0 em março de 2026; a plataforma de governança em volta continua proprietária, com opção de data plane auto-hospedado. Escolha por governança pronta, se você não quer construir a parte de política.
- Helicone — forte em observabilidade e auto-hospedável, mas entrou em modo de manutenção depois da aquisição pela Mintlify. Considere com cuidado se for depender dele por anos.
6. OpenRouter não é alternativa. É provedor.
Essa é a confusão mais comum na hora de decidir, e ela custa caro nos dois sentidos.
O OpenRouter é um roteador hospedado: uma API para centenas de modelos, com failover e uma conta só. Não loga prompt por padrão, tem controle de Zero Data Retention que restringe o roteamento a provedores que não retêm nem treinam, e oferece roteamento in-region na União Europeia para conta enterprise.
Duas coisas que você precisa saber antes de decidir:
- Existe um desconto de 1% em troca de habilitar log de prompt — e habilitar concede direito comercial irrevogável sobre entradas e saídas. Não habilite sem ler.
- Zero retention cobre conteúdo, não metadado. Contagem de token, latência e timestamp continuam retidos, e a retenção final depende do provedor para onde ele roteou.
Se a sua trava for para onde o dado vai — segredo industrial, cláusula de confidencialidade com cliente, setor regulado — o OpenRouter adiciona um salto em vez de remover. Você sai de "meu código vai para a Anthropic" para "vai para o OpenRouter e depois para a Anthropic". Pode ser aceitável, mas é uma decisão a mais para justificar numa auditoria, não a menos. Sobre esse tipo de restrição escrevi em Sua política de uso de IA não impede o vazamento.
E aí está o ponto que quase ninguém faz: você não precisa escolher. Declare o OpenRouter como um provedor dentro do LiteLLM.
- model_name: amplo
litellm_params:
model: openrouter/anthropic/claude-sonnet-5
api_key: os.environ/OPENROUTER_API_KEY
Chave virtual, teto por time, log e auditoria na sua infraestrutura. Amplitude de modelos do OpenRouter nas rotas que podem sair. As rotas que não podem apontam para provedor direto ou para modelo local, no mesmo arquivo.
A régua de o que pode sair da empresa passa a ser uma linha de YAML versionada, revisável em pull request. É a melhor propriedade de todo esse arranjo, e ela some se você tratar os dois como concorrentes.
7. Meça no seu caso
Não aceite meu número. Ele depende de quantos callbacks você habilita, se o cálculo de custo está ativo, e do hardware.
O método deste post é reproduzível em uma tarde: sobe um upstream local que responde imediatamente, mede o caminho direto, mede o caminho pelo proxy, e isola o salto de rede antes de atribuir a diferença ao proxy. É a única forma de saber se a camada cabe no seu orçamento de latência antes de descobrir em produção.
O stack completo, com o Compose e a config, está em como montar o gateway.
Como ajudamos times a adotar IA
Trabalhamos com times de engenharia que buscam incorporar IA ao dia a dia de desenvolvimento — não como experimento, mas como parte real do fluxo de trabalho.
Isso passa por escolher as ferramentas certas para o contexto do time, configurá-las de forma que façam sentido para a política de dados da empresa e garantir que os desenvolvedores saibam usá-las de um jeito que realmente aumente a produtividade, em vez de gerar mais fricção.
Se você tem um time de desenvolvimento e está tentando colocar IA para trabalhar de forma séria, fale com a gente.

