Heidelberg AICurriculum
Track 12 · Advanced
12.12

LiteLLM

Hands-on: stand up your own gateway, then break it on purpose

7 lessons 2026-08-13 AI-generated

1Overview

An open-source LLM proxy: one OpenAI-compatible endpoint in front of many providers, adding virtual keys, budgets, routing, fallbacks and a spend log.

The gateway chapter argues the case. This one is the keyboard: install LiteLLM, put two providers behind one endpoint, cut a virtual key for a colleague with a hard budget, watch the 429 arrive when they spend it, and read the log that says who spent what. → It follows the same shape as the other per-tool chapters in this course — one product, start to finish, with the parts that bite you called out rather than smoothed over. → Note before you start: LiteLLM was rearchitected onto a Rust core with a Python SDK, so guides written before that describe a different deployment.

One product, end to end. Install it, route through it, cut a budgeted key, break it deliberately, and read what it recorded. By the end you have a gateway a small team can actually use — and you have seen each failure mode before it finds you in production.

1.2After this chapter you can
Run LiteLLM locally and route one request through it
Put two providers behind a single OpenAI-compatible endpoint
Cut a virtual key with a hard budget and watch it refuse the request
Configure a fallback chain and prove it by taking a provider away
Read the spend log and attribute a cost spike to a caller
Route by task so bulk work never lands on the expensive model
Deploy it somewhere your team can reach, with its own failure plan
1.3When to reach for it

Two or more AI projects, or two or more providers, and nobody can currently say who is spending what.

1.4Key parts

The proxy, a config file listing model routes, a database for keys and spend, virtual keys with budgets, and a fallback chain.

1.5Free vs paid

The proxy is open source and self-hostable at the cost of one container and a database. There is also a paid enterprise tier; nothing in this chapter needs it.

1.6Watch out

It sits on the critical path of every AI call your organisation makes. Anything that takes the gateway down takes all of them down, so it needs its own availability plan before production traffic does.

2Lessons 7

2.1 Run the LiteLLM proxy and make a request

The litellm --config config.yaml command launches the LiteLLM proxy, exposing an OpenAI‑compatible endpoint that routes calls defined in a YAML file.

Start the LiteLLM gateway and receive a completion through it.

  1. Create a new empty folder and install the proxy with uv tool install 'litellm[proxy]'
  2. Add a file named config.yaml containing the model mapping and reference to the OpenAI API key environment variable
  3. Export your OpenAI key and start the gateway by running litellm --config config.yaml in the same terminal
  4. Open a second terminal and send a request with curl http://0.0.0.0:4000/chat/completions using a JSON payload
  • You'll see A normal OpenAI‑shaped JSON response appears in the second terminal and a request line is logged in the first terminal where the proxy runs
  • Takeaway The LiteLLM gateway provides a single process that routes model calls defined in a YAML file via /chat/completions or /v1/chat/completions
  • Check What does the litellm --config config.yaml command achieve when starting the LiteLLM gateway?
  • Cost Free to run the proxy itself. You pay your provider (OpenAI, in this example) for the actual tokens the test request used — a few fractions of a cent.

2.2 Call different models through the same endpoint

model_list entries in config.yaml define each provider that the proxy can route to.

Add a second provider to the configuration and invoke both models using identical request shapes, varying only the model name.

  1. Stop the running proxy by pressing Ctrl+C in its terminal
  2. Edit config.yaml to add a second entry under model_list with the new provider’s details
  3. Export the Anthropic key using export ANTHROPIC_API_KEY=your_key in the same terminal
  4. Restart the gateway with litellm --config config.yaml
  5. Send a request for the OpenAI model with curl, keeping the endpoint and headers unchanged and setting model to gpt-3.5-turbo
  6. Send a request for the Anthropic model with curl, changing only the model field to claude-haiku
  • You'll see Two responses from two distinct providers appear, each identifying its own model while the curl commands are otherwise identical
  • Takeaway Each new provider is added as another entry under model_list without altering the caller‑facing API
  • Check How does adding a second entry under model_list let you invoke different providers using identical request shapes?
  • Cost Free for the proxy config change. You pay each provider for its own request — two small charges instead of one.

2.3 Create a budget‑limited virtual key and trigger its exhaustion

A virtual API key created through /key/generate that includes a max_budget limit.

