Migrate from LiteLLM

Migrating from LiteLLM?Keep the API. Stop running the proxy yourself.

Your app already calls the LiteLLM proxy with an alias in model. Point it at ModelRiver instead, turn each alias and its fallbacks into a workflow, and stop deploying and scaling the proxy.

  • BYOK
  • no token markup
  • Free plan stops at 25,000 requests/month

2 lines of code + 1 workflow

Keep your OpenAI SDK. On the client line, change the base URL and key. On the request line, set model to the name of a workflow.

Step 0: create a workflow in the console with your primary model and backups. Its name is what you send as model.

Before

app.py
import os
from openai import OpenAI

client = OpenAI(
    base_url="http://0.0.0.0:4000",
    api_key=os.environ["LITELLM_MASTER_KEY"],
)

resp = client.chat.completions.create(
    model="support-model",  # alias from config.yaml
    messages=[{"role": "user", "content": "Summarize this ticket."}],
)
print(resp.choices[0].message.content)

After

app.py
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.modelriver.com/v1",
    api_key=os.environ["MODELRIVER_API_KEY"],
)

resp = client.chat.completions.create(
    model="support_model",  # workflow name
    messages=[{"role": "user", "content": "Summarize this ticket."}],
)
print(resp.choices[0].message.content)

Before

app.ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "http://0.0.0.0:4000",
  apiKey: process.env.LITELLM_MASTER_KEY,
});

const resp = await client.chat.completions.create({
  model: "support-model", // alias from config.yaml
  messages: [{ role: "user", content: "Summarize this ticket." }],
});
console.log(resp.choices[0].message.content);

After

app.ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.modelriver.com/v1",
  apiKey: process.env.MODELRIVER_API_KEY,
});

const resp = await client.chat.completions.create({
  model: "support_model", // workflow name
  messages: [{ role: "user", content: "Summarize this ticket." }],
});
console.log(resp.choices[0].message.content);

Before

request.sh
curl http://0.0.0.0:4000/chat/completions \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "support-model",
    "messages": [{"role": "user", "content": "Summarize this ticket."}]
  }'

After

request.sh
curl https://api.modelriver.com/v1/chat/completions \
  -H "Authorization: Bearer $MODELRIVER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "support_model",
    "messages": [{"role": "user", "content": "Summarize this ticket."}]
  }'

What maps to what

LiteLLM concepts and where they live in ModelRiver.

LiteLLMModelRiver
model_list[].model_name aliasWorkflow nameSame idea: your code sends a name, the server decides the provider model. Workflow names use letters, digits and underscores.
litellm_params.model: openai/gpt-4oWorkflow primary provider and modelPicked from the catalog in the Console, or a custom OpenAI-compatible base URL.
fallbacks: [{"alias": ["b", "c"]}]Up to 2 backup models on the workflowBackups run on 429, 5xx, 408, 404 and connection errors, including during streaming.
api_key: os.environ/OPENAI_API_KEYProvider credential stored in the projectEncrypted at rest and masked in the Console. No environment variables to manage.
general_settings.master_keyModelRiver project API keySent as Authorization: Bearer, the same header your OpenAI SDK already uses.
num_retries, allowed_fails, cooldown_timeNo equivalentModelRiver retries only dropped connections, then moves to the next backup. There is no cooldown or circuit breaking.
Several deployments under one model_name + routing_strategyNo equivalentEach workflow slot is one provider and one model. There is no load balancing.
request_timeoutFixed 120-second timeoutNot configurable today.
context_window_fallbacks, content_policy_fallbacksNo separate chainsOne backup order per workflow, triggered by the error statuses above.

Map your config

Your fallbacks, output shape and budget move into one named workflow.

Your current LiteLLM request

request
model_list:
  - model_name: support-model
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY
  - model_name: support-backup
    litellm_params:
      model: anthropic/claude-sonnet-5
      api_key: os.environ/ANTHROPIC_API_KEY

router_settings:
  fallbacks: [{"support-model": ["support-backup"]}]

ModelRiver

The same setup as a ModelRiver workflow

Primary
openai/gpt-4o
Backup 1
anthropic/claude-sonnet-5
Backup 2
google/gemini-3.5-flash (optional)
Structured output
Optional JSON schema, saved on the workflow
Budget
Optional USD cap per model: hourly, daily, weekly or monthly
Release
Draft → Live, roll back any time

Try it with your keys. The Free plan stops at 25,000 requests a month instead of charging overage. Model usage is billed by your provider on your own keys.

Create a workflow free

When to stay where you are

LiteLLM may suit you better if any of these matter most.

What you gain, what you give up

What you gain

  • No proxy to deploy, upgrade or scale. ModelRiver runs the gateway, with a public status page and a 99.9% uptime target (no contractual SLA today).
  • Request logs and a per-request timeline with the provider and model used, each failover attempt and a cost estimate. No log database to host.
  • Async requests through the native API, with signed webhooks, WebSocket streaming and event-driven backend pipelines.
  • USD budgets per workflow model, reset hourly, daily, weekly or monthly. A slot over its cap hands off to the next backup.
  • Team access built in: owner, admin, editor and viewer roles, two-factor sign-in, and Draft and Live releases with rollback.

