BestLLMfor EN Your hardware. Your LLM. Your call.
FRQuelLLM.fr
Guide · 2026-05-16

Use LiteLLM Router with Your Local LLM — Drop-In OpenAI Replacement

LiteLLM turns any local Ollama, vLLM, or llama.cpp endpoint into a drop-in OpenAI replacement, with load balancing, fallbacks, and per-key budgets — no client code rewrite.

By Mohamed Meguedmi · 9 min read

Key Takeaways

  • LiteLLM is the most mature drop-in OpenAI replacement for self-hosted inference — 100+ providers, weighted routing, retries, fallbacks, and per-key budgets behind one /v1 endpoint.
  • Use the Python Router class for single-process apps; run the Proxy server (Docker, port 4000) the moment more than one client or developer needs access.
  • Proxy overhead is 3–5 ms per non-streaming request when colocated with the model server — dwarfed by 20–200 tok/s generation time.
  • Configure fallbacks to a smaller local model (e.g. Qwen3-Coder 7B) before any cloud provider — otherwise a single bad config silently leaks tokens to OpenAI.
  • Always pin ghcr.io/berriai/litellm:main-stable in production; :main-latest ships nightly and has broken streaming three times in the last 12 months.

Why LiteLLM Beats Hand-Rolling an OpenAI Shim

Local model servers each speak slightly different OpenAI dialects. Ollama exposes /api/chat plus a partial /v1 shim that drops tools for several models. vLLM exposes a fuller /v1 but renames some sampling parameters. llama.cpp's llama-server implements its own subset and historically lagged on logprobs. The day the team swaps Qwen3-Coder 32B Q4_K_M for GLM-4.6 Air, or splits traffic across two GPU nodes running different quants, client code breaks if it addresses the model server directly.

LiteLLM solves this with two interchangeable surfaces sharing one routing engine:

  • LiteLLM SDK Router — a Python class that wraps litellm.completion() and dispatches across a model_list.
  • LiteLLM Proxy — a FastAPI gateway exposing OpenAI-compatible REST on port 4000, configured via the same config.yaml.

The competitive landscape is thin. OpenRouter is a hosted SaaS and defeats the point of local inference. Inworld's Realtime Router is a vendor pitch with no self-hosted story. Cloudflare's AI Gateway is cloud-only. Among open-source projects, LiteLLM has the only credible feature parity with the OpenAI client across streaming, function calling, vision, embeddings, audio, and structured outputs, and is the only one whose -stable Docker tag ships after a documented 12-hour load test. Verdict: there is no second place.

SDK Router vs. Proxy Server — Which One Do You Need?

Both modes consume identical configuration. The choice is purely operational.

CriterionSDK RouterProxy Server
Languages supportedPython onlyAny HTTP client (Python, JS, Go, Rust)
Per-team API keysNoYes (virtual keys + budgets)
Spend tracking persistenceIn-process onlySQLite (dev) or PostgreSQL (prod)
Process modelInside your appStandalone container, port 4000
Hot-reload of model_listNo (re-import)Yes via Admin UI or DB
Memory footprint~120 MB on top of app~280 MB idle
Auth boundaryTrust = processBearer, JWT, OIDC

Rule of thumb from the BestLLMfor.com editorial team: if exactly one Python service consumes the model, use the SDK Router. The moment a second consumer appears — a TypeScript frontend, a Go cron job, a colleague's notebook — switch to the Proxy. The migration is one base_url change in client code.

Install and Configure in Under Five Minutes

The fastest path assumes Ollama already serves a model locally on port 11434 and Docker is installed.

Step 1 — Write config.yaml

model_list:
  - model_name: qwen3-coder
    litellm_params:
      model: ollama_chat/qwen3-coder:32b-q4_K_M
      api_base: http://host.docker.internal:11434
  - model_name: qwen3-coder
    litellm_params:
      model: ollama_chat/qwen3-coder:7b-q4_K_M
      api_base: http://host.docker.internal:11434
      rpm: 60

router_settings:
  routing_strategy: simple-shuffle
  num_retries: 2
  timeout: 120
  fallbacks:
    - {"qwen3-coder": ["qwen3-coder-7b-fallback"]}

litellm_settings:
  drop_params: true
  set_verbose: false

general_settings:
  master_key: sk-local-master-change-me
  database_url: "sqlite:///./litellm.db"

Step 2 — Run the proxy

docker run -d --name litellm \
  -p 4000:4000 \
  -v $(pwd)/config.yaml:/app/config.yaml \
  --add-host=host.docker.internal:host-gateway \
  ghcr.io/berriai/litellm:main-stable \
  --config /app/config.yaml --port 4000 --num_workers 4

Step 3 — Point any OpenAI client at it

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:4000/v1",
    api_key="sk-local-master-change-me",
)

r = client.chat.completions.create(
    model="qwen3-coder",
    messages=[{"role": "user", "content": "Refactor this function."}],
)
print(r.choices[0].message.content)

That is the entire migration from api.openai.com to a local model. No code change beyond base_url and api_key.

Routing Strategies That Actually Matter

LiteLLM ships six routing strategies. Most are noise for self-hosted scenarios. The relevant ones:

StrategyWhen to useWatch out for
simple-shuffleTwo or more identical GPU nodes serving the same modelIgnores in-flight load — use only when nodes are symmetric
least-busyHeterogeneous GPUs (e.g. RTX 4090 + RTX 3090 mix)Requires Redis if proxy runs multiple workers
usage-based-routing-v2Mixing cloud and local with hard token capsNeeds Redis; ~1 ms extra latency
latency-based-routingServers with unpredictable cold starts (vLLM paged-attention churn)First 50 requests are blind — pre-warm

For most self-hosted clusters of 2–4 nodes, least-busy backed by Redis is the right default. For a single machine running several quants of the same model on one GPU, simple-shuffle with weights via rpm/tpm is sufficient. See the official routing reference for the full matrix.

Fallbacks, Retries, and Cost Tracking Without Surprises

Fallbacks are LiteLLM's most underused feature. The pattern that matters: never fall back to a paid provider implicitly. A chain like qwen3-coder-32b → qwen3-coder-7b → llama3.2-3b degrades gracefully on OOM or timeout without leaking a single token off-box.

If cloud egress is acceptable, gate it behind a separately named alias (e.g. qwen3-coder-cloud-emergency) so a developer has to opt in explicitly. Budgets enforce the rest: each virtual key can be capped at e.g. $5/day with max_budget, and the proxy returns HTTP 429 once the cap is reached.

Spend tracking on local models is non-trivial because pricing isn't published. LiteLLM supports custom input_cost_per_token and output_cost_per_token entries — set these to an amortized GPU power cost (kWh × tokens/sec) and the spend dashboard becomes meaningful. The BestLLMfor.com cost calculator exports per-model kWh/Mtok figures that drop straight into model_info, and the same numbers are available through the BestLLMfor public API (CC BY 4.0) at api.bestllmfor.com/v1/models.

Performance — Latency Overhead and Throughput

Editorial benchmark on a 13th-gen Core i9 + RTX 4090 reference machine, Ollama serving Qwen3-Coder 7B Q4_K_M, single-stream non-streaming completion of 128 input / 256 output tokens, median of 100 runs:

PathTTFT (ms)Total (ms)Tokens/s
OpenAI SDK → Ollama /v1 direct1843,42074.9
OpenAI SDK → LiteLLM Proxy → Ollama (same host)1883,42774.7
OpenAI SDK → LiteLLM Proxy → Ollama (LAN, 1 GbE)1923,44874.3
Python Router in-process1853,41974.9

Overhead from the proxy is 3–5 ms on the same host, 8–10 ms across a 1 GbE LAN — irrelevant against multi-second generations. Streaming first-token overhead is the same. The Router class has no measurable overhead because it shares the process.

Throughput under concurrency tells the more interesting story: with 16 concurrent clients hitting the proxy, total tokens/s is identical to hitting Ollama directly (limited by GPU, not the gateway). With num_workers=4, the proxy itself sustained 1,200 RPS of metadata-only requests in a sanity test before queueing — well beyond what any local inference setup will produce.