Generate a virtual key with a $0.01 spend limit, use it until the limit is reached, and observe the proxy’s budget‑exceeded error.

  1. Stop any running LiteLLM proxy and launch the quickstart stack with Docker using curl -sSL https://docs.litellm.ai/docker-compose.yml | docker compose -f - up -d
  2. Verify that both containers are active by running docker compose ps
  3. Locate the automatically generated master key in the downloaded docker‑compose.yml (or set your own by exporting LITELLM_MASTER_KEY before starting the stack)
  4. Generate a virtual key with a $0.01 budget by calling curl 'http://0.0.0.0:4000/key/generate' --header 'Authorization: Bearer ' --header 'Content-Type: application/json' --data-raw '{"models": ["gpt-3.5-turbo"], "max_budget": 0.01}'
  5. Use the returned virtual key to make several /chat/completions requests, authenticating with Authorization: Bearer until spend exceeds $0.01
  6. Observe the final response: the proxy returns HTTP 400 and a JSON error containing ExceededTokenBudget
  • You'll see Initial requests succeed, then the same endpoint returns HTTP 400 with an ExceededTokenBudget message once the budget is spent
  • Takeaway A virtual key with a max_budget returns a 400 ExceededTokenBudget error as soon as its allocated spend is exhausted
  • Check What response does the proxy return when a virtual key’s $0.01 max_budget is exceeded?
  • Cost A few cents of real provider spend to exhaust the test budget — that is the point of the lesson. Running the quickstart's Postgres container is free; it is one more local container.

2.4 Set up a fallback model and verify it triggers when the primary fails

litellm_settings.fallbacks maps a primary model like gpt‑3.5‑turbo to fallback models such as claude‑haiku.

Create a fallback from one model to another, break the primary key, and confirm the request still returns a 200 response.

  1. Add a litellm_settings.fallbacks block to config.yaml that maps gpt-3.5-turbo to ["claude-haiku"] and set num_retries: 1
  2. Edit the gpt-3.5-turbo entry’s api_key line so it references a non‑existent environment variable, e.g. api_key: os.environ/THIS_VAR_IS_NOT_SET
  3. Restart the LiteLLM proxy to load the modified configuration
  4. Send a request for model: "gpt-3.5-turbo" using curl as you normally would
  5. Inspect the JSON response; verify that the model field reports claude-haiku and the HTTP status is 200
  • You'll see An HTTP 200 with a valid answer where the JSON model field shows claude-haiku instead of the broken gpt-3.5-turbo
  • Takeaway fallbacks under litellm_settings redirects errors to alternate models without changing the caller’s request
  • Check When the primary model’s API key is invalid, how does the fallbacks setting affect the returned model field and HTTP status?
  • Cost One provider key deliberately broken costs nothing — no requests reach it. The fallback model bills normally for the requests it actually answers.

2.5 Identify which key and model caused a cost spike

The GET /spend/logs endpoint returns request‑level spend data for analysis.

Extract the request‑level spend log from the proxy and pinpoint the keys and models responsible for recent spending.

  1. Open a browser and navigate to http://0.0.0.0:4000/ui
  2. Select the Usage tab to view the spend table and chart
  3. Use the filter controls to narrow results by the virtual API key used in lesson 3
  4. Add a second filter for the model_group column to see which model actually answered each request
  5. Optionally, run curl 'http://0.0.0.0:4000/spend/logs?summarize=true' --header 'Authorization: Bearer ' to retrieve aggregated totals
  • You'll see A table of rows, one per request made in the chapter, each showing spend amount, model used and API key – including fallback requests logged as claude-haiku while the caller asked for gpt-3.5-turbo
  • Takeaway The spend logs turn anonymous cost increases into concrete key‑model request data
  • Check Which endpoint or UI feature lets you filter spend logs to pinpoint the virtual key and model responsible for a cost increase?
  • Cost Free — reading the log costs nothing beyond what the underlying requests already cost.

2.6 Expose model groups by task name

model_name assigns a custom label (e.g., bulk-classify) to a provider model.

Expose two model groups by task name instead of by model name, so an application asks for "bulk" or "judgment" and the config decides what actually answers.

  1. Edit config.yaml to add entries with model_name: bulk-classify and model_name: judgment-review, each pointing to the desired provider model under litellm_params
  2. Restart the LiteLLM proxy so it reloads the updated configuration
  3. Send a request using "model": "bulk-classify" and another using "model": "judgment-review" in the same JSON shape as previous lessons
  • You'll see Two calls with different task‑shaped model names resolve to two different real models and appear as separate rows in the spend log showing the actual model used
  • Takeaway A model_name is just a label you choose, so naming it by task lets you swap underlying models later without changing any caller code
  • Check How does defining a model_name like bulk-classify in config.yaml change the way callers specify tasks versus concrete provider models?
  • Cost No new cost — same requests as lesson 2, renamed. The saving this pattern buys is routing volume to the cheap group instead of defaulting everything to the expensive one, which only pays off once real call volume goes through it.

2.7 Run LiteLLM as a reachable, fault‑tolerant service

The /health/readiness endpoint reports the proxy’s readiness status.

Turn your local LiteLLM container into a network‑accessible service that survives failures.

  1. Run docker run -v $(pwd)/config.yaml:/app/config.yaml -e OPENAI_API_KEY -e LITELLM_MASTER_KEY -p 4000:4000 docker.litellm.ai/berriai/litellm:latest --config /app/config.yaml with your real key values
  2. From a second machine, execute curl http://:4000/v1/chat/completions … to confirm the API is reachable
  3. Check the health endpoint by running curl http://:4000/health/readiness and verify it returns 200 OK
  4. Document the on‑call owner who will be paged if the gateway becomes unreachable
  • You'll see A curl request from another machine returns a normal response and the /health/readiness endpoint returns 200 OK
  • Takeaway Deploying the stateless proxy behind a load balancer with shared storage removes the gateway as a single point of failure
  • Check What HTTP status code indicates the LiteLLM service is ready when querying /health/readiness after container deployment?
  • Cost One always-on container (or two-plus, once you take replicas seriously) plus a managed or self-hosted Postgres — the same shape as any other small production service, not something specific to LiteLLM.

