> ## Documentation Index
> Fetch the complete documentation index at: https://gomodel-feat-http-socks5.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Failover

> Fail over between the targets of a virtual model, and make a target list a strict priority order with the failover strategy.

## Overview

Failover is part of [virtual models](/features/virtual-models). Every
redirect with two or more targets fails over between them: when the target a
request was sent to returns a failover-eligible error, GoModel retries the
request against the redirect's remaining available targets, in declared order,
and stops at the first success.

The redirect's **load-balancing strategy** decides only which target is tried
first:

| Strategy     | First target                       | Then                                 |
| ------------ | ---------------------------------- | ------------------------------------ |
| Round-robin  | rotates across targets (weighted)  | the other targets, in declared order |
| Lowest cost  | the cheapest available target      | the other targets, in declared order |
| **Failover** | the first available target, always | the next targets, in declared order  |

Pick **Failover** when the target list is a priority order — always use the
best model unless it is down, and only then cascade to the backups.

For the other strategies the editor shows a **Failover** checkbox, on by
default. Untick it (or set `failover: false` as code) when a redirect should
only balance and a failed request should return its error, for example when
the targets are not interchangeable and a client handles retries itself. The
Failover strategy always fails over, so the checkbox is not offered there.

## Configure a failover chain

In the dashboard, open **Models** and edit the model you want to protect:
the model is already pinned as the first target, so add the fallbacks below
it in priority order and save — the strategy defaults to **Failover**. To
fail over under a new name instead, create a virtual model, list the targets
in priority order, and pick **Failover** in the **Load-balancing strategy**
dropdown. Weights and session keeping do not apply to this strategy, so the
editor hides them. Removing the pinned row turns the entry into a plain
redirect: requests for the model go to the remaining targets instead.

As code (`config.yaml` or the `VIRTUAL_MODELS` environment variable):

```yaml theme={null}
virtual_models:
  # A new name that always prefers the first target.
  - source: resilient-chat
    strategy: failover
    targets:
      - { model: kimicode/kimi-k2 }
      - { model: openai/gpt-4o }
      - { model: ollama/qwen3:8b }

  # Failover for a real model: the redirect shadows `gpt-4o`, tries it first,
  # then the fallbacks in order. Listing the source itself as the first target
  # stands for the concrete model it shadows.
  - source: gpt-4o
    strategy: failover
    targets:
      - { model: gpt-4o }
      - { model: azure/gpt-4o }
      - { model: gemini/gemini-2.5-pro }
```

A target may also name another virtual model
([chaining](/features/virtual-models#chain-virtual-models)); the sweep then
tries every concrete model behind it.

## When it runs

Failover is attempted only after an attempt returns:

* `5xx`
* `429`, including a rate limit GoModel itself enforces on the target — a
  saturated target is skipped while another target has capacity
* model unavailable, unsupported, or not found style errors
* upstream failure messages relayed with a `4xx` status (aggregator providers
  such as OpenCode Zen can report a transient failure of their own upstream as
  `400 "Upstream request failed"`)

It applies to translated `/v1/chat/completions`, `/v1/responses`, and
`/v1/messages` requests. The request log shows every attempt, so a served
failover is visible in the audit trail and priced at the model that answered.

A request that names its provider in the `provider` field bypasses virtual
models and reaches the concrete model directly. It still gets the chain of a
virtual model that shadows exactly that model and lists it as a target (the
shape the Models page creates for a real model), since that virtual model adds
failover to the model rather than replacing it.

Set `FAILOVER_ENABLED=false` (or `failover.enabled: false`) to switch the
sweep off globally; a [workflow](/advanced/workflows) can also turn it off for
its scope. The chosen target is still served, without retries.

## Migrating from failover rules

Earlier releases managed failover as separate per-model mappings (the shuffle
icon on the Models page and the `failover.rules` configuration). Both are
converted automatically:

* Dashboard-managed mappings become virtual models with the failover strategy
  that shadow their primary model. The conversion runs once at startup and
  then removes the old `failover_rules` store (any of its historical shapes).
  When the primary model already has a plain per-model setting (a slowdown or
  description set from the Models page), the mapping is merged into it and
  the setting is kept. A primary that already has a redirect, a path-scoped
  setting, or is disabled is logged and skipped, and the store is kept until
  it is resolved — add its fallbacks as targets of that virtual model with
  the failover strategy, then delete the row. A primary listed in
  `disabled_models` converts as a disabled virtual model: its fallbacks are
  kept but inactive until you enable it from the Models page.
* `failover.rules`, `manual_rules_path`, `FAILOVER_RULES_JSON`, and
  `disabled_models` still load and are translated into configuration-managed
  virtual models on every start, with a deprecation warning. A rule whose
  primary model has a virtual model in the dashboard is skipped with a
  warning, so it never replaces that virtual model's routing. Move the rules
  under `virtual_models` at your convenience.
