Ragmux

Use cases

Migrating from LiteLLM to Ragmux

Move a LiteLLM proxy config to Ragmux's model connections and projects — a field-by-field mapping, what has no equivalent, and what to test before cutting over.

Updated: Last reviewed: Verified against Ragmux 0.5.0

Moving off LiteLLM is a config-translation problem more than a code-rewrite one, provided the calling application already talks to an OpenAI-compatible /chat/completions endpoint — which LiteLLM’s own proxy also exposes, so most applications already do. What changes is where a deployment, a key and a budget live: LiteLLM keeps them in a YAML file and a database; Ragmux keeps them as model connections and projects reachable through its own admin API. This walks through that translation piece by piece, including the parts that don’t map cleanly, so a migration doesn’t quietly drop a limit or a fallback nobody meant to remove. For the “should I move at all” question rather than the “how,” see Ragmux vs LiteLLM — this page assumes that decision is already made.

What a LiteLLM config actually holds

A LiteLLM Proxy deployment is driven by a config.yaml built around one model_list, each entry pairing a model_name — the alias callers request — with litellm_params naming the real provider and model, plus credentials:

model_list:
  - model_name: gpt-4o
    litellm_params:
      model: openai/gpt-4o
      api_key: os.environ/OPENAI_API_KEY
  - model_name: claude-team
    litellm_params:
      model: anthropic/claude-sonnet-4-5
      api_key: os.environ/ANTHROPIC_API_KEY
      rpm: 100

The os.environ/VAR syntax reads a credential from the proxy’s own environment rather than storing it in the file, and the proxy is started against that file directly — litellm --config /path/to/config.yaml, listening on http://0.0.0.0:4000 by default. Two entries can share one model_name, which is how LiteLLM does load balancing and fallback: a request for that alias is routed across every deployment registered under it, by routing_strategy, and rpm/tpm on each entry cap what that specific deployment can take before the router moves on to the next.

The mapping, piece by piece

One litellm_params entry becomes one model connection. POST /admin/api/models takes a provider_type (openai, anthropic, gemini, deepseek, ollama or custom_openai), an api_key, and a model_name — the same three pieces of information litellm_params already carries, just under Ragmux’s own field names. A deployment routed through LiteLLM itself, or any other server speaking the Chat Completions format, becomes provider_type: custom_openai with an explicit base_url — used exactly as given, so the /v1 suffix has to be included yourself; everything hosted directly by a provider Ragmux has a native adapter for skips the base_url field entirely. A LiteLLM proxy is typically reached at a Compose service name, localhost, or another private-network address, and Ragmux refuses those by default — add it to PRIVATE_UPSTREAM_ALLOWLIST, or set ALLOW_PRIVATE_UPSTREAMS=true, before the connection saves. See Private upstreams. The os.environ/VAR indirection has no equivalent — a connection’s api_key is stored, encrypted, on the connection itself, not read from the gateway process’s environment at request time — so a migration script reading the same environment variables LiteLLM used and passing their values straight into the API call is the direct replacement.

One model_name alias becomes one project, not one connection, because a project is also where Ragmux’s own limits and retrieval attach. POST /admin/api/projects with model_connection_id pointing at the connection from the previous step creates it, and the response’s api_key — an sk-proj-… value — is shown exactly once; save it before moving on, the same discipline a LiteLLM virtual key demands. If several LiteLLM deployments shared one alias for load balancing or fallback, the Ragmux equivalent is a route inside that project: one connection per deployment, each added as a target of the route, and the alias becomes the route’s name so the client’s model value stays the same. See Routing.

Limits translate, but the unit changes. LiteLLM’s rpm/tpm on a deployment and its dollar-denominated key and user budgets both express a ceiling; Ragmux’s rate_limit_rpm, rate_limit_tpm, budget_daily_tokens and budget_monthly_tokens on the project body express the same idea in requests and tokens, with 0 meaning unlimited. A requests-per-minute or tokens-per-minute figure carries over as-is. A dollar budget has to be converted using the provider’s own per-token price for that model, and re-derived if that price changes — Ragmux has no dollar-denominated budget field to set directly.

Routing strategy maps only in part. LiteLLM’s routing_strategy (least-busy, latency-based, and similar) spreads a request across whichever deployment under an alias looks healthiest at that moment. A Ragmux route orders its targets by priority (groups ascending, weighted random by weight inside a group) and moves to the next target on a failure that allows fallback (a 500, a reset connection or a 401 hands over without being retried; see Retry and fallback), so weighted splits and ordered fallback carry over, while strategies that measure latency or load per request do not.

What’s genuinely different underneath

LiteLLM’s own README describes it as giving “a single, unified interface to call 100+ LLM providers… using the OpenAI format” and ships as both a Python SDK (uv add litellm) and the separately-run Proxy (uv tool install 'litellm[proxy]', then litellm --model gpt-4o for a quick single-model start). That breadth is the thing a migration can’t recreate: Ragmux ships six provider types including custom_openai, which covers whatever an OpenAI-compatible server exposes, so a model_list entry naming a provider Ragmux has no adapter for has no destination to migrate to — it either stays on LiteLLM, moves behind a custom_openai connection if that provider exposes an OpenAI-compatible endpoint of its own, or needs a provider Ragmux doesn’t support yet. Licensing is the other asymmetry worth naming plainly during a migration decision: LiteLLM’s core SDK and proxy are MIT, but code inside its enterprise/ directory carries a separate commercial license required for production use — the license text doesn’t enumerate which features that covers, so treat it as a licensing question to raise with LiteLLM directly rather than a specific feature list — while Ragmux is AGPL-3.0-or-later throughout, with no gated tier to hit later.

What a migration gains, rather than loses, is retrieval as part of the same request path. A LiteLLM deployment doing retrieval-augmented generation today is calling a separate vector database and injecting context itself, before the request ever reaches the proxy. Attach a rag_store_id to a Ragmux project instead, and that same request gets its query embedded, searched and the matched passages injected automatically — one less system a migrated application has to keep operating.

Teams, keys and the database underneath

LiteLLM’s proxy separates a master key from per-user and per-team virtual keys, with budgets and rate limits attachable at any of those levels, and it can run without a database at all in a simpler mode that shares one key across every caller — a database becomes required specifically once virtual keys, spend tracking or budgets enter the picture. Ragmux’s access model maps onto that only partly: a project’s member_user_ids is its team, PUT /admin/api/projects/{id}/members is how that set changes later, and every member who is also an editor can rotate the project’s key or change its limits — there’s no separate concept of a master key above the project level, because there’s no shared key meant to span every project the way a LiteLLM master key spans every team. And Ragmux needs PostgreSQL unconditionally, for a single evaluation instance as much as for production, so a LiteLLM deployment that had been running database-free with a shared key needs a Postgres instance provisioned as part of the move, not as an optional upgrade taken later.

That database is also where the two systems diverge on what a migration inherits versus starts over. LiteLLM’s spend tracking and request logs live in its own tables, and nothing about creating a Ragmux connection or project reads them — a migrated deployment starts its request log, budgets and cost estimates at zero on the day it cuts over, with no historical spend carried across. Plan the cutover date accordingly if a monthly budget or a spend report needs to span the transition cleanly: closing out LiteLLM’s numbers for the old period and starting Ragmux’s for the new one, rather than expecting one continuous history, avoids a reporting gap nobody budgeted time to reconcile by hand.

Testing the cutover before it’s permanent

