Roteamento de fallback para API de LLM: um playbook de failover em produção
O roteamento de fallback para APIs de LLM parece simples até o primeiro incidente real: capturar um erro, trocar de modelo e tentar novamente. Em produção, essa regra pode transformar um problema de um provedor em chamadas duplicadas de ferramentas, JSON quebrado, saída de streaming misturada, tráfego de retry descontrolado ou uma resposta que é tecnicamente bem-sucedida, mas já não satisfaz o contrato do produto.
Um design mais seguro trata o fallback como uma máquina de estados limitada, e não como uma lista de nomes de modelos de backup. Cada requisição passa por um pequeno conjunto de decisões:
- A falha é passível de retry?
- É seguro repetir esta requisição?
- A próxima tentativa deve usar o mesmo destino ou outro diferente?
- O fallback pode preservar o contrato exigido?
- A requisição já produziu saída ou efeitos colaterais?
- O tempo de latência ponta a ponta e o orçamento de tentativas foram esgotados?
Este playbook transforma essas perguntas em uma matriz de erros, política de roteamento, controlador em TypeScript, plano de testes e checklist de rollout para aplicações LLM com múltiplos provedores.
The four actions behind reliable LLM API fallback routing
Não envie todo erro para o mesmo loop de retry. Um roteador em produção precisa de quatro ações distintas.
| Action | Use it when | Typical examples |
|---|---|---|
| Retry the same target | The failure looks transient and the current deployment may recover within the request deadline | Connection reset before headers, isolated timeout, short rate-limit wait |
| Fail over to an equivalent target | The provider, region, deployment, or account is unhealthy but the same model contract is available elsewhere | Regional outage, exhausted deployment quota, repeated 5xx responses |
| Fall back to another model | An evaluated alternate model can preserve the application's minimum capability and output contract | Primary model unavailable and a tested secondary model supports the same tools and schema |
| Stop and surface the error | Repeating the request will not fix it, may create side effects, or cannot preserve the contract | Invalid authentication, malformed request, unsupported parameter, policy block, partial stream |
A distinção entre failover e fallback importa. Failover mantém o contrato lógico do modelo e altera a infraestrutura. Fallback muda o modelo ou o nível de capacidade. Failover geralmente é a opção de menor risco.
Se você precisar do design mais amplo do caminho da requisição em torno de aliases, health scoring, cobrança e observabilidade, comece com o guia de arquitetura de gateway de API de IA. Este artigo foca no controlador que executa depois que um destino foi selecionado.
Build an error-to-action matrix before writing retry code
Os SDKs dos provedores expõem diferentes classes de exceção e corpos de resposta, mas o roteador deve normalizá-los em uma pequena taxonomia interna.
| Falha normalizada | Repetir o mesmo destino? | Failover equivalente? | Fallback entre modelos? | Observações |
|---|---|---|---|---|
| Falha de conexão antes da aceitação da solicitação | Sim, uma vez | Sim | Talvez | Mantenha-se dentro de um único prazo de ponta a ponta |
| Timeout antes dos cabeçalhos da resposta | Talvez | Sim | Talvez | Repita apenas solicitações que sejam seguras para reexecutar |
Limite de taxa 429 |
Após atraso limitado | Sim | Talvez | Respeite a orientação do servidor quando disponível; não crie uma tempestade de retries |
5xx do provedor ou sobrecarga |
No máximo uma vez | Sim | Talvez | Abra o circuito após um limite definido de falhas |
| Erro de autenticação ou permissão | Não | Não | Não | Corrija as credenciais ou a política; trocar de modelo não ajuda |
| Solicitação malformada ou parâmetro não suportado | Não | Não | Não | Corrija o contrato do cliente |
| Limite de contexto excedido | Sem retry cego | Não | Somente com uma adaptação explícita | Truncamento, sumarização ou uma rota com contexto maior alteram a solicitação |
| Rejeição por segurança ou política | Sem retry cego | Não | Geralmente não | Trocar de provedor para contornar uma decisão de política não é uma estratégia de confiabilidade |
| Falha de validação do esquema de saída | Talvez com reparo | Não | Somente se avaliado | Mantenha o reparo de esquema separado dos retries de transporte |
| Stream falha antes do primeiro token | Talvez | Sim | Talvez | Ainda não existe saída visível ao usuário |
| Stream falha depois que a saída começa | Sem troca automática | Não | Sem troca automática | Não emende duas respostas do modelo |
| É possível que a chamada de ferramenta já tenha sido executada | Sem retry cego | Não | Sem retry cego | Exija chaves de idempotência ou desduplicação no nível da ferramenta |
A documentação oficial dos provedores reforça por que a normalização é necessária. A Anthropic documenta erros distintos de limite de taxa, API e sobrecarga e observa que uma solicitação em streaming ainda pode falhar após uma resposta inicial bem-sucedida. A OpenAI também separa solicitações inválidas, limites de taxa e falhas do lado do servidor. Seu aplicativo deve traduzir sinais específicos do provedor em decisões internas estáveis, em vez de incorporar nomes de provedores em toda a lógica de negócios.
Coloque um único orçamento de retry em torno de toda a solicitação
As tentativas de repetição geralmente existem em vários lugares ao mesmo tempo: o cliente HTTP, o SDK do provedor, o gateway, o job em segundo plano e o serviço da aplicação. Se cada camada fizer três tentativas, uma única ação do usuário pode se transformar em muito mais chamadas upstream do que a equipe pretendia.
O padrão mais seguro é:
- Escolher uma camada para ser responsável pelas tentativas de repetição e pelo fallback do LLM.
- Definir um único deadline de ponta a ponta para a requisição ou job do usuário.
- Definir um número máximo de tentativas upstream.
- Reservar parte do deadline para o destino de fallback.
- Usar backoff exponencial com jitter para falhas transitórias.
- Parar quando o tempo restante não suportar outra tentativa significativa.
A orientação da AWS sobre timeouts, retries, backoff e jitter descreve como as tentativas de repetição podem amplificar a sobrecarga e recomenda comportamento limitado, em vez de repetição imediata constante. O mesmo princípio se aplica às APIs de modelos, em que um provedor sob carga é o menos capaz de absorver tráfego de retries sincronizados.
Um orçamento interativo prático pode ser expresso como política, em vez de sleeps codificados:
type RetryBudget = {
deadlineMs: number;
maxAttempts: number;
maxSameTargetAttempts: number;
reserveForFallbackMs: number;
};
Os valores exatos dependem do produto. Uma interface de chat, um agente de código, um avaliador em lote e um fluxo assíncrono de vídeo não devem compartilhar o mesmo orçamento.
Use circuit breakers para impedir o roteamento para falhas conhecidas
Um circuit breaker impede que cada nova requisição redescubra a mesma indisponibilidade.
Os estados padrão são:
- Fechado: as requisições fluem normalmente enquanto o roteador mede falhas e latência.
- Aberto: o destino está temporariamente inelegível porque seu comportamento recente cruzou um limite.
- Meio aberto: um pequeno número de requisições de teste verifica se o destino se recuperou.
O padrão de circuit-breaker da Azure descreve esse ciclo fechado/aberto/meio aberto. Para o roteamento de LLM, a chave do breaker deve ser específica o suficiente para isolar a superfície com falha. Dimensões úteis incluem provedor, modelo, região, implantação, conta e capacidade. Uma implantação de conclusão de texto pode estar saudável enquanto um caminho de tool calling ou um endpoint regional está falhando.
Evite abrir circuitos em todo erro de cliente. Autenticação inválida, requisições malformadas, estouro de contexto e rejeição por política geralmente dizem mais sobre a requisição do que sobre a saúde do provedor. Os breakers devem reagir principalmente a sinais transitórios de infraestrutura, como falhas de conexão, timeouts, sobrecarga e erros de servidor.
Preserve um contrato de capacidade entre modelos
Um modelo de fallback não é seguro apenas porque aceita uma requisição compatível com OpenAI. Defina o contrato mínimo para cada alias de rota.
route: support-agent-v3
requires:
modalities: [text]
streaming: true
tools: true
parallel_tool_calls: false
structured_output: json_schema
context_window_min: 64000
max_output_tokens_min: 4000
quality_gates:
task_success_rate_min: 0.94
schema_valid_rate_min: 0.995
policy:
same_model_failover_first: true
cross_model_fallback_allowed: true
Antes de adicionar um destino ao conjunto de fallback, teste pelo menos:
- Parâmetros de solicitação suportados
- Definição da ferramenta e comportamento da chamada de ferramenta
- Validade da saída estruturada
- Forma dos eventos de streaming
- Limites de contexto e de saída
- Comportamento de segurança apropriado à aplicação
- Campos de contabilização de tokens usados pelos controles de custo
- Latência e qualidade em prompts representativos
Essa abordagem orientada por contrato é especialmente importante para fluxos de trabalho que atravessam modalidades. O guia de roteamento de agentes multimodais cobre verificações adicionais para rotas de texto, imagem, áudio e vídeo.
A TypeScript fallback controller
O exemplo a seguir é intencionalmente neutro em relação ao provedor. Ele pressupõe que adaptadores upstream normalizem erros e respostas antes que a camada de roteamento os veja.
type FailureKind =
| "connect"
| "timeout"
| "rate_limit"
| "overloaded"
| "server_error"
| "invalid_request"
| "auth"
| "policy"
| "context_overflow"
| "partial_stream"
| "unknown";
type Target = {
id: string;
contractId: string;
healthy: boolean;
circuit: "closed" | "open" | "half_open";
};
type RequestState = {
attempt: number;
sameTargetAttempts: number;
deadlineAt: number;
outputStarted: boolean;
sideEffectsPossible: boolean;
};
function canReplay(state: RequestState): boolean {
return !state.outputStarted && !state.sideEffectsPossible;
}
function isTransient(kind: FailureKind): boolean {
return [
"connect",
"timeout",
"rate_limit",
"overloaded",
"server_error",
].includes(kind);
}
function chooseNextAction(
kind: FailureKind,
state: RequestState,
current: Target,
equivalent: Target | undefined,
fallback: Target | undefined,
) {
if (!canReplay(state) || kind === "partial_stream") return { type: "stop" };
if (!isTransient(kind)) return { type: "stop" };
if (state.attempt >= 3 || Date.now() >= state.deadlineAt) {
return { type: "stop" };
}
if (
state.sameTargetAttempts < 1 &&
current.circuit === "closed" &&
current.healthy
) {
return { type: "retry", target: current };
}
if (equivalent?.healthy && equivalent.circuit !== "open") {
return { type: "failover", target: equivalent };
}
if (
fallback?.healthy &&
fallback.circuit !== "open" &&
fallback.contractId === current.contractId
) {
return { type: "fallback", target: fallback };
}
return { type: "stop" };
}
O código de produção também precisa de atrasos com jitter, propagação de cancelamento, IDs de solicitação, atualizações do circuit breaker, telemetria e análise de erros específica do adaptador. A propriedade importante é que a segurança de replay e a compatibilidade de contrato sejam verificadas antes de outro destino ser selecionado.
Treat streaming fallback as a separate protocol
O streaming cria uma fronteira rígida: uma vez que o conteúdo chega ao cliente, o gateway não pode mais fingir que a tentativa nunca aconteceu.
Se o upstream falhar antes de o primeiro evento ser encaminhado, uma repetição ou fallback ainda pode ser transparente. Depois que o primeiro token, delta de ferramenta, evento de imagem ou chunk de áudio é entregue, a troca automática de modelo corre o risco de combinar duas respostas incompatíveis.
Use uma destas estratégias explícitas:
- Falhe o stream de forma clara. Retorne um evento de erro estável com o ID da solicitação e deixe o cliente oferecer retry.
- Faça buffer antes de liberar. Para respostas estruturadas curtas, valide o resultado completo antes de enviá-lo downstream. Isso sacrifica o tempo até o primeiro token.
- Implemente retomada no nível da aplicação. Inicie uma nova rodada com contexto explícito dizendo que a resposta anterior foi interrompida. Trate isso como uma nova geração do modelo, não como uma continuação do mesmo stream de bytes.
Não concatene silenciosamente a saída de dois modelos.
Separe a confiabilidade das chamadas de ferramenta da confiabilidade das chamadas ao modelo
Uma solicitação de LLM pode ser reexecutável enquanto a ferramenta que ela selecionou não é. Um pagamento, e-mail, deploy, gravação em banco de dados ou criação de ticket pode ter sucesso mesmo que a conexão com o modelo falhe antes de a aplicação registrar o resultado.
Proteja ferramentas de escrita com:
- Uma chave de idempotência derivada da operação do usuário, não da tentativa do provedor
- Um registro durável de execução da ferramenta
- Deduplicação na fronteira da ferramenta
- Uma distinção clara entre
planned,started,succeededeunknown - Revisão humana para efeitos colaterais de alto impacto incertos
Se efeitos colaterais forem possíveis e o resultado deles for desconhecido, interrompa o fallback automático. Primeiro reconcilie o estado da ferramenta.
Observe o fallback como um resultado do produto
Uma baixa taxa de erro do provedor não prova que o fallback está funcionando. Acompanhe o resultado completo do caminho.
| Métrica | O que ela revela |
|---|---|
| Taxa de sucesso no alvo primário | Saúde base do provedor ou do deploy |
| Taxa de recuperação por retry | Se retries no mesmo alvo são úteis |
| Taxa de recuperação de failover equivalente | Valor de deploys redundantes ou regiões |
| Taxa de recuperação por fallback entre modelos | Valor do conjunto alternativo de modelos |
| Taxa de rejeição por contrato | Com que frequência os alvos candidatos falham nas verificações de elegibilidade |
| Validade do schema após fallback | Se respostas “bem-sucedidas” continuam utilizáveis |
| Sucesso da tarefa após fallback | Se os usuários ainda concluem o trabalho pretendido |
| Latência adicional do fallback | Custo de confiabilidade pago pelo usuário |
| Delta de custo do fallback | Impacto de faturamento do caminho de recuperação |
| Duração do circuito aberto e sucesso da sondagem | Se os limiares do breaker e o timing de recuperação fazem sentido |
Registre um motivo de rota para cada tentativa: alvo selecionado, erro normalizado, atraso de retry, estado do circuito, motivo do fallback, tempo restante até o prazo da solicitação e resultado final. Evite registrar prompts ou saídas sensíveis, a menos que a política de dados do produto permita explicitamente.
Teste os caminhos de falha antes de ativar o fallback automático
Execute injeção de falhas em um ambiente de staging e depois faça canary da política em produção.
Testes de transporte e provedor
- Desconecte a conexão antes dos cabeçalhos da resposta.
- Retorne limites de taxa repetidos com e sem orientação de nova tentativa.
- Simule sobrecarga e erros de servidor.
- Atrasar o primário até que o prazo da solicitação esteja quase esgotado.
- Abra um circuito de destino e verifique se o tráfego muda para uma rota elegível.
- Recupere o destino e verifique se as sondas half-open não restauram o tráfego total cedo demais.
Testes de contrato
- Remova uma ferramenta obrigatória do adaptador de fallback.
- Retorne saída estruturada inválida.
- Altere o formato de um evento de streaming.
- Exceda os limites de contexto ou de saída.
- Compare a qualidade do fallback em um conjunto fixo de avaliação.
Testes de segurança contra replay
- Falhe antes e depois do primeiro evento transmitido.
- Falhe depois que uma ferramenta do lado de escrita começar.
- Repita a mesma chave de idempotência.
- Cancele a solicitação do cliente enquanto a tentativa de fallback estiver pendente.
O teste só passa quando o roteador escolhe a ação esperada e registra o motivo.
Onde a Flatkey se encaixa
A Flatkey fornece uma chave de API e uma URL base compatível com a OpenAI para os modelos suportados, com uso e cobrança centralizados. Isso cria uma fronteira de integração estável para acesso e roteamento multi-modelo.
As equipes de aplicação ainda devem ser responsáveis pelo contrato de rota descrito neste playbook: quais erros podem ser tentados novamente, quais destinos são equivalentes, se o fallback entre modelos é अनुमतिido, como as ferramentas são deduplicadas e qual limite de qualidade uma resposta recuperada deve atender.
Para o caminho de integração mais curto, use o starter de integração da Flatkey. Se você estiver migrando um cliente existente, a lista de verificação do gateway de API compatível com OpenAI cobre URL base, parâmetros, streaming e verificação do formato de erro.
Checklist de implantação em produção
- Normalize os erros do provedor em uma taxonomia interna estável.
- Defina ações de retry, failover equivalente, fallback entre modelos e parada.
- Atribua a um único componente a responsabilidade pelo orçamento de retry.
- Impor um único prazo de ponta a ponta e um número máximo de tentativas.
- Adicione backoff exponencial com jitter para falhas transitórias.
- Vincule os circuit breakers ao menor domínio de falha útil.
- Defina um contrato de capacidade versionado para cada alias de rota.
- Bloqueie a troca automática depois que a saída parcial começar.
- Adicione idempotência e reconciliação para ferramentas do lado de escrita.
- Registre os motivos da rota e os resultados finais da tarefa.
- Injete falhas de transporte, sobrecarga, contrato, streaming e efeitos colaterais.
- Faça um canary do failover equivalente antes de habilitar o fallback entre modelos.
- Adicione kill switches para cada destino e política de fallback.
FAQ
O que é roteamento de fallback para APIs de LLM?
Roteamento de fallback para APIs de LLM é uma política de confiabilidade que seleciona outro modelo ou provedor elegível quando a rota preferida não consegue concluir uma solicitação. O fallback seguro verifica a segurança contra replay, a compatibilidade de capacidades, a saúde do circuito, o orçamento de latência e o estado da saída antes de alternar.
Qual é a diferença entre um retry de LLM e fallback?
Uma nova tentativa repete a solicitação contra o mesmo destino. O failover move para uma infraestrutura equivalente, preservando o contrato lógico do modelo. O fallback entre modelos altera o modelo e, portanto, exige testes mais rigorosos de compatibilidade e qualidade.
Um API de LLM deve tentar novamente todo erro 429 ou 5xx?
Não. As novas tentativas devem ser limitadas por um prazo fim a fim, um limite de tentativas, uma política de backoff, o estado do circuito e uma verificação de segurança para repetição. O failover equivalente pode ser melhor do que chamar repetidamente um destino com problemas.
Um roteador de LLM pode trocar de modelo durante um stream?
Não de forma transparente depois que a saída chegou ao cliente. O padrão seguro é falhar o stream de forma clara ou iniciar uma nova interação no nível da aplicação. Concatenar saídas parciais de modelos diferentes pode corromper o contrato da resposta.
Quando o fallback entre modelos deve ser desativado?
Desative-o quando o modelo alternativo não puder preservar as ferramentas exigidas, a saída estruturada, os limites de contexto, o comportamento de segurança, os limites de qualidade ou as garantias de efeitos colaterais. Também desative a repetição automática após saída parcial ou execução incerta de ferramentas.
Quantas tentativas de fallback uma solicitação de LLM deve fazer?
Não existe um número universal. Use a menor contagem de tentativas limitada que se ajuste ao orçamento de latência do produto e às evidências de teste. O roteador deve parar quando o prazo restante não puder suportar outra tentativa útil.
Fallback confiável não significa “tentar de tudo”. Significa tornar a próxima ação explícita, compatível, segura para repetição, observável e fácil de interromper.



