The LLM gateway is the control point job postings now name explicitly: one OpenAI-compatible endpoint in front of every provider and your self-hosted models, with per-team keys, budgets, rate limits, model allowlists, and automatic fallbacks.
Tier: Advanced · Workflow area: Platform-for-AI: serving & gateways
This playbook deploys LiteLLM (self-hosted, MIT-licensed) as that layer, so no application ever holds a raw provider key and no team can silently blow the AI budget.
Skip a gateway when exactly one app calls one provider under one budget — wrap the SDK and revisit at the second consumer.
litellm (the proxy image) plus a Postgres database (required for virtual keys and spend tracking; DATABASE_URL).LITELLM_MASTER_KEY (must start with sk-) — treat it like a cloud root credential.Write the config: models, routing, fallbacks.
# litellm-config.yaml
model_list:
- model_name: chat-default # user-facing alias
litellm_params:
model: anthropic/claude-sonnet-4-6
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: chat-default # same alias = load-balanced group
litellm_params:
model: bedrock/anthropic.claude-sonnet-4-6
aws_region_name: us-east-1
- model_name: chat-local
litellm_params:
model: hosted_vllm/Qwen/Qwen2.5-7B-Instruct
api_base: http://vllm-qwen.ml.svc:8000/v1
litellm_settings:
fallbacks: [{"chat-default": ["chat-local"]}]
num_retries: 2
request_timeout: 120
router_settings:
routing_strategy: usage-based-routing
general_settings:
master_key: os.environ/LITELLM_MASTER_KEY
Aliases are the contract with app teams; providers behind an alias can change without breaking anyone. Verify exact field names against the LiteLLM docs for your pinned version — the config surface evolves.
Deploy with Postgres and pin the version. docker run/Helm with DATABASE_URL and the config mounted. Pin the image tag; gateway upgrades are change-managed like any other prod middleware.
Mint virtual keys per team, with budgets attached.
curl http://gateway:4000/key/generate \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H 'Content-Type: application/json' \
-d '{
"team_id": "checkout-squad",
"models": ["chat-default"],
"max_budget": 200.0,
"budget_duration": "30d",
"tpm_limit": 200000,
"rpm_limit": 500,
"metadata": {"service": "support-bot", "env": "prod"}
}'
One key per service per environment. The models allowlist is your first guardrail: a team without chat-local access cannot route client data to the wrong tenancy even by accident.
Point apps at the gateway. Apps use any OpenAI-compatible SDK with base_url=http://gateway:4000 and their virtual key. Confiscate raw provider keys from app configs — rotate them so old copies die.
Prove the failure modes before your users find them. Three drills: (a) exhaust a test key's max_budget and confirm requests 4xx with a budget error; (b) exceed rpm_limit and confirm 429s; (c) break the primary provider (bad key in staging) and confirm fallback serves traffic — and that the fallback event is visible in logs/alerts, because silent fallback to a weaker model is a quality incident.
Wire spend reporting. Per-key/team spend accrues in the database; export to your FinOps dashboards and alert at 80% of budget. This is the cost-per-team number your leadership asks for (feeds pb-46's observability layer).
The master key can mint unlimited spend — vault it, scope admin UI access, rotate on personnel change, and never bake it into an image.
max_budget stops spend after it happens up to the cap. Pair with tpm_limit/rpm_limit to cap burn rate, not just the monthly total.This layer is the services-company superpower: route by data classification.
models list contains only in-VPC targets (client's Bedrock/Azure OpenAI tenancy, or the pb-43 vLLM). General workloads get hosted-provider aliases. Policy becomes enforceable config, not a wiki page."Which model may see which data" stops being a training slide and becomes a key's model allowlist — that is the whole point of owning the gateway.