cd /news/ai-infrastructure/what-is-an-ai-gateway-and-what-makes… · home › topics › ai-infrastructure › article
[ARTICLE · art-169385] src=dev.to ↗ pub= topic=ai-infrastructure verified=true sentiment=· neutral

What is an AI gateway, and what makes one European? OpenRouter vs Opper

A developer compared OpenRouter and Opper as two approaches to keeping LLM requests inside the EU, both reachable through the OpenAI-compatible SDK. OpenRouter enforces EU residency at the endpoint level (eu.openrouter.ai, limited to Business and Enterprise plans), while Opper, a Stockholm-based company, enforces it through org- or project-level model access rules and refuses ineligible routes with a 403 before reaching a provider. Both fail closed, but OpenRouter's docs note that account and billing records may still be processed in the US.

by read3 min views3 publishedNov 14, 2026

An AI gateway is a single API between your app and many LLM providers. Without one, you end up rebuilding the same plumbing: a key per provider, an SDK per provider, retries, fallbacks, and a bill from everyone. A gateway puts all of that behind one endpoint.

A European AI gateway is one that runs in Europe, specifically the EU, and can keep your requests there, from the gateway itself to the model that answers.

This is a short, high-level comparison. I use OpenRouter and Opper as the two examples because they keep requests in the EU in different ways, and you can try both with the same OpenAI SDK.

That covers most "should I use a gateway" decisions. Where it gets interesting is the data.

"EU-hosted" gets used loosely. In practice there are four separate questions:

Point 4 is the one people miss. Failover and data residency pull in opposite directions, so a European setup needs a way to say "fail over, but only inside this boundary".

OpenRouter Opper
Company Stripe (US), which acquired OpenRouter in 2026 Opper Technology AB, Stockholm, Sweden
OpenAI-compatible base URL https://openrouter.ai/api/v1 https://api.opper.ai/v3/compat
Keeping a request in the EU Call the EU endpoint https://eu.openrouter.ai/api/v1 , Business and Enterprise plans only Call an EU-hosted route on any account, or set a model access rule
Per-request data controls provider.zdr ,provider.data_collection ,provider.only /ignore The route you call, provider/model
Org-wide enforcement Privacy settings on the account Model access rule on the org or a project
No eligible route left The request errors instead of leaving the region Refused with 403 before it reaches a provider
Fee on credit purchases 5.5%, or 8% on Business, which the EU endpoint needs 3%, EU-hosted routes included (5.5% with Control Plane rules)

On OpenRouter you don't pick a European model for this. You call the EU endpoint with the usual model id, and it only uses provider endpoints in the EU/EEA, the UK or Switzerland, so fewer models are available than on the global endpoint.

Both fail closed, which is the right call. The difference is where the boundary lives. OpenRouter draws it at the endpoint you call. Opper draws it in a rule on your org or project, so every key and every app under it inherits the same boundary. One more detail from OpenRouter's own docs: with the EU endpoint, prompts and completions stay in the region, while account, billing and other operational records may be processed in the US.

Both speak the OpenAI API, so switching is a base URL and a model name.

OpenRouter, EU endpoint, zero data retention providers only:

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://eu.openrouter.ai/api/v1",
    api_key=os.environ["OPENROUTER_API_KEY"],
)

resp = client.chat.completions.create(
    model="mistralai/mistral-small-2603",
    messages=[{"role": "user", "content": "Summarise GDPR Article 28 in two sentences."}],
    extra_body={"provider": {"zdr": True, "data_collection": "deny"}},
)
print(resp.choices[0].message.content)

Opper, an EU-hosted route:

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.opper.ai/v3/compat",
    api_key=os.environ["OPPER_API_KEY"],
)

resp = client.chat.completions.create(
    model="mistral/mistral-small-2603",  # Mistral Small on Mistral's own EU route
    messages=[{"role": "user", "content": "Summarise GDPR Article 28 in two sentences."}],
)
print(resp.choices[0].message.content)

On Opper the model id carries the route as provider/model, and each route's data policy is in the public catalogue. https://api.opper.ai/v3/models?q=mistral-small-2603 lists every route for that model, and for the one above it returns "inference_location": "EU", "training": "no" and "logging": "none".

To make it a rule rather than a habit, a model access rule allowlists EU inference locations for the whole org or a project. A call that names a US route then comes back as:

403 model "anthropic/claude-sonnet-5" is blocked by the active model allowlist: inference location US is outside EU

A bare model name, like mistral-small-2603 without a provider, still fails over, but only across the allowed routes, and it's refused with 403 if none are left. That's point 4 handled in one place.

Docs if you want to dig in: OpenRouter EU in-region routing, Opper model access rules.

── more in #ai-infrastructure 4 stories · sorted by recency
── more on @openrouter 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/what-is-an-ai-gatewa…] indexed:0 read:3min 2026-11-14 · —