llm-integration.eu

LiteLLM EU Gateway: Claude via Bedrock

Self-host LiteLLM in the EU as a Claude gateway on Bedrock: port 4000, Postgres budgets that fail open without a database, and the eu.anthropic.claude-sonnet-5 profile.

Updated 8 min readFacts verified on 29 September 2026

TL;DR

LiteLLM is a self-hosted gateway in front of Claude. Run release v1.103.0 in your own EU network on port 4000, with Postgres, and call Bedrock as bedrock/eu.anthropic.claude-sonnet-5. That profile keeps Sonnet 5 data inside EU regions. OpenRouter may send personal data to US servers. A budget with no database does not stop spend.

What does a LiteLLM gateway change for an EU team?

LiteLLM Proxy is an OpenAI-compatible gateway you run yourself. Apps send one chat-completions request to your host. The proxy authenticates a virtual key, records spend, and forwards the call to Bedrock, Vertex, Anthropic or another provider. The CLI quick start says the server manages a unified interface for 100+ LLMs, cost tracking, virtual keys and load balancing, and that load tests passed 1,500 requests per second.

The EU decision is where that process runs. A gateway on a laptop, or on a US SaaS router, stores prompts and spend logs outside your control. A gateway on a VM in Frankfurt or Ireland, talking only to a Bedrock EU profile, keeps both the log and the model call in Europe. We recommend that split: LiteLLM for keys and budgets, Bedrock for the model. Our Amazon Bedrock EU guide covers which models actually have an EU profile. Pricing of the tokens behind the gateway is in our Claude API pricing EU comparison.

Code outside the enterprise/ directory is MIT, copyright 2023 Berri AI. The LICENSE puts anything under enterprise/ on a separate licence. Treat the open-source proxy as the piece you operate. Do not assume enterprise features are free because the GitHub repo is public.

Current release: v1.103.0, published 28 September 2026. LiteLLM 1.84.0 and newer require Python 3.10 or higher. A bare pip install on an older interpreter does not error. It silently resolves to 1.83.9, the last release that still allowed that Python. Check python --version before you install, or use uv tool install 'litellm[proxy]', which provisions a compatible interpreter.

How do you start LiteLLM with a database?

The Docker quick start is the setup we would actually run. One compose file brings up the gateway on port 4000 and a Postgres 16 database for models, virtual keys and spend logs. The image in that file is docker.litellm.ai/berriai/litellm:main-stable. The same page says that beyond local evaluation you should pin a release tag. main-stable will move. Pin v1.103.0 once you have tested it.

The proxy refuses to start without two secrets:

  1. Generate LITELLM_MASTER_KEY and LITELLM_SALT_KEY (the docs use openssl rand -hex 32 and an sk- prefix, which is a convention, not a requirement).
  2. Start compose. The gateway is at http://localhost:4000. The Admin UI is at /ui, username admin, password equal to the master key.
  3. Add the Bedrock model in the UI, or in config.yaml, using os.environ/... for the AWS keys so the raw key is not pasted into the database.
  4. Issue a virtual key per app. Send traffic to /chat/completions or /v1/chat/completions with that key.
  5. Keep the .env file. Regenerating LITELLM_SALT_KEY makes credentials already stored in Postgres unreadable. There is no in-place rotation.

LITELLM_MASTER_KEY is a root password. It authorises every management call and, by default, is the Admin UI password. Anyone who has it can create keys and read spend. Store it like a production secret, not in the compose file you commit.

Postgres in the quick start uses user, password and database name litellm. That is fine for a first boot on your laptop. It is not fine on a reachable host. Change the password, do not publish port 5432, and put the gateway behind your existing network controls. The database URL in the compose file is postgresql://litellm:litellm@db:5432/litellm, with STORE_MODEL_IN_DB set to true.

Which Bedrock model ID keeps Claude in the EU?

LiteLLM’s own Bedrock page shows this example: bedrock/us.anthropic.claude-sonnet-5, with AWS_REGION_NAME left for you to fill. Copying that string sends Sonnet 5 down the US geo profile. The Sonnet 5 model card is explicit about what each profile does.

Profile ID What AWS says about the data
eu.anthropic.claude-sonnet-5 EU geo: keeps data within EU regions
us.anthropic.claude-sonnet-5 US geo: keeps data within US and Canada
global.anthropic.claude-sonnet-5 Global: routes worldwide, no residency constraint
anthropic.claude-sonnet-5 Bare ID, only on the bedrock-mantle endpoint, not on bedrock-runtime on-demand

On bedrock-runtime, the bare model ID is rejected. AWS says geo and global profiles can route outside the source Region and do not provide single-Region data residency. EU geo is the residency control for a normal Bedrock runtime call. Single-Region Sonnet 5 uses bedrock-mantle and the bare ID. The mantle region list on that card includes eu-north-1 (Stockholm) and eu-west-1 (Ireland). Frankfurt (eu-central-1) is on the runtime region list, which is where you send the EU geo call from, not a promise of single-Region processing.

Anthropic’s Bedrock page says regional endpoints cost 10% more than global endpoints for Sonnet 4.5 and later models. That premium is the price of the EU profile. Token tables for the same 10% on Bedrock and Google Cloud are in our pricing article. Claude Code pointed at Bedrock rather than at this gateway is a different setup, covered in Claude Code on Bedrock.

model_list:
  - model_name: claude-eu
    litellm_params:
      model: bedrock/eu.anthropic.claude-sonnet-5
      aws_region_name: eu-central-1
      aws_access_key_id: os.environ/AWS_ACCESS_KEY_ID
      aws_secret_access_key: os.environ/AWS_SECRET_ACCESS_KEY

