Self-hosting an OpenAI-compatible LLM gateway with LiteLLM
By Mike Perry, Founder & Editor-in-Chief · Published 2026-04-21 · Updated 2026-09-30 · 2 min read
One API shape in your code. model="gpt-4o" vs model="claude-opus-4" vs model="ollama/qwen3:32b" — same client library, same request format. Rate
Every LLM app you write can pretend it's calling OpenAI. LiteLLM makes that true by routing OpenAI-shaped requests to whatever backend you actually want.
Why you want this
One API shape in your code. model="gpt-4o" vs model="claude-opus-4" vs model="ollama/qwen3:32b" — same client library, same request format.
Postgres for spend persistence. Without it, restarts wipe your spend history.
Redis for caching. 300-second TTL matches Anthropic's ephemeral cache window.
Fallback ladder goes cloud → cloud → local. Primary-model Slack alert at $300 spend over 30 days.
Virtual keys per team. Issue via /key/generate endpoint; track spend per key.
How public benchmarks show and compared
The SpecPicks pipeline runs exactly this config (minus the Slack alerting URL) against ~50k generations/month. Patterns are cross-referenced with the LiteLLM documentation and community discussions. For the self-hosted-Claude-proxy complement, see our self-hosted Claude proxy guide.
Virtual-key workflow (issuing per-team access)
bash
# Create a key with a $50/month cap for "team-a"
curl -X POST http://localhost:4000/key/generate \
-H "Authorization: Bearer ${MASTER_KEY}" \
-H "Content-Type: application/json" \
-d '{
"metadata": {"team": "team-a"},
"max_budget": 50,
"budget_duration": "30d",
"models": ["gpt-4o", "claude-sonnet"]
}'
# → returns sk-proxy-xxx that team-a uses as their "OpenAI API key"
Now team-a's developers set OPENAI_API_KEY=sk-proxy-xxx and OPENAI_BASE_URL=http://litellm-internal:4000. They see no change in their code; LiteLLM handles everything.
Caching patterns that actually work
Long system prompt, short user turns. The biggest wins. Stable system prompt becomes a cache hit on every turn. 40-60% cost reduction common.
Document Q&A with stable corpus. If the retrieved chunks are stable across requests, cache hits are high. Implement retrieval deterministically to maximise this.
Agent tool definitions. Lots of agents have 500-2000 tokens of tool schema. Perfect cache-hit candidate.
Cache misses are common in:
Agent loops with timestamps or random IDs embedded in prompts.
Multi-user workflows where user ID is interpolated early in the system prompt.
Streaming use cases that hash differently per chunk — unintuitive but observed.
Three failure modes
1. LiteLLM shows zero cache hits. Redis is unreachable or misconfigured. Check docker logs litellm | grep -i cache; expected: Cache: initialized Redis connection.
2. Spend tracking shows 0.0 USD forever.database_url isn't set. LiteLLM silently runs in-memory without it.
3. Stream responses hang. Some backends don't support streaming with all params. Set drop_params: true in litellm_settings — lets unsupported params (e.g. OpenAI-specific seed on Anthropic) be silently dropped instead of erroring.
One CPU To Rule Them All - Ryzen 7 9800X3D Review — Linus Tech Tips on YouTube
Frequently asked questions
What are the main benefits of using LiteLLM as a self-hosted proxy?
LiteLLM offers a unified API shape for multiple LLM backends, enabling developers to use the same client library regardless of the model. It includes features like rate limiting, spend tracking, fallback routing, and cost-based routing. These capabilities make it easier to manage multiple models and optimize costs while maintaining consistent application behavior.
How does LiteLLM handle fallback routing between models?
LiteLLM allows users to configure fallback routes in its `config.yaml`. If the primary model fails, requests are automatically routed to secondary models in the specified order. This ensures high availability and reliability, even if one backend becomes temporarily unavailable.
What caching strategies work best with LiteLLM?
Effective caching strategies include using long, stable system prompts and deterministic retrieval for document Q&A tasks. These patterns maximize cache hits, reducing costs by up to 40-60%. However, cache misses are more common in scenarios like agent loops with dynamic prompts or streaming use cases with variable chunk hashes.
What are the common failure modes when using LiteLLM?
Three common issues include zero cache hits due to Redis misconfiguration, spend tracking showing 0.0 USD if `database_url` is unset, and stream responses hanging when unsupported parameters are passed to certain backends. These can be resolved by checking logs, setting a persistent database, and enabling the `drop_params` option.
Can LiteLLM be used in multi-tenant environments?
Yes, LiteLLM supports multi-tenancy by allowing the creation of virtual keys for different teams. Each key can have its own budget, duration, and model access restrictions. This enables independent spend tracking and access control for multiple teams sharing the same LiteLLM instance.