What you give up

  • Hosted only: ModelRiver is not open source and is not self-hostable.
  • No load balancing across deployments and no routing strategies.
  • No configurable retries, cooldowns or timeouts: ModelRiver retries only dropped connections, moves to the next backup, and times out at 120 seconds.
TopicLiteLLMModelRiver
How it billsOpen-source proxy (MIT, except the enterprise/ directory) that you run on your own infrastructure, so you pay for hosting and your providers. Enterprise is priced by usage through their sales team. Source (opens in a new tab) · checked Monthly plans by request volume, with no markup on tokens. Model usage is billed by your provider on your own keys.
Compared, with sources
  • The LiteLLM proxy runs on infrastructure you manage, with Redis to share state across instances. ModelRiver is a hosted service with a public status page and a 99.9% uptime target (no contractual SLA today). Source (opens in a new tab) · checked
  • LiteLLM reads its model list and fallbacks from config.yaml. ModelRiver keeps each workflow as Draft and Live versions with revision history and rollback. Source (opens in a new tab) · checked
  • LiteLLM is open source, with Enterprise priced by usage; you also pay to host it. ModelRiver bills a plan by request volume, adds no token markup, and its Free plan stops at 25,000 requests a month. Source (opens in a new tab) · checked
  • The LiteLLM repository is MIT-licensed outside its enterprise/ directory and runs as a self-hosted proxy. ModelRiver is not open source and is not self-hostable. Source (opens in a new tab) · checked
  • LiteLLM load-balances deployments that share a model_name, with routing strategies such as least-busy and latency-based. ModelRiver has no load balancing. Source (opens in a new tab) · checked
  • LiteLLM has num_retries, and allowed_fails with cooldown_time to cool down a failing deployment. ModelRiver retries only dropped connections, then moves to the next backup. Source (opens in a new tab) · checked
  • LiteLLM sets timeouts with request_timeout. ModelRiver timeouts are fixed at 120 seconds. Source (opens in a new tab) · checked
  • LiteLLM supports fallbacks per model group plus context-window, content-policy and default fallback chains. A ModelRiver workflow has one backup order with up to 2 backups. Source (opens in a new tab) · checked
  • LiteLLM describes support for 100+ LLMs. ModelRiver supports 13 providers, plus any OpenAI-compatible base URL. Source (opens in a new tab) · checked

Steps to move over

  1. Step 1

    Add your provider keys

    Add each key your config.yaml reads with os.environ/.... Keys are encrypted at rest and masked once saved, so there are no environment variables to manage.

  2. Step 2

    Create one workflow per alias your app calls

    Primary: the litellm_params.model behind the alias. Backups: the first two models in that alias's fallbacks list. Name it with underscores, such as support_model.

  3. Step 3

    Replay a few proxy requests against the Draft

    Take requests your app sends to the proxy today and run them through the Draft in the Playground. To wire up your app without provider calls, switch the workflow to Testing mode; switch back to Production before you publish.

  4. Step 4

    Publish the workflow Live

    API requests run the Live version, so publish before you switch code. support_model then plays the role your model_name alias plays in the proxy.

  5. Step 5

    Swap base URL, key and model

    Replace the proxy URL with https://api.modelriver.com/v1, the master key with a ModelRiver API key, and the alias with the workflow name.

    base_url="https://api.modelriver.com/v1"
    api_key=os.environ["MODELRIVER_API_KEY"]
    model="support_model"
  6. Step 6

    Keep the proxy as a fallback for a while

    Keep your current gateway configured in your code as a fallback until you're confident, then remove it. Leave the proxy running with its current config.yaml and send to it with the old alias if a ModelRiver call fails.

  7. Step 7

    Edit the workflow, not the config file

    Where you used to change config.yaml, edit the workflow Draft in the Console, publish it, and roll back to an earlier revision if needed.

Frequently asked questions

Can I keep my hyphenated alias, such as support-model?

Name the workflow support_model. A request for support-model resolves to it, and the x-modelriver-model-resolved-from response header records what you sent. Sending the exact name skips that lookup.

What replaces num_retries and cooldowns?

Nothing configurable. ModelRiver retries a dropped connection, and on 429, 5xx, 408 or 404 it moves to the next backup model. If you rely on cooldowns or tuned retries, that is a reason to stay.

I use the LiteLLM Python SDK, not the proxy. Can it call ModelRiver?

Yes, as an OpenAI-compatible endpoint: litellm.completion(model="openai/support_model", api_base="https://api.modelriver.com/v1", api_key=...). The openai/ prefix tells LiteLLM which API shape to use; ModelRiver sees support_model.

Can I import my config.yaml?

Not automatically. Send it to us with the keys removed and we will reply with the matching workflow setup. Most configs map to one workflow per alias.

Where are my provider keys stored?

In your ModelRiver project, encrypted at rest. Each request uses your key, and your provider bills you directly. ModelRiver adds no token markup.

Can ModelRiver run inside our VPC?

No. ModelRiver is a hosted service. If the gateway has to run on your infrastructure, keep the proxy.

Bring your keys. Keep your SDK.

Start on the Free plan, create a workflow and point your SDK at it.

Send us your models[] request or config.yaml (remove keys first) and we’ll reply with the matching workflow setup. Get help moving

Checked · Report an inaccuracy

Sources

LiteLLM is a trademark of its owner. ModelRiver is not affiliated with, endorsed or sponsored by it.