model_name is what your apps send (claude-eu). model is what LiteLLM sends to Bedrock. Use an IAM role on the instance where you can. Static keys in the environment are what the LiteLLM docs demonstrate, and they are the thing LITELLM_SALT_KEY encrypts if you store them through the UI.

Vertex is the other EU route. The CLI quick start documents VERTEX_PROJECT and VERTEX_LOCATION. Their sample location is us-west. Set the location to the EU multi-region or EU region where you already run Claude, then use a vertex_ai/ model string. Do not leave the sample us-west in a European config.

How do budgets stop a runaway key?

Every budget on the budgets page is enforced against spend read from the database. None of them cap anything on a deployment with no database. litellm_settings.max_budget fails open: global spend is only loaded when a database client exists, so with nothing to compare, the check is skipped and requests continue past the limit. A warning is logged once at startup. Key, team and user budgets are unavailable for the same reason. The error text is No connected db.

That is the failure mode that matters. A team adds max_budget: 100 to feel safe, runs the proxy without Postgres, and the cap never fires. The Docker quick start avoids this because Postgres is in the compose file. A one-line litellm --model ... from the CLI quick start does not.

With a database, provider budgets live under router_settings.provider_budget_config. The budget routing page shows limits in USD and periods such as 1d, 30d and 1mo. The documented examples include anthropic at 100 USD over 10 days and vertex_ai at 100 USD over 12 days. When a provider is over budget, the proxy skips it. If every provider is over budget, the caller gets HTTP 429 and a message of the form No deployments available - crossed budget for provider. Redis is required only when several proxy instances must share one spend counter. A single EU instance can track spend in Postgres alone.

Two further rules from the same budgets page, current as of v1.95.0. For a key that belongs to a team, the personal user budget is not enforced. The team budget applies. v1.94.0 briefly enforced both, behind a flag named skip_user_budget_on_team_key. v1.95.0 removed the flag and the extra check. And a model budget matches the name you configured plus the provider-prefixed form, so one cap can cover claude-sonnet and bedrock/eu.anthropic.claude-sonnet-5 if you set it on the family name you actually route.

We would set three limits, not one: a provider budget for bedrock or anthropic, a team budget per product, and a low max budget on any key used from a laptop. Check remaining spend at GET /provider/budgets with a key that is allowed to read it.

LiteLLM or OpenRouter for company data?

OpenRouter is a hosted router. LiteLLM is a process you run. The OpenRouter privacy policy says that when you use the service, personal data may be transferred to OpenRouter servers in the US, or to other countries outside the EEA and the UK. It also says any text you input that includes personal data is collected by OpenRouter. That can be acceptable for public prompts. It is a transfer for employee or customer text.

LiteLLM on your EU host OpenRouter
Who runs the gateway You OpenRouter
Where gateway logs sit Your Postgres Their service
Personal data, their own words You choose the region of the VM May go to US servers or outside the EEA and UK
Licence of the proxy MIT outside enterprise/ Hosted product
Spend cap Real only with a database Their account limits

We would not send EU personal data through OpenRouter when the same app can call a LiteLLM instance in your VPC. Use OpenRouter for experiments that contain no personal data. Use LiteLLM plus the EU geo profile when the prompt can name a person, a customer or an employee. The legal comparison of Claude providers, without the gateway in the middle, is our GDPR provider comparison.

FAQ

Does a LiteLLM budget work without Postgres?

No. Budgets are checked against spend in the database. Without a database, the global max budget fails open and key, team and user budgets do not exist. The Docker quick start includes Postgres 16 for this reason.

Is the LiteLLM Bedrock example safe for EU data?

No. The documented example model is bedrock/us.anthropic.claude-sonnet-5. AWS says that profile keeps data in the US and Canada. Use bedrock/eu.anthropic.claude-sonnet-5 when the call must stay in EU regions.

What is the difference between EU geo and single-Region Sonnet 5?

EU geo (eu.anthropic.claude-sonnet-5) keeps data within EU regions but can route across those regions. It does not promise one Region. Single-Region uses the bedrock-mantle endpoint and the bare model ID. Mantle’s listed EU regions on the Sonnet 5 card are Stockholm and Ireland.

Does the EU Bedrock route cost more than global?

Yes. Anthropic states that regional endpoints include a 10% premium over global endpoints for Sonnet 4.5 and later models. Global routing has no premium and no residency constraint.

LiteLLM versus OpenRouter: where can personal data go?

On LiteLLM, to whatever region you run the proxy and the model profile you select. On OpenRouter, the privacy policy allows a transfer to servers in the US or to countries outside the EEA and the UK, and Inputs that contain personal data are collected by OpenRouter.

Which LiteLLM version should a company pin?

v1.103.0, published 28 September 2026, unless a newer release has been tested. The Docker quick start image is main-stable, which moves. Python must be 3.10 or newer or pip will silently install 1.83.9.

Sources

  1. LiteLLM docs: CLI quick start (29 September 2026)
  2. LiteLLM docs: Docker quick start (29 September 2026)
  3. LiteLLM docs: Budgets and rate limits (29 September 2026)
  4. LiteLLM docs: Provider budget routing (29 September 2026)
  5. LiteLLM docs: AWS Bedrock (29 September 2026)
  6. BerriAI/litellm LICENSE (29 September 2026)
  7. BerriAI/litellm release v1.103.0 (29 September 2026)
  8. AWS: Claude Sonnet 5 model card (29 September 2026)
  9. Anthropic: Claude on Amazon Bedrock (29 September 2026)
  10. OpenRouter privacy policy (29 September 2026)

Related guides