How OmniRoute's 4-Tier Fallback System Prioritizes LLM Providers

OmniRoute routes requests through a four-tier hierarchy—Subscription, API Key, Cheap, then Free—to ensure high-priority traffic uses paid, high-quota backends while automatically degrading to cost-optimized alternatives when providers fail.

The open-source routing engine diegosouzapw/OmniRoute classifies every large language model (LLM) provider connection into one of four distinct tiers based on business relationship and cost model. This classification drives a deterministic prioritization algorithm that keeps enterprise traffic on subscription contracts while maintaining availability through lower-cost fallbacks.

Understanding the Four Provider Tiers

In src/shared/constants/providers.ts, each provider definition includes a tier field that maps to one of four categories. These tiers determine both scoring weights and the order of automatic failover.

Tier 1 – Subscription (Highest Priority)

Subscription tier providers rely on paid enterprise contracts or higher-quota plans. The routing engine treats these as the primary target for all requests because they typically offer the highest rate limits and most reliable service. According to the source code in open-sse/services/autoCombo/scoring.ts, these connections receive the maximum tierPriority boost during candidate selection.

Tier 2 – API Key (Standard Credentials)

API Key tier covers individual API credentials that are not part of a formal subscription contract. While still paid, these lack the enterprise guarantees of Tier 1. The scoring engine places them after Subscription providers but before any cost-optimized routes, ensuring paid traffic stays ahead of budget-conscious fallbacks.

Tier 3 – Cheap (Cost-Optimized)

The Cheap tier identifies providers with inexpensive per-token pricing, often "floor" or "budget" pricing models. OmniRoute selects these when higher tiers are unavailable or when the request explicitly specifies a cost-optimized route via the auto/cheap selector.

Tier 4 – Free (Last Resort)

Free tier providers operate on limited or zero-cost quotas. The system only considers these after exhausting all other tiers or when a request explicitly targets auto/free. This ensures that paid customers never consume free-tier capacity unless absolutely necessary.

How the Fallback Mechanism Works at Runtime

The fallback system operates through a multi-layer pipeline implemented across open-sse/services/autoCombo/virtualFactory.ts and src/sse/handlers/chat.ts.

Step 1: Candidate Pool Construction

When a request arrives (e.g., model: "auto"), the system queries all active connections:

// From open-sse/services/autoCombo/virtualFactory.ts
const candidates = await getProviderConnections({ isActive: true });

Each connection object carries the tier classification from the provider constants. The buildVirtualAutoCombo() function assembles these into an in-memory pool of potential candidates.

Step 2: Tier-Aware Scoring

The scoring engine in open-sse/services/autoCombo/scoring.ts applies two tier-specific factors:

  • tierPriority: Adds a positive weight to higher-tier providers (Subscription > API Key > Cheap > Free)
  • tierAffinity: Matches the requested tier when using auto/<category>:<tier> suffixes
// Score the pool with tier weighting
const scored = scorePool(candidates, taskType, undefined, getTaskFitness);
const best = scored[0]; // e.g., provider "anthropic-sub" (Subscription tier)

Step 3: Layered Failure Detection

Before final selection, the system filters candidates through three exclusion layers defined in src/sse/services/auth.ts:

  1. Circuit Breaker Check: Providers with an OPEN circuit status (from getCircuitBreaker(provider).getStatus()) are removed from the pool
  2. Rate Limit Cooldown: Connections with active rateLimitedUntil timestamps are temporarily excluded
  3. Model Lockout: Specific model failures trigger isModelLocked() checks, allowing the connection to remain available for other models while blocking the failed one

Step 4: Global Tier Fallback

If all candidates from the current tier are exhausted, src/sse/handlers/chat.ts (lines 1134–1150) orchestrates the cross-tier fallback:

// Fallback triggered in src/sse/handlers/chat.ts
if (!response.ok) {
  const fallbackProvider = getNextTier(currentTier); // Subscription → API Key → Cheap → Free
  const fallbackModelStr = `${fallbackProvider}/${fallbackModel}`;
  
  return handleSingleModelChat(
    { ...body, model: fallbackModelStr },
    fallbackProviderModelStr,
    null // no combo strategy for emergency fallback
  );
}

The globalFallbackModel configuration setting allows administrators to define a specific endpoint of last resort when the entire provider chain fails.

Request-Level Controls and Headers

OmniRoute exposes granular control through HTTP headers processed in the chat handler:

  • X-OmniRoute-Mode: Forces a specific tier classification (e.g., fast, cheap, free)
  • X-OmniRoute-Budget: Caps the per-request cost; if no candidate satisfies the cap, the system references X-OmniRoute-Budget-Fallback to determine whether to select the cheapest viable provider or return HTTP 402 (Payment Required)

These headers interact directly with the scoring engine's cost factors, overriding default tier priorities when business constraints require specific economic controls.

Summary

  • OmniRoute's 4-tier fallback system categorizes providers as Subscription, API Key, Cheap, or Free to enforce business-priority routing
  • The Subscription tier receives first preference through tierPriority scoring boosts in open-sse/services/autoCombo/scoring.ts
  • Four exclusion layers protect against cascading failures: circuit breakers, connection cooldowns, model lockouts, and global tier fallback
  • When high-tier providers fail, the engine automatically degrades to API Key, then Cheap, and finally Free providers via handleSingleModelChat() in src/sse/handlers/chat.ts
  • Request headers allow dynamic override of tier selection and budget constraints without modifying provider configurations

Frequently Asked Questions

How does OmniRoute determine which tier a provider belongs to?

The tier classification is static metadata defined in src/shared/constants/providers.ts. Each provider entry includes a tier field that maps to one of the four categories. This metadata propagates to active connection objects via getProviderConnections(), making it available to the scoring engine during candidate evaluation.

What happens if all providers in the Subscription tier are unavailable?

If the circuit breaker, rate limit, or quota filters exclude all Subscription candidates, the engine automatically falls back to the API Key tier, then Cheap, and finally Free. This progression is hardcoded into the fallback logic in src/sse/handlers/chat.ts, which rebuilds the request body with fallbackModelStr pointing to the next available tier.

Can I force OmniRoute to use only Free-tier providers for testing?

Yes. Send the X-OmniRoute-Mode: free header with your request. This triggers tierAffinity scoring in open-sse/services/autoCombo/scoring.ts, effectively filtering the candidate pool to only Free-tier providers. Note that if Free providers are rate-limited or exhausted, the request may fail unless globalFallbackModel is configured to allow cross-tier escalation.

What is the difference between the Cheap tier and cost-based routing?

The Cheap tier is a static provider classification based on the provider's base pricing model, while cost-based routing is a dynamic strategy that compares real-time token prices. A provider in the Subscription tier might still be cheaper per token than a Cheap-tier provider during a promotion, but the 4-tier system prioritizes contractual relationships (Subscription > API Key) before evaluating per-request economics unless explicitly overridden by X-OmniRoute-Mode or X-OmniRoute-Budget headers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →