Abstract illustration of glowing network routing paths, with a backup path glowing hot from overuse beside a nearly empty gauge

I checked my Qwen usage because I thought it should be almost untouched.

I had not been selecting Qwen for normal conversations. It was not my primary model. It was sitting behind Kimi in a fallback chain, waiting for the occasional overload or quota error. In my head, that made it the emergency spare tire: important to have, rarely used.

The weekly quota was completely empty.

So I pulled the gateway logs. They showed 912 successful Qwen HTTP responses since July 21, plus the later quota failures. The worst hour contained hundreds of model starts while one long scheduled job kept working through tool calls. I had not manually chosen Qwen, but my system had chosen it for me again and again.

The fallback worked so well that I did not notice it was eating the fallback.

A successful fallback is supposed to feel boring

The routing logic was doing exactly what I asked. Kimi was the primary. When Kimi hit a weekly limit, returned an overload error, or stalled, the runner moved to Qwen. Qwen completed the work, so the conversation or scheduled job looked healthy from the outside.

That is the purpose of failover. If switching providers required me to intervene every time, it would not be failover; it would be a notification system with homework.

OpenClaw's current model-failover documentation makes the behaviour explicit. A configured default or a scheduled-job primary can walk its configured fallback chain. The winning fallback applies to that turn without changing the session's selected primary. An explicit model choice is different: it is strict, so if I manually pin a model and it fails, the system reports the failure instead of quietly choosing something unrelated.

That distinction explained two things that had looked contradictory.

First, the status still showed Kimi as the selected model even when Qwen had done the actual work. Second, manually selecting Qwen after its quota was exhausted produced a hard failure. Normal routing allowed failover; my explicit selection did not.

Nothing was broken. My mental model was.

One notification is not the same as ongoing visibility

The software can emit a notice when a turn moves to a fallback and another when the primary later recovers. It also avoids repeating the same notice on every consecutive fallback turn. That is sensible. A banner attached to every response would become wallpaper within an hour.

But suppressing repetitive noise creates a different problem: a fallback can become operationally important while remaining psychologically invisible.

I was thinking in conversations. The quota was being consumed in model requests.

One agent turn can include many rounds: inspect something, call a tool, receive the result, reason again, call another tool, and continue. A scheduled job can run much longer than a chat reply. My 912 successful responses were not 912 conversations; they were HTTP calls inside a smaller number of multi-step runs. That is exactly why glancing at how often I personally selected a model told me almost nothing about its actual usage.

The sharpest spike came from a long scheduled worker. Once Kimi became unavailable, Qwen inherited the whole job rather than one small retry. Hundreds of calls later, the spare tire had driven the entire highway.

Reliability and capacity are two different promises

My chain answered the reliability question:

If the primary fails, can the work continue?

It did not answer the capacity question:

How much work can the fallback absorb before it also fails?

Those are not the same design problem.

A fallback with a small rolling quota may be perfect for a few interactive recoveries and terrible for an hour-long tool loop. A provider with usage-based billing may have no hard quota but create a different risk. A slower model may survive the workload while making scheduled jobs overlap. Ordering a chain only by model quality ignores the resource that failover is meant to preserve.

The better unit of planning is not "backup model." It is a capacity tier with an explicit job.

For my home setup, that means separating interactive continuity from unattended workloads. A model can remain available for conversations without automatically inheriting every scheduled job. Heavy jobs can use a different fallback list, tighter tool-round limits, or a provider whose capacity matches long runs. A job that loops for nearly an hour also needs its own ceiling, regardless of which model happens to win.

What I am changing in my head

I used to treat fallback order like a ranked list:

  1. best model;
  2. second-best model;
  3. emergency model.

Now I see it as a routing policy with a budget attached to every branch.

The questions are more concrete:

  • Which failures should trigger a switch?
  • Which workloads may use each provider?
  • How many calls can one run consume?
  • Where can I see usage by actual winner rather than selected primary?
  • What happens when a healthy fallback becomes the new bottleneck?

I also want alerts based on consumption, not just failure. A quota warning at 70 or 80 percent is useful. A perfect failover notice after the quota reaches zero is merely an obituary.

The funny part is that the system did what resilient systems are praised for doing: it absorbed failure without bothering me. The lesson is not to make failover louder until it becomes annoying. It is to measure the work that disappeared behind the quiet.

Redundancy kept my agent alive. Observability would have kept the redundancy alive.