Deriva de provedor: como o roteamento padrão aumenta o custo dos LLMs
Conteúdo
Você ativou o prompt caching. O contador de acertos sobe de vez em quando, mas a conta quase não mudou. Antes de culpar a estrutura do prompt, verifique algo que o dashboard não mostra: qual upstream atendeu cada requisição.
Gateways com vários provedores distribuem um mesmo modelo entre diversos upstreams e escolhem um deles a cada requisição. Os prompt caches são separados por provedor e, muitas vezes, até por nó dentro do mesmo provedor. Se a segunda requisição idêntica cair em um upstream diferente da primeira, ocorrerá um cache miss, mesmo que nenhum byte do prompt tenha mudado. Isso é deriva de provedor e, em modelos cobrados por token, aumenta silenciosamente o custo.
TL;DR
- Com o roteamento padrão de fábrica, um gateway com vários provedores distribuiu 20 chamadas idênticas por 9 upstreams e acertou o prompt cache em apenas 4 das 20.
- Um gateway com backend único acertou 19/20 com a mesma carga; por causa da deriva, a execução custou cerca de 3.9x mais ($0.0102 contra $0.0026).
- No modelo da família DeepSeek analisado, um cache miss custou cerca de 4x mais que um hit (mediana de $0.00062 contra $0.00015 por chamada).
- A deriva ocorre por modelo: no mesmo gateway, um modelo da classe GPT foi encaminhado para um único upstream nas 20 chamadas e obteve 19/20 hits.
As duas condições que provocam a deriva
Não é uma configuração incorreta que você escolheu. É o comportamento padrão:
- Roteamento automático padrão. A requisição é enviada ao modelo sem fixar um upstream, e o gateway escolhe um a cada chamada.
- Ordenação padrão de provedores = “default (balanced)”. O gateway balanceia a carga entre os upstreams qualificados, em vez de manter as requisições em apenas um.
As duas opções vêm assim de fábrica. Você não precisa alterar nada para ter deriva; precisa mudar a configuração para evitá-la.
Como ficam 20 requisições idênticas
Enviamos o mesmo prefixo de aproximadamente 8K tokens 20 vezes seguidas para um gateway popular com vários provedores, usando as configurações padrão acima. Em cada chamada, pedimos os campos de provedor e cache informados pelo próprio upstream. Para um modelo da família DeepSeek com cache em disco:
- 9 upstreams distintos atenderam as 20 chamadas:
N***a,S***w,M***h,D***a,A***L,P***l,S***e,V***e,A***d. - Taxa de acerto do cache: 4/20 (20%). Só houve hit quando a chamada caiu por acaso em um upstream que já havia armazenado o prefixo.
Ao executar as mesmas 20 chamadas em um gateway com backend único — um modelo, um upstream e sem balanceamento —, a taxa de acerto foi de 19/20 (95%) com a mesma carga. Mesmo modelo, mesmo prompt e mesmo número de chamadas. A única variável foi a ocorrência de deriva no roteamento.
Como comparação, no mesmo gateway com vários provedores, um modelo da classe GPT foi encaminhado para um único upstream (A***e) nas 20 chamadas e obteve 19/20 hits. A deriva não é uniforme. Ela afeta os modelos que o gateway decide distribuir e, nessa execução, isso ocorreu com o modelo da família DeepSeek.
Conclusão A: o custo esperado e o custo real
O custo por chamada do modelo sujeito à deriva se separou claramente de acordo com o resultado do cache:
| tipo de chamada | custo mediano / chamada |
|---|---|
| cache hit | ~$0.00015 |
| cache miss | ~$0.00062 |
Nesse modelo, um miss custa cerca de 4x mais que um hit. Considerando apenas os tokens de entrada, a diferença publicada é ainda maior: aproximadamente 50x. Somando as 20 chamadas:
| cenário | taxa de acerto | custo de 20 chamadas idênticas |
|---|---|---|
| esperado (cache acessível) | 95% | $0.0026 |
| real (deriva padrão) | 20% | $0.0102 |
Mesmo modelo, mesmo prompt, mesmas 20 requisições. A deriva de provedor fez a execução custar ~3.9x mais. O cache permaneceu ativo o tempo todo, mas a camada de roteamento cobrou a maioria dos tokens pelo preço de miss. Em um endpoint de produção que reutiliza um prefixo grande e estável durante todo o dia, essa diferença passa a representar a maior parte do gasto com tokens de entrada.
Conclusão B: sem cache, não há redução de latência
O cache não serve apenas para reduzir custos. Com o prefill já aquecido, o primeiro token chega mais rápido. Quando a deriva impede o acesso ao cache, essa redução de latência também é perdida. Medimos o tempo até o primeiro token (TTFT) em chamadas idênticas e repetidas:
Modelo da classe GPT (encaminhado sempre para o mesmo upstream, com cache acessível):
| chamada | TTFT |
|---|---|
| 1ª (fria, miss) | ~1760 ms |
| seguintes (aquecidas, hit) | ~1130 ms |
O cache reduz em aproximadamente 36% o tempo até o primeiro token, de maneira consistente: todas as chamadas com cache aquecido ficam em uma faixa estreita.
Modelo da família DeepSeek (deriva padrão, cache raramente acessível):
- Cache hits em uma sequência de 10 chamadas: 0.
- O TTFT variou de ~1000 ms a ~4500 ms entre as chamadas, com respostas vazias ocasionais.
Como quase toda requisição chega a um upstream novo, a latência permanece no nível de um prefill frio e ainda varia conforme o provedor que respondeu. O modelo GPT teve uma redução de 36% no TTFT porque o cache estava acessível. O modelo sujeito à deriva não teve ganho algum, além de apresentar uma diferença de 4.5x entre a chamada mais rápida e a mais lenta.
Audite sua configuração em cinco minutos
Não confie nesses números, nem nos de qualquer outra pessoa. Envie várias vezes o mesmo prefixo longo e acompanhe dois campos. O código não fixa nenhum domínio; use variáveis de ambiente para apontá-lo ao seu gateway.
import os, uuid
from openai import OpenAI
client = OpenAI(api_key=os.environ["GW_KEY"], base_url=os.environ["GW_BASE"])
SYS = f"[probe {uuid.uuid4().hex}]\n\n" + ("You are a support assistant. " * 300)
seen, hits = {}, 0
for i in range(20):
r = client.chat.completions.create(
model=os.environ["GW_MODEL"], max_tokens=16,
messages=[{"role": "system", "content": SYS},
{"role": "user", "content": f"q{i}"}],
extra_body={"usage": {"include": True}})
d = r.model_dump()
det = r.usage.prompt_tokens_details
cached = (getattr(det, "cached_tokens", 0) or 0) if det else 0
seen[d.get("provider")] = seen.get(d.get("provider"), 0) + 1 # populated when exposed
hits += 1 if cached else 0
print(f"hit rate {hits}/20; upstreams seen: {len(seen)}")
Mais de um upstream para o mesmo modelo indica deriva. Se a taxa de acerto estiver muito abaixo do nível de estabilidade dos seus prompts, a deriva está aumentando seu custo. O método completo está em Seu gateway de LLM mente sobre o cache?.
O que verificar
A solução para a deriva é estrutural: encaminhe cada modelo para um backend consistente, para que o cache aquecido continue acessível na requisição seguinte. Não balanceie cada chamada para um upstream novo que nunca recebeu seu prefixo. Ao avaliar um gateway, envie o mesmo prefixo 20 vezes e conte os upstreams. Um é o resultado desejado. Nove representam um custo adicional.
Há uma ressalva: prompt caching é best-effort em qualquer plataforma. Nos modelos com cache em disco, a taxa de acerto ainda cai após longos períodos de inatividade, mesmo com backend único. Eliminar a deriva não cria um cache infinito. Apenas remove a principal e mais dispendiosa fonte de misses, aquela que você não escolheu e não consegue enxergar.
Encerramento
“Oferece suporte a prompt caching” e “seu cache está acessível” são afirmações diferentes. Um gateway que distribui um modelo entre vários upstreams rotativos pode afirmar corretamente que oferece suporte a cache, mas ainda assim entregar uma taxa de acerto de 20%, uma conta ~4x maior e uma latência até o primeiro token que varia 4.5x. O dado relevante não é se o cache aparece na lista de recursos. É a taxa de acerto medida e o número de upstreams percorridos por requisições idênticas. Execute o teste e deixe os dados responderem.
Para conhecer o método de auditoria mais amplo, consulte Seu gateway de LLM mente sobre o cache?. Para entender por que esses caches existem, consulte Como funcionam o KV Cache e o TTL.
Perguntas frequentes
Isso é uma configuração incorreta do meu lado? Não. O problema ocorre com as configurações de fábrica: roteamento automático e ordenação de provedores definida como “default (balanced).” Para evitar a deriva, é preciso fixar explicitamente um upstream.
Fixar um único upstream resolve o problema? Isso elimina a deriva entre provedores, mas um único upstream costuma operar várias réplicas sem afinidade de prefixo. Por isso, os hits ainda podem alternar. Meça o resultado depois de fixar o upstream, em vez de presumir que funcionou.
Por que o modelo da classe GPT não apresentou deriva? Nessa execução, o gateway o encaminhou por acaso para um único upstream. A deriva ocorre por modelo e depende da quantidade de upstreams qualificados entre os quais o gateway faz o balanceamento. Ela não é uniforme.
A diferença de custo é mesmo de ~4x? Nos totais por chamada que medimos, um miss custou ~4x mais que um hit. Nos preços publicados dos tokens de entrada para essa classe de modelo, a diferença entre hit e miss fica mais próxima de 50x. Nos dois casos, o custo vem de transformar hits esperados em misses.
Qual métrica devo monitorar? A taxa de acerto do cache por modelo ao longo do tempo, junto com a quantidade de upstreams distintos por modelo. Se a taxa de acerto cair ou o número de upstreams subir, seu custo efetivo por token acabou de aumentar.