429.
Rotation is off until a second key is configured. One key behaves exactly as it
always has.
Configure
Add keys with numbered environment variables.<PROVIDER>_API_KEY is the first
key; <PROVIDER>_API_KEY_2, _3, and so on add the rest.
openai cycle sk-first → sk-second →
sk-third → sk-first → …
Or in config.yaml:
api_key and api_keys may be combined; api_key is used first.
Any provider that authenticates with an API key can rotate — ANTHROPIC_API_KEY_2,
GEMINI_API_KEY_2, GROQ_API_KEY_2, and so on. Providers that authenticate
another way (Vertex AI and Bedrock, which use Google and AWS credentials) ignore
these variables.
Rules
- Numbering starts at
2, since<PROVIDER>_API_KEYis key 1. Spelling out<PROVIDER>_API_KEY_1instead of the unsuffixed form also works. - Gaps are fine. Setting only
_API_KEYand_API_KEY_3gives two keys. - Duplicate keys are collapsed, so a key repeated across two variables does not take a double share of the traffic.
- Keys are used in the order configured: the unsuffixed key first, then ascending by number.
- Environment variables replace the provider’s whole
api_keyslist fromconfig.yamlrather than merging into it. - A key that does not resolve — an
${UNSET_VAR}placeholder — is dropped. A provider left with no keys at all is not registered.
Keys rotate per outbound HTTP request, including retries. A request that a
provider rejects with
429 is retried under the next key rather than the one
that was just throttled.Rotation on suffixed providers
Suffixed environment variables register a separate provider of the same type. The two mechanisms compose, and the trailing number is what tells them apart:openai-eu with two keys. The trailing _2 names a key.
openai-region-2 with one key. Here the 2 is part of the
provider suffix, not a key number.
What rotation covers
Every call GoModel makes to the provider draws the next key: chat completions, responses, embeddings, audio, images, batches, and provider-native passthrough routes. Realtime websocket sessions pick a key when the session opens and keep it for the life of that session. Rotation is per gateway process. Counters live in memory and reset on restart, soN replicas each rotate independently — which is fine, since the goal is to
spread load rather than to sequence it exactly.
Choosing between rotation and separate providers
Both let you use several keys of one provider type. They solve different problems.
If you want several keys and prompt caching, register them as suffixed
providers and put a
round_robin virtual model in
front. Each provider keeps its own key, so each keeps its own warm cache, at the
cost of qualified model IDs and more configuration.