The LiteLLM proxy, run the way an enterprise has to run it
LiteLLM proxy is the self-hosted gateway that puts one OpenAI-compatible API in front of many providers. A default install is one master key and no spend attribution. Production means Docker, virtual keys, per-team budgets and monitoring before the first call. Pexon runs LiteLLM for control in EU estates, not to undercut OpenRouter on price.
The quickstart gives you a running proxy. It does not give you a deployable one.
LiteLLM proxy is an open-source gateway that puts one OpenAI-compatible API in front of many model providers. You define the models in a config file, your applications call a single endpoint, and the gateway handles routing, load balancing, fallbacks and cost tracking behind it. The README path to a running instance takes about ten minutes, and it is the wrong path for anything that will outlive a demo, because a default LiteLLM deployment is one master key, one config file and no idea who spent what.
The enterprise setup is not a bigger version of the quickstart. It is a different configuration, and this guide walks through it in the order we run it in customer estates: the docker-compose skeleton, the config with model routes, virtual keys instead of the master key, budgets and limits per team, monitoring before the first incident, and routing rules with fallbacks as the cost control.
One disclaimer up front, because it decides how you read everything below. A self-hosted gateway with real availability is usually more expensive per token than a SaaS aggregator for the first year, and anyone who tells you otherwise is comparing a GPU rental price against a list price. You run LiteLLM for control: your keys, your logs, your infrastructure, your DSGVO story. The engineering below is about making that control real rather than nominal.
Sequence
The setup order we run in, and why it is that order
- Deploy the container before you write a single route. The image runs anywhere Docker runs. Pin the tag, mount a config directory, and make the health endpoint reachable before any application points at it. A proxy that cannot answer /health has no business being configured.
- Write the config with provider keys in the environment, never in the file. config.yaml declares model names, providers and routing rules. The keys themselves come from environment variables or a secrets manager, so the config file is safe to commit and review.
- Create virtual keys and throw the master key away from day one. Every application and every team gets its own virtual key. The master key then exists only to mint and revoke virtual keys, and nobody's code ever sees it. This is the single control that makes every later one possible.
- Set budgets and limits per team before the first user. LiteLLM supports per-key budgets, per-team limits and model access rules. Configure the containment before the traffic: a limit you add after the incident is a post-mortem, not a control.
- Stand up monitoring before the second team joins. Cost, tokens, latency and error rate per model and per team, on a dashboard the operator actually opens. The metrics exist in the proxy; the work is deciding who looks at them and when.
Executable artefact
The docker-compose skeleton and the config that goes with it
Versions are placeholders; pin whatever is current when you deploy. The shape is the point: environment for keys, volume for config, healthcheck that makes the proxy observable.
# docker-compose.yml — the enterprise skeleton
services:
litellm:
image: ghcr.io/berriai/litellm:main-latest # pin a release tag in production
container_name: litellm
ports:
- "4000:4000"
environment:
- STORE_MODEL_IN_DB=false
- DATABASE_URL=postgresql://litellm:${DB_PASSWORD}@postgres:5432/litellm
# provider keys come from the environment, never from config.yaml
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- AZURE_API_KEY=${AZURE_API_KEY}
volumes:
- ./config.yaml:/app/config.yaml
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4000/health/liveliness"]
interval: 30s
timeout: 5s
retries: 3
# config.yaml — model routes only; keys stay in the environment
model_list:
- model_name: gpt-4o
litellm_params:
model: openai/gpt-4o
- model_name: claude-sonnet
litellm_params:
model: anthropic/claude-sonnet-4-20250514
- model_name: local-llama
litellm_params:
model: ollama/llama3.1:8b
api_base: http://ollama:11434 # self-hosted fallback on your own GPUs
litellm_settings:
drop_params: true
num_retries: 2
request_timeout: 600
general_settings:
master_key: ${LITELLM_MASTER_KEY} # used only to mint virtual keysThe healthcheck and the key separation are the two lines that separate this from the quickstart.
Security is virtual keys, budgets, RBAC and an audit trail — in that order
The security story of a LiteLLM deployment is mostly the story of what the master key is not used for. Virtual keys carry their own budgets, spend limits and model access, so a leaked application key costs you the exposure of one team's routes rather than the whole gateway. The master key, held by the platform team, exists to mint and revoke those keys and to change the config.
Budgets come second because they are the control that makes cost attribution real. A per-team budget turns the monthly invoice from a single line into a set of accounts you can defend at renewal, which is exactly the argument the FinOps team needs when the question is whether the gateway pays for itself. The audit trail comes third: who called which model, from which key, at what cost, on a log you can replay. LiteLLM writes this natively; the enterprise work is deciding retention and who may read it.
For European operators the fourth layer is where the gateway earns its keep. Self-hosted on your own infrastructure, with provider keys held in your environment and logs under your control, the data-sovereignty argument becomes concrete: the routing decision and the usage record live on hardware you operate. That is the difference between a defensible DSGVO story and a hand-wave at a SaaS provider's subprocessor list.
What the gateway cannot do is police the prompts themselves. Prompt injection and guardrail enforcement belong to the layer above — the tracing and guardrail stack the OWASP guidance for LLM applications points at. Treat LiteLLM as the transport control and buy the guardrail layer separately; pretending one product does both is how the incident happens.
Our position: a gateway without per-team budgets is an invoice with extra steps. The cost attribution is not a feature of the setup, it is the point of the setup.
Monitoring: the four numbers that decide whether the gateway is working
A LiteLLM deployment produces four numbers worth watching per model and per team, and they answer four different questions. Cost per team tells you whether the budgets are doing their job. Tokens per model tells you whether the routing rules are actually routing. Latency tells you whether a provider degradation is your problem or theirs. Error rate tells you whether the fallbacks are firing or silently failing.
The monitoring work is not in the metrics, which the proxy exposes natively, but in the decisions around them. Who is on call for a gateway that sits between every application and every model? What happens to the dashboard when nobody looks at it for a week? The answer we give customers is that a gateway is infrastructure, not a library: it gets an owner, an on-call rotation and a change process, and the monitoring dashboard is the visible part of that ownership.
The cost control follows from the same data. Routing rules that prefer a cheaper model for a task the expensive one does not need, fallback routes that catch a provider outage without a human being paged at 3am, and a model-priority policy that says which provider wins when two can serve the same request. None of this is exotic. All of it is configuration the quickstart does not have, which is the whole difference between running LiteLLM and running LiteLLM as infrastructure.
Gateway selection
LiteLLM vs OpenRouter vs Portkey vs self-built
| Dimension | LiteLLM (self-hosted) | OpenRouter (SaaS) | Portkey (managed) | Self-built |
|---|---|---|---|---|
| Operation | Self-hosted open source; you run it | Hosted aggregator; you pay per token | Managed gateway; SaaS with caching and guardrails | You build and operate everything |
| Data sovereignty | Your infrastructure, your logs, your keys | Traffic leaves your estate | Traffic flows through a third party | Complete, if you do it right |
| Setup effort | A day for the skeleton, a week for the full control set | Minutes to an API key | Hours to a working route | Weeks, and the maintenance is forever |
| Cost shape | Free software; infra plus model fees | Per-token margin on top of model fees | Subscription plus usage | Engineer time plus infra |
| Best for | Regulated estates and multi-team cost control | Prototypes and low-sensitivity workloads | Teams that want guardrails without building them | Platform teams that already run everything |
Qualitative scoring only; prices change quarterly and depend on your model mix. The decision rule: if the answer to 'whose infrastructure processes this prompt' has to be 'ours', the SaaS options are out regardless of price.
The middle path we see most often: OpenRouter for the prototype, LiteLLM for the production estate, and the routing rule between them as the first real configuration. Nobody runs one gateway for long.
Questions we get asked when the proxy is already in a pilot
What is an LLM proxy and why would a company run one?
An LLM proxy is a gateway between your applications and the model providers. It bundles every API call through one endpoint, holds the provider keys in one place, and logs cost and usage per team and model. LiteLLM is the best-known open-source implementation: you define the available models in a config file, and applications only ever talk to a single OpenAI-compatible URL.
How do I install LiteLLM proxy?
The standard path is Docker: run the LiteLLM image, write a config.yaml that lists your model routes with their provider keys, and call the proxy endpoint. The full enterprise sequence — install, virtual keys, budgets, monitoring, routing — is what this guide walks through, with the config blocks you can copy into your own stack.
Is LiteLLM secure enough for enterprise use?
The gateway itself is only the software; security comes from how you operate it. The documented baseline is virtual keys instead of the master key, budgets and limits per team, RBAC on who can change routes, and an audit trail of who called what. Self-hosted on European infrastructure, those controls are what make a DSGVO-compliant setup arguable at all.
How does LiteLLM compare to OpenRouter or Portkey?
The difference is ownership. LiteLLM is self-hosted open source: your keys, your logs, your infrastructure, and your operational burden. OpenRouter is a SaaS aggregator you pay per token. Portkey is a managed gateway with caching and guardrails on top. The comparison table in this guide scores them on data sovereignty, setup effort and running cost.
What does running LiteLLM cost?
The software is free; the costs are the model API fees and the infrastructure you operate it on. Routing rules that prefer cheaper models and fallbacks that catch provider outages are where the gateway pays for itself. The honest statement is that a self-hosted gateway with real availability costs more to run than a SaaS aggregator, and you do it for control, not for the price tag.
Next step
Make the gateway decision once, with the monitoring already on
Two weeks, fixed price. We stand up the LiteLLM proxy with virtual keys, per-team budgets and a monitoring dashboard that answers the first incident question before it is asked, then hand you the config and the runbook. The setup is yours to keep whether or not we operate it.