Because nothing about creating a Ragmux connection touches the LiteLLM deployment it was copied from, the two can run side by side against the same upstream provider keys for as long as the comparison takes. Run the same set of requests — the ones that exercise tools, streaming and whatever provider-specific parameters the application actually sends — through both, and check for a mismatch before pointing production traffic at the new project key. POST /admin/api/models/{id}/test catches a bad key or a mistyped base_url before that; it doesn’t catch a subtler behavioral difference, like a routing_strategy that used to mask a flaky deployment and behaves differently under a route’s priority and fallback rules. Once the comparison holds and every application config has moved from the LiteLLM proxy’s URL and virtual key to Ragmux’s URL and project key, the LiteLLM deployment itself is safe to decommission — right down to the API keys it held, which are worth rotating rather than reusing indefinitely across two systems.

Full reference: /docs/configuration/.

Move a LiteLLM proxy config to Ragmux

  1. Turn each model_list entry into a model connection

    For every deployment in LiteLLM's model_list, POST /admin/api/models once with the matching provider_type, api_key and model_name. A custom_openai or self-hosted deployment also needs an explicit base_url, used exactly as given — include the /v1 suffix yourself; a LiteLLM proxy or any other host on a private or local network (a Compose service name, localhost) is refused unless it's added to PRIVATE_UPSTREAM_ALLOWLIST, or ALLOW_PRIVATE_UPSTREAMS=true is set.

  2. Test each connection before anything depends on it

    POST /admin/api/models/{id}/test with {"mode": "chat"} for every connection you just created, so a copied key or an unreachable self-hosted server is caught here rather than in front of a real caller.

  3. Turn each model_name alias into a project

    POST /admin/api/projects with model_connection_id set to the matching connection, and rate_limit_rpm / budget_daily_tokens set from whatever limits the LiteLLM config enforced for that alias. The response's api_key is shown exactly once.

  4. Test the cutover, then move application configs and decommission LiteLLM

    Run the same requests through both proxies side by side and check for a mismatch before pointing production traffic at the new project key. Once the comparison holds, convert each application's config from the LiteLLM proxy's URL and virtual key to Ragmux's URL and project key, then decommission the LiteLLM deployment.

Frequently asked questions

Can I import a LiteLLM config.yaml directly into Ragmux?
No — there's no config-file import today. Ragmux's connections and projects are created through the admin API or dashboard, one at a time or scripted against the API; a model_list of a dozen deployments becomes a dozen POST /admin/api/models calls, which is mechanical enough to script but isn't a one-file drop-in.
What happens to LiteLLM's model_name aliasing when there's no equivalent in Ragmux?
It doesn't carry over directly. LiteLLM lets several deployments share one alias for load balancing or fallback; in Ragmux the closest equivalent is a route: a named entry point in a project whose targets are model connections, each with a weight and a priority. The client sends the route's name as model, and the gateway spreads requests across the targets and falls back to the next one on a failure.
Do I lose per-key dollar budgets moving off LiteLLM?
Yes, as a currency — LiteLLM's budgets are set and reported in dollars; Ragmux's rate_limit_rpm, rate_limit_tpm, budget_daily_tokens and budget_monthly_tokens are all token- or request-denominated. A dollar ceiling has to be converted to a token ceiling using your own provider's per-token price, and re-checked if that price changes.
Does migrating change how my application code calls the model?
No, as long as it was already calling an OpenAI-compatible /chat/completions endpoint, which LiteLLM's proxy also exposes. The change is base_url and api_key pointing at Ragmux and a project key instead of the LiteLLM proxy and a virtual key; the request and response bodies keep the same OpenAI shape.
Can I run Ragmux and LiteLLM side by side during the migration?
Yes, and it's the safer way to do this — nothing about adding a Ragmux connection touches the LiteLLM deployment it was copied from, so both can read the same upstream API key simultaneously while you compare responses, latency and error rates before moving production traffic over.
What LiteLLM features have no Ragmux equivalent at all?
Provider breadth past Ragmux's six provider types (custom_openai included), dollar-denominated budgets, and routing strategies beyond a route's weights and priorities (least-busy, latency-based, and similar) have no equivalent today. See the fuller comparison for what each project actually solves.

Sources

Product and provider names are trademarks of their respective owners.

Arrow keys to move, Enter to open.