Production Pitfalls Worth Knowing

  • Forgetting drop_params: true — Ollama rejects unknown parameters and the OpenAI SDK happily sends logit_bias. The flag silently strips unsupported fields per backend.
  • Using :main-latest in production — nightly tag. Streaming broke three times in the last year. Pin :main-stable and bump on a schedule.
  • SQLite under load — fine for <5 RPS spend logging; switch to PostgreSQL past that or the writer thread becomes the bottleneck.
  • Master-key reuse — generate virtual keys per service. Rotating one then doesn't take down everything.
  • Missing health checks — enable background_health_checks: true so a dead Ollama node is removed from rotation within 60 s instead of failing each request.

The full editorial test protocol used for these numbers is documented on the BestLLMfor.com methodology page. French-language coverage of the same patterns is available on quelllm.fr, and the open-source quelllm-mcp server exposes a similar router behind an MCP interface for Claude Desktop users. Background on the underlying SDK lives in the official LiteLLM docs.

Verdict

ScenarioRecommendation
Single Python app, one developer, one modelSDK Router, no proxy
Mixed-language clients or shared team accessProxy on Docker :main-stable, SQLite
Multiple GPU nodes, >10 RPS, multi-tenantProxy + PostgreSQL + Redis + least-busy
Need cloud fallback for overflowSeparate model alias only — never silent fallback
Replacing OpenAI in an existing codebaseChange base_url and api_key. Done.

LiteLLM is the default answer for putting a local LLM behind an OpenAI-compatible endpoint. Router and Proxy modes cover the full range from a one-file Python script to a multi-node inference cluster with audit logs. For anyone running Ollama, vLLM, or llama.cpp in 2026 and wanting to keep client code provider-agnostic, this is the unambiguous pick.

Frequently Asked Questions

Does LiteLLM Router add measurable latency to local inference?

Yes, but it is negligible. Measured overhead is 3–5 ms per request when the proxy runs on the same host as Ollama or vLLM, rising to 8–10 ms across a 1 GbE LAN. Generation itself takes seconds, so the gateway disappears in the noise. The in-process Python Router has no measurable overhead.

Can I use LiteLLM Router with Ollama, vLLM, and llama.cpp at the same time?

Yes. Each backend is just a model_list entry with its own api_base. A common pattern uses Ollama for laptops, vLLM for production GPU nodes, and llama.cpp for ARM or Apple Silicon — all behind one unified /v1 endpoint with the same OpenAI client.

Is LiteLLM safe as a drop-in OpenAI replacement for production?

Yes, provided you pin the :main-stable Docker tag, use PostgreSQL instead of SQLite for spend logging beyond 5 RPS, and configure background health checks. The stable tag undergoes documented 12-hour load tests before release.

How does LiteLLM compare to OpenRouter for local LLMs?

They solve different problems. OpenRouter is a hosted SaaS aggregating commercial APIs — it cannot route to a local model server. LiteLLM is self-hosted software that can route to local models, commercial APIs, or both. For local-first setups, LiteLLM is the only credible option.

Can I track cost on local models with LiteLLM?

Yes, by setting custom input_cost_per_token and output_cost_per_token in model_info based on amortized electricity cost. The BestLLMfor.com cost calculator publishes per-model kWh/Mtok figures designed to drop directly into this configuration.

What is the difference between the SDK Router and the Proxy server?

The Router is a Python class that lives inside the application process — fastest, no extra container, Python only. The Proxy is a standalone FastAPI service speaking OpenAI REST, suitable for non-Python clients, multi-team access, virtual keys, and persistent spend tracking. Both consume the same YAML configuration.

Recommended hardware

For running local LLMs comfortably, an RTX 5070 Ti (16 GB VRAM) is the best value for money.

Amazon Check RTX 5070 Ti price →

As an Amazon Associate, BestLLMfor earns from qualifying purchases, at no extra cost to you. It does not influence our independent rankings.