3You’ll know it worked 12 checkable outcomes in this chapter

  • curl http://localhost:4000/v1/chat/completions with model=anthropic.claude works and returns a response
  • An API call with the key after the quota is spent returns status 429 and the server log shows the offending key ID
  • The model appears in the “Models & Endpoints” list and shows a success toast after adding.
  • After restarting the container with the config mounted, the models appear in the dashboard without manual UI entry.
  • The third rapid request returns an error like “current limit has hit”, and the dashboard shows a log entry for that attempt.
  • Opening http://localhost:4000 in a browser shows the Swagger UI and health endpoint returns OK
  • Using the generated key to call /v1/chat/completions for any other model returns “key not allowed to access model” and spending stops once $10 is reached (observed in usage tab)
  • The API call returns status code 429 with message “budget exhausted” and the dashboard’s Usage tab shows total spent = $10

12 outcomes in all — one per recipe below.

4FAQ, Tips & How-to 12

one problem, one solution, one action
How-to Everyone

Multiple AI models behind one URL

LiteLLM can run as a Dockerized proxy that normalizes API calls to different LLM providers. By defining each provider in the config file you expose a single endpoint that forwards requests to the chosen backend, simplifying client code.

Better Stack ↗ Lesson → AI-generated
How-to Everyone

Want to limit API spend

The LiteLLM UI lets you generate API keys (virtual keys) with per‑key quotas. When a user exceeds the allocated request count or token budget, LiteLLM returns HTTP 429 and logs the overage, enabling precise cost control.

Better Stack ↗ Lesson → AI-generated
How-to Everyone

Need a local LLM API you can call

Docker provides an isolated environment for LiteLLM, ensuring all dependencies are met and the service runs consistently across machines. Starting the container exposes the API on localhost:4000, ready for configuration.

KeyLabz ↗ Lesson → AI-generated
How-to Everyone

Want to add a new AI model without touching code

The dashboard lets you register external LLM providers without editing code. Selecting a provider, entering its API key, and saving creates a model entry that LiteLLM can route requests to.

KeyLabz ↗ Lesson → AI-generated
How-to Everyone

Need to define multiple models without manual entry

A configuration file allows bulk model definitions and version‑controlled setup, which the Docker container can read at startup to auto‑populate models.

KeyLabz ↗ Lesson → AI-generated
How-to Everyone

Need to stop AI costs from exploding

Virtual keys let you grant scoped access to specific models and enforce spending caps, preventing runaway costs. The dashboard captures these constraints per key.

KeyLabz ↗ Lesson → AI-generated
How-to Everyone

More than two requests per minute hit the limit

Rate limits protect APIs from overload. LiteLLM enforces per‑key RPM/TPM caps and records each request with metadata, enabling audit trails.

KeyLabz ↗ Lesson → AI-generated
How-to Everyone

I need a local OpenAI‑compatible API

The video shows how to clone the LiteLLM repo, set a master key and salt in .env, then launch the proxy with Docker Compose. This creates a local HTTP server (default port 4000) that serves the OpenAI‑compatible API for all configured models.

Data Science Basics ↗ Lesson → AI-generated
How-to Everyone

Need to call both OpenAI and Groq models

After the proxy is running, the admin UI lets you register multiple LLM providers. By entering each provider’s API key and selecting a model (e.g., GPT‑4.1 mini for OpenAI, Llama 3 for Groq), the gateway can route requests to either backend using the same OpenAI‑compatible endpoint.

Data Science Basics ↗ Lesson → AI-generated
How-to Everyone

Need a team API key that can’t overspend or see other models

The UI’s Virtual Keys page lets you generate per‑team secret keys that are scoped to specific models and can enforce a dollar budget. This isolates teams (e.g., Finance) so they only see the Groq model and cannot exceed $10 spend.

Data Science Basics ↗ Lesson → AI-generated
How-to Everyone

Budget runs out after repeated requests

When the Finance virtual key’s $10 budget is exhausted, LiteLLM returns HTTP 429 Too Many Requests. The video demonstrates sending repeated requests until the limit is hit and then checking the logs for the exact spend and offending request.

Data Science Basics ↗ Lesson → AI-generated
Tip Everyone

LiteLLM Logging — view per‑request logs showing who spent what

The gateway records each request with model, token usage, team, and API key identifier. The video shows navigating to Logs in the UI to see a table where you can filter by virtual key or team and see exact token counts and dollar cost.

The same set on /recipes, filtered by tool and role.

5See also

💬 Discuss this chapter

Ask, share, or report — over on the Heidelberg AI community forum.