[Superseded] Automatic provider failover on ChatGPT usage-limit exhaustion
Feature: automatic model-provider failover on ChatGPT usage-limit exhaustion
What variant of Codex are you using?
Codex CLI and TUI (0.144.1).
What feature would you like to see?
Add an opt-in provider failover policy that keeps the official ChatGPT/OpenAI
provider as the baseline, switches to a user-configured fallback provider when
either the 5-hour or weekly ChatGPT usage window is exhausted, and returns to
the official provider when every exhausted window has reset.
This is different from generic HTTP retry or model rerouting. It is a
quota-aware provider state machine with provider-specific authentication.
Problem
Codex already exposes structured ChatGPT limit data:
RateLimitSnapshot.primaryfor the 5-hour window.RateLimitSnapshot.secondaryfor the weekly window.used_percent,window_minutes, andresets_at.rate_limit_reached_type.UsageLimitReachedError.resets_at.- App-server
account/rateLimits/readand
account/rateLimits/updated.
However, when a subscribed user's 5-hour or weekly allocation is exhausted, a
turn stops even if the user has an independently configured API-compatible
provider that could continue the work. Users can manually editmodel_provider, credentials, and provider configuration, but doing so:
- Interrupts the current workflow.
- Risks sending the wrong credential to a custom base URL.
- Requires tracking both reset windows manually.
- Does not automatically restore the preferred official provider.
Desired behavior
In automatic mode:
- Prefer the configured primary provider (
openaiin the common case). - Continue using it while every applicable ChatGPT quota window is available.
- If either the 5-hour or weekly window reaches its limit, activate the first
eligible fallback provider.
- Persist the exhausted windows and their reset timestamps.
- Stay on fallback until all exhausted windows have reset.
- Probe official availability using the existing structured rate-limit API.
- Return to the primary provider automatically.
- If the official provider still returns
UsageLimitReachedError, immediately
return to fallback and update the reset state.
Manual primary, fallback, and auto overrides should always be available.
Possible configuration
The exact schema is open for discussion. One possible shape:
[provider_failover]
mode = "auto"
primary = "openai"
fallbacks = ["company-proxy"]
fallback_on = ["chatgpt_usage_limit"]
restore = "when_all_exhausted_windows_reset"
max_turn_retries = 1
[model_providers.company-proxy]
name = "Company proxy"
base_url = "https://proxy.example.invalid"
wire_api = "responses"
env_key = "COMPANY_PROXY_API_KEY"
requires_openai_auth = false
Manual CLI/TUI controls could be:
/provider auto
/provider primary
/provider company-proxy
or:
codex --provider-mode auto
codex --provider-mode primary
codex --provider company-proxy
Authentication and security requirements
This feature should not reuse one global credential blindly across providers.
- ChatGPT bearer/refresh tokens must never be sent to a custom provider URL.
- A fallback should be eligible only when it has an independent credential
binding, such as its own env_key, provider auth block, or provider-scoped
stored credential.
- Failover should be disabled with a clear diagnostic if the fallback's auth
cannot be resolved safely.
- Logs and rollout events should record provider IDs and transition reasons,
but never credentials.
Provider-scoped auth is the main reason this should be designed natively rather
than implemented as a blind retry around the current global auth.json.
Suggested state machine
PrimaryAvailable
-> PrimaryLimited(exhausted windows + resets_at)
-> FallbackActive
-> ProbePrimary(after strictest relevant reset)
-> PrimaryAvailable
Manual override is orthogonal:
Auto | ForcePrimary | ForceFallback(provider_id)
For two exhausted windows, recovery should use the strict condition:
now >= max(reset timestamp of every exhausted window)
An earlier 5-hour reset must not restore the primary provider while the weekly
window remains exhausted.
Turn continuity
The ideal behavior is to retry the same user turn once after switching the
provider.
To avoid duplicate side effects:
- Automatic same-turn replay is safe when the usage-limit failure occurs before
any assistant output or tool call is committed.
- If the failure occurs after side effects, Codex should preserve the thread and
resume with an explicit continuation boundary rather than blindly replaying
the whole turn.
- Transition loops must be bounded.
User-visible behavior
Codex should emit a concise transition event:
Official ChatGPT weekly limit reached.
Switched to provider "company-proxy" until 2026-07-18 12:00 local time.
On recovery:
Official ChatGPT limits are available again.
Switched back to the primary provider.
/status and app-server thread/account status should expose:
- provider mode;
- active provider;
- transition reason;
- exhausted windows;
- next primary probe/reset time.
Acceptance criteria
- [ ] Official provider remains active when both 5-hour and weekly windows have
quota.
- [ ] Exhausting either window activates the configured fallback.
- [ ] Exhausting both windows waits for both resets, not only the earlier one.
- [ ] Official availability is checked from structured data, not localized
error-string matching.
- [ ] Recovery returns to the primary provider automatically.
- [ ] Manual primary/fallback/auto overrides work.
- [ ] Provider credentials are isolated.
- [ ] Same-turn retry is bounded and does not duplicate committed tool effects.
- [ ] TUI, exec mode, and app-server clients receive provider-transition events.
- [ ] Existing behavior is unchanged when failover is not configured.
Suggested tests
- Primary request succeeds: no transition.
- Primary returns a 5-hour limit error: fallback receives one retry.
- Primary returns a weekly limit error: fallback remains active until weekly
reset.
- Both windows are exhausted: earlier reset does not restore primary.
- Probe after the strictest reset succeeds: primary is restored.
- Probe still reports exhausted: fallback remains active.
- Fallback auth missing: fail safely without sending primary credentials.
- Failure after a committed tool call: no blind full-turn replay.
- Manual override suppresses automatic transitions.
- Restart/resume preserves the active failover state.
Related issues and distinction
- #20310 requests scriptable usage-limit status.
- #21073 requests auto-resume when a usage limit resets.
This request uses the same structured rate-limit primitives but addresses a
different workflow: continue immediately on a separately authenticated provider
and restore the preferred official provider after quota recovery.
Local workaround
I implemented a PowerShell/Node proof of concept outside Codex that:
- reads rollout
RateLimitSnapshotevents; - calls
account/rateLimits/readthrough an isolated official app-server; - tracks both reset windows;
- atomically changes local provider profiles;
- provides
auto,official, andproxyoverrides; - restarts with
codex resume --lastwhen run through a managed launcher.
The workaround validates the state-machine behavior, but native support is
needed for safe provider-scoped auth, config reload, and exact same-turn retry.
Reference implementation and validation notes:
https://github.com/guangxiangdebizi/Medical-webwithai/pull/2
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