Blog

OpenRouter vs LiteLLM vs Portkey: three different products, and the seven questions that pick one

Read from the three vendors' own docs on 2026-09-03: OpenRouter is a hosted model marketplace, LiteLLM an open-source proxy you run, Portkey a hosted gateway with a hybrid option. Seven questions about keys, bills, data, failover, protocols, upgrades and ownership, then a decision tree. No benchmarks.

Leo Kaka21 min read
Hand-drawn ink illustration: three different objects in a row, each delivering water into the same glass. A plumbed-in public drinking fountain on the left; a hand-built rig of copper pipe, valves and a pump on a wooden crate in the middle, its workings exposed with a toolbox beside it; a sealed brass cabinet on the right whose side hatch is open while a hand fits a yellow cartridge into it.

OpenRouter, LiteLLM and Portkey are not three answers to one question. They are three kinds of product, and which you should use depends on who holds the provider keys, who pays the provider, and who is allowed to see the prompts. OpenRouter is a hosted model marketplace: its key, its credits, its catalog. LiteLLM is an open-source proxy: you run it, you bring every provider key, and the vendor sells a license for extra controls on the same binary. Portkey is a hosted gateway: you bring provider keys, pay a subscription, and can move the data plane into your own VPC on Enterprise or run its MIT-licensed gateway alone.

Seen as three shapes, “which should I use” turns into seven questions about your situation, each with a different answer per shape. This post walks the seven, quoting the vendors’ own documentation as it read on 2026-09-03, and ends with a decision tree that branches on who you are. Where a document does not answer, the text says “the docs do not say” rather than guessing. There are no benchmarks here, by design; the section before the decision tree says what this comparison does not measure.

Three shapes, not three competitors

The vendors describe themselves precisely enough that a table of their own words does most of the work.

OpenRouterLiteLLMPortkey
ShapeHosted marketplace and gateway: “a unified API to access all the major LLM models,” billing “in one place” (FAQ)“OpenAI Proxy Server (LLM Gateway) to call 100+ LLMs in a unified interface & track spend, set budgets per virtual key/user” (LiteLLM AI Gateway (LLM Proxy))“a unified interface for interacting with over 250 AI models” (What is Portkey?)
Who runs the request pathOpenRouterYouPortkey, or your VPC on the Enterprise hybrid deployment, or you with the open-source gateway
Provider keyOpenRouter’s by default; BYOK optionalYoursYours, stored in Portkey’s Model Catalog
Open sourceNoMIT, except the enterprise/ directory (LICENSE)Gateway under MIT (LICENSE); control plane is not
Paid tierCredits plus a platform fee; Enterprise agreementsEnterprise license on the same self-hosted binaryFree, $49/month, Enterprise

Two shape details change the rest of the post.

LiteLLM’s paid product is a license, not a service. Its Enterprise page lists one deployment option, “Self-Hosted,” and states “No data leaves your environment” (Enterprise). The pricing page describes two tiers, Open Source at $0 “free to self-host, forever” and Enterprise “sized to your annual gateway request capacity, deployment architecture, and support needs — never per token” (Pricing). The GitHub README still links to a “Hosted Proxy” at an anchor named hosted-litellm-proxy on the Enterprise page (README); that anchor does not exist on the page as it read on 2026-09-03. So if you want someone else to run LiteLLM for you, the docs do not say what that looks like. Read it as self-hosted.

Portkey is three things wearing one name. The hosted service at api.portkey.ai is what the pricing page sells. The open-source gateway starts with npx @portkey-ai/gateway, and “You can also self-host the gateway and then connect it to Portkey” (AI Gateway). The Enterprise hybrid deployment splits the product: a “Data Plane runs within your VPC” and a “Control Plane hosted by Portkey handles administration, configs, and analytics” (Enterprise Architecture). The gateway README carries a note that “Portkey’s core enterprise gateway is merging into open-source with our 2.0 release,” marked pre-release (Gateway README); until that ships, several README features are footnoted “Available in hosted and enterprise versions.”

OpenRouter has one shape with an option. Bring-your-own-key changes which credential authenticates the upstream call, not who you contract with, which is the first question.

Matrix comparing OpenRouter, LiteLLM and Portkey on four rows read from their own documentation: product shape, who holds the provider key, what you pay, and whether prompts are kept
The four rows that decide the choice, in each vendor's own words. Read from their documentation on 2026-09-03.

Question 1: whose provider key, and whose contract with the provider

The key is the small version of the contract. Whoever holds it is the party the provider recognises, and the one who gets the notice when something changes.

OpenRouter holds it. Its Enterprise page sells exactly this: “Single API, single contract, unified billing” (Enterprise). The terms spell out what sits behind that single contract. Each model carries its provider’s “Model Terms,” which “may be modified, supplemented, or replaced from time to time by the applicable Model Provider,” and OpenRouter “may suspend, restrict, disable, or terminate” your access “if we are required or requested to do so by the applicable Model Provider,” without a guarantee of “advance notice in all circumstances” (Terms of Service, §5.3 and §5.5). Its own exit is broader: it may terminate an account “at any time for any reason or no reason, with or without notice,” and reserves “the right to modify or discontinue the Service at any time” (§9). Material changes to the terms get “thirty (30) days advance notice” (§11).

BYOK narrows the credential without touching the contract. Your key is tried first, always: “OpenRouter always prioritizes BYOK endpoints first, regardless of where that provider appears in your specified order … There is currently no way to change this behavior” (BYOK). When it fails, the default is to spend OpenRouter’s: “if all keys in both sections encounter a rate limit or failure, OpenRouter will fall back to using shared OpenRouter endpoints.” A three-level per-key switch runs from “Use shared capacity (default)” to “Never use shared capacity on this provider.” If your provider contract says traffic must go through your account, that switch is the one line of configuration that makes it true.

LiteLLM never sees the key as a party. Provider credentials live in your config.yaml or, encrypted, in your Postgres, behind one fragile secret: “set a salt key for encrypting and decrypting stored variables. Do not change it after adding a model; it encrypts your LLM API key credentials, and changing it makes them unreadable” (Production Best Practices). Each provider contract stays between you and the provider, and the Shared Responsibility Model files “Your provider accounts, quotas, and provider-side outages” under the column headed “You” (Shared Responsibility Model). Between you and LiteLLM there is the MIT license, plus an Enterprise agreement the public docs do not reproduce.

Portkey holds your keys for you. The Model Catalog turns “raw API keys and scattered environment variables into governed Provider Integrations,” each with “Securely stored credentials” and a slug you use as @openai-prod/gpt-4o (Model Catalog). Beyond “securely stored” the docs do not say where the hosted plan keeps them; the security page adds AES-256 at rest and TLS 1.2 or higher in transit (Security @ Portkey). On hybrid the control plane still owns the record: the gateway in your VPC fetches “Prompt templates, routing configs, integrations, providers, API keys” on a “1-minute heartbeat,” and “Deltas (changed items) are fetched, decrypted locally” (Enterprise Architecture). Your contract with the provider is yours. The place the credential is administered is theirs.

Last week’s post on the Cursor change-of-control clause made the general point: when your models arrive through someone else’s key, you are the third party to a two-party contract. OpenRouter is that arrangement by design and says so in its terms. LiteLLM is the opposite by construction. Portkey is your contract with the provider, administered from their console.

Question 2: where the bill lands, and where the budget is enforced

Three shapes, three billing relationships. Only one of them touches your money before the provider does.

OpenRouter is prepaid. You buy credits, and OpenRouter “pass[es] through the pricing of the underlying providers; there is no markup on inference pricing (however we do charge a fee when purchasing credits)” (FAQ). The fee is a rendered constant in the FAQ’s source, 5.5% ($0.80 minimum) for cards and 5% for crypto; the pricing page prints 5.5% as the Pay-as-you-go “Platform Fees” line and “Fee discounts available” under Enterprise (Pricing). Purchases run $5 to $25,000 per transaction, refunds close after 24 hours, and OpenRouter “reserves the right to expire unused credits three hundred sixty-five (365) days after purchase” (Terms of Service, §4.1 and §4.2). Two pricing-page answers matter for a cost model: “When routing/fallback is enabled, you’re billed only for the successful model run,” and on a provider price change “you will be charged at the new rate and your credits will deduct accordingly.” Budget enforcement is a key attribute, limit plus limit_reset, answered with 402 when spent (Limits). Team money is an organization credit pool where “Only organization administrators can purchase credits,” and “An organization can only have 10 members” (Organization Management). BYOK has its own meter: “$25,000 of list price inference / month with no fees, 5% fee after” on Pay-as-you-go, $200,000 on Enterprise.

LiteLLM never holds money. Providers bill you directly. What it sells is enforcement: virtual keys with max_budget, teams and users, all of which “Need a postgres database” and a master key that “must start with sk-” (Virtual Keys). The Enterprise license is “priced to your gateway’s scale, never per token” (Pricing). Whether a feature you rely on can later move behind that license is answered by the Migration Policy: a beta feature moving to Enterprise gets “at least 30 days notice” and “a free 3 month License to prevent any disruptions to production” (Migration Policy). That is a published rule about how the free tier can shrink. Neither of the other two has an equivalent page.

Portkey bills a subscription and the providers bill you. The subscription is metered in logged requests, not tokens: Developer is free with “10k recorded logs per month” and “3 days for Logs” retention; Production is $49/month for 100k, ”+$9 overages per additional 100k requests,” 30-day retention; Enterprise is custom (Pricing). Budget enforcement per API key is “Available on Enterprise plan and select Pro customers” (Enforce Budget Limits and Rate Limits for Your API Keys). The pricing page has no tier named Pro; its self-serve tier is called Production, and the docs do not say which customers count as “select.” Workspaces, the unit that team budgets attach to, are “currently a feature only enabled on the Enterprise Plans” (Org Management).

The mechanics under each cap, when the check runs and what code comes back, were the subject of Per-key spending limits; where a shared pool sits relative to those caps is in Shared team wallet. Nothing there changed on the pages re-read for this post. The shape-level fact is simpler: with OpenRouter your budget and your payment are one ledger; with the other two your budget is a gate in front of a bill someone else sends.

Question 3: whose servers see the prompt, and what they keep

Every request passes through the provider. The question is what sits in between, and whether it writes anything down.

OpenRouter, by default, does not. The FAQ is unusually direct: “Prompt and completion are not logged by default. We do zero logging of your prompts/completions, even if an error occurs, unless you opt-in to logging them” (FAQ). Metadata is kept: “number of prompt and completion tokens, latency, etc” (Data Collection). Two opt-ins exist. One lets OpenRouter use your prompts to improve the product “in exchange, you receive a 1% discount on all model usage.” The other, Input & Output Logging, stores prompts for your own review in “an isolated Google Cloud Storage project,” where “Data is retained for a minimum of 3 months, and may be retained beyond 3 months at OpenRouter’s discretion unless you request deletion” (Input & Output Logging). What the provider keeps is a routing decision: ZDR can be enforced “globally, per model group, per guardrail, or per request” with provider: { zdr: true }, OpenRouter assumes a provider “both retains and trains on data” when it cannot establish a policy, and “in-memory caching of prompts is not considered ‘retaining’ data” (Zero Data Retention). One inconsistency to know about: the Provider Logging page states that “OpenRouter does not have routing rules that change based on data retention policies of providers” (Provider Logging), while the ZDR page documents exactly such a rule. Both sentences were live on 2026-09-03; the ZDR page is the more specific one. In-region EU or US processing is “only enabled for enterprise customers by request.”

LiteLLM’s answer is that there is no in-between. “No data or telemetry is stored on LiteLLM Servers when you self-host” (Data Privacy and Security). Prompts go wherever your logging callbacks send them, and turn_off_message_logging: True keeps message content out of those destinations while spend is still tracked (Logging). Spend log rows land in your own Postgres (What is stored in the DB). The cost is that the compliance paperwork is yours too: the vendor’s page lists SOC 2 Type II as “In progress. ETA September 15th, 2026.” Your auditor audits your deployment, not theirs.

Portkey keeps logs by plan. Retention is the metered feature: Developer 3 days, Production 30, Enterprise “Unlimited” (Logs). Per request, the x-portkey-debug: false header, which the docs call DO NOT TRACK, records “only high-level statistics like tokens used, cost, and latency” and omits content. Organisation-wide, “Metrics Only (Privacy Mode)” “is a Portkey Enterprise plan feature,” and switching to it “will not retroactively remove previously logged data” (Configure Request Logging). Hybrid changes the geometry, not the policy: “All prompt content and LLM responses remain within your network,” upstream analytics are “Non-sensitive operational metrics,” and logs either stay in “your environment’s Blob Store” or go encrypted to Portkey, your choice (Enterprise Architecture).

Portkey's hybrid deployment diagram: a Data Plane box labelled Your VPC containing an AI App with SDK, an AI Gateway, a Data Service, Redis and a Blob Store, with arrows to private, proprietary and public LLMs; a Private Link to a Control Plane box containing the Portkey Dashboard, a Backend Service, and MySQL and ClickHouse data stores with envelope encryption using your KMS
Portkey's own drawing of the Enterprise split: prompts and responses stay in the data plane inside your VPC; configs, keys and analytics live in the control plane Portkey runs.Source: Enterprise Architecture.

The pattern is not “hosted bad, self-hosted good.” OpenRouter is hosted and stores nothing by default. Portkey is hosted and stores everything by default, for a fee, because logs are the product. LiteLLM stores whatever you told it to, in a database you pay for. Pick the default that matches your data classification, then check whether the switch to change it is on your plan.

Questions 4 and 5: failover and protocols, or what lives in the request goes with you

All three fail over across providers, and the previous post in this series worked through how their configuration models differ. The shape-level summary is where the fallback list lives. OpenRouter puts it in the request body as provider.order and load-balances by price when you leave it out, with the caveat that “If you have sort or order set in your provider preferences, load balancing will be disabled” (Provider Selection). LiteLLM puts it in server config, and “If a call fails after num_retries, LiteLLM falls back to another model group” (Fallbacks, Load Balancing, Retries). Portkey puts it in a config object, “a JSON object that can be used to define routing rules,” saved in the dashboard and referenced by an id like pc-***, or attached to an API key as its default (Configs). Request, server, saved object: three places, three different people who can change it.

On protocols the three have converged further than most comparisons admit. All speak OpenAI Chat Completions. OpenRouter also serves the Responses API and POST /api/v1/messages in “the Anthropic Messages API format” (Create a message). LiteLLM’s /v1/messages works with “All LiteLLM supported providers” (/v1/messages). Portkey lists the same three formats: “Each works with all providers — Portkey handles translation automatically” (Universal API), with the Messages endpoint pitched at tools “like Claude Code and the Claude Agent SDK” (Messages). What translation cannot hide is a separate post: seven things leak through whichever route you take.

The migration cost is therefore not the protocol. It is everything vendor-specific you let into the request or the config: on OpenRouter the provider object and slugs of the form openai/gpt-4o; on Portkey x-portkey-* headers, @provider/model slugs and pc-*** config ids; on LiteLLM your model_name aliases and the config.yaml that maps them. Grep for those before you sign anything. The count is your switching cost in lines.

Question 6: who absorbs the breaking change, or the Fable 5.1 day

On 1 September 2026 Anthropic shipped Claude Fable 5.1, and a third-party gateway’s changelog for that day shows what a hosted layer does when the upstream changes the rules. Three lines from it (Claude Fable 5.1 — Changelog, LLM Gateway):

New in 5.1: Anthropic rejects forced tool use — tool_choice: "required" or a named function — with a 400. The gateway forwards these requests with auto instead, so existing code keeps working.

The model accepts max_tokens and effort only. The gateway strips sampling parameters such as temperature and top_p before forwarding, so a request that sets them still succeeds.

Anthropic requires 30-day data retention for this model. A provider key from a zero-data-retention Anthropic organization is rejected upstream.

That is the hosted bargain in three sentences. Nobody on your team shipped anything on launch day. Also, a request that asked the model to call a tool no longer asks, returns 200, and your dashboards show a healthy morning. The third line inverts the bargain: a retention policy you negotiated is now a reason a request fails, and the gateway can only tell you so.

The same day looks different in each shape. OpenRouter’s documented default is that a provider “will ignore unknown parameters,” and require_parameters: true turns silent-ignore into not-routed (Provider Selection): the decision is made for you unless you flip it. LiteLLM’s default is to raise on an unsupported parameter, with drop_params as the opt-in to strip it instead (Drop Unsupported Params); the decision is yours, and so is the upgrade. It ships a new minor line “roughly every week” and supports “the four most recent stable minor lines,” so a deployment a month behind is out of the window (Enterprise, Release Cycle), and “Any endpoint not in the OpenAPI spec is private” and “can change … without notice” (API Stability Policy). Portkey’s hybrid deployment splits the difference on purpose: the control plane “Automatically updates with new features and provider integrations without requiring changes to your infrastructure,” filed under “Feature Velocity … multiple times per week” (Enterprise Architecture). The gateway containers in your VPC are still yours to roll.

Two costs, stated together. A hosted layer absorbs the breaking change and, in doing so, decides what your request means now. A self-hosted proxy hands you the 400 and the upgrade ticket. The first is a support cost you do not see, the second an ops cost you do. Neither is free, and which you pay depends on whether your team would rather be paged or surprised.

Question 7: who owns the vendor now

Two of the three changed hands in 2026, and one of those changes is finished.

Portkey belongs to Palo Alto Networks. The press release, dated 29 May 2026, uses the past tense: Palo Alto Networks “today announced it has closed the acquisition of Portkey, a pioneer in AI Gateways” (Palo Alto Networks Completes Acquisition of Portkey). The product has since been folded into a security line: PRISMA AIRS AI Gateway reached general availability on 16 July 2026 (Announcing General Availability of Prisma AIRS AI Gateway), and the docs footer now reads “Portkey is now PRISMA AIRS AI Gateway.” Whether the acquisition changed the terms or the tiers, the docs do not say. Portkey’s terms page renders client-side, so a curl returns the shell and not the clauses; this post quotes no Portkey terms for that reason.

OpenRouter has agreed to join Stripe, and the deal has not closed on the pages read here. Stripe’s newsroom headline is “Stripe agrees to acquire OpenRouter,” dated 19 August 2026 (Stripe newsroom). OpenRouter’s own announcement ends with the status: “The transaction is subject to customary closing conditions. We expect to close in the coming weeks” (OpenRouter is Joining Stripe). The same post promises “same mission, same name, same product, same roadmap. If you build on OpenRouter today, nothing about your integration changes.” Two weeks later there is a Stripe-shaped surface in the docs, stripe projects add openrouter/api (Stripe Projects), and no closing announcement on any page read on 2026-09-03. The docs do not say the deal is done.

LiteLLM is still BerriAI’s, and what stands between you and a change of terms is the MIT license on the code you already hold, plus a published policy for how free features move behind the paid one.

Do not model the acquirer’s intentions. Model the clauses that survive an owner change: OpenRouter’s §9 lets it discontinue the service “at any time,” §11 gives thirty days on material terms changes, and neither depends on who signs the cheques. A gateway you run from a container image you already pulled fails differently than a hosted account.

What this comparison does not measure

No latency, no throughput, no success rate, no uptime. No number here came from a test I ran, and I did not repeat the ones each vendor publishes about itself. A vendor-reported millisecond figure measures the vendor’s test, not your traffic from your region at your concurrency; quoting it would launder a marketing claim into a comparison table.

Also unmeasured: support quality, dashboard usability, behaviour during a real provider outage, and whether the retention promises are kept. Every data claim above is a vendor statement about its own conduct, not an audit finding, and Enterprise agreements routinely differ from published pages.

Seven undocumented answers, phrased as the questions to send a salesperson. Five of them a vendor can answer today; the two acquisition ones only time can.

  1. “Do you offer a hosted LiteLLM, and on what terms?” The README links to an anchor the Enterprise page does not have; that page lists Self-Hosted only.
  2. “Which customers are the ‘select Pro customers’ with per-key budgets?” Portkey’s pricing page has no Pro tier.
  3. “How do retries interleave with fallbacks?” Portkey documents the ladder exactly, not the ordering, as the failover post found separately.
  4. “What is the per-request retry count and provider cooldown?” OpenRouter’s fallback array is the retry mechanism; no count is documented.
  5. “Where are provider credentials stored?” Beyond “Securely stored credentials” and an AES-256 statement, Portkey’s hosted plan does not say.
  6. Has the Stripe acquisition of OpenRouter closed? Not answerable on a call.
  7. Did the Palo Alto Networks deal change Portkey’s terms or pricing? Same.

Everything above was read on 2026-09-03. Pages move, so the links are there for you to re-check whichever ones your decision rests on.

The decision tree, by who you are

One question at the root, because it is the one that cannot be undone cheaply: who must hold the provider key and the provider contract?

It must be you, because compliance requires it, because you negotiated committed-use pricing, or because an existing agreement names your account. That leaves three, not two — the third is the one most teams are actually in.

  • Can you run Postgres, Redis and a weekly upgrade cadence? Then LiteLLM. You give up the ops — a salt key you can never rotate carelessly, Redis once you run a second instance, a four-minor-line support window, SOC 2 Type II in progress with an ETA of 15 September 2026, SSO free only to five users — and you get nothing between your prompts and your provider, under a license nobody can revoke.
  • You cannot, or will not. Then Portkey’s hybrid Enterprise deployment: prompts stay in your VPC, administration does not. The cost is an Enterprise contract, a control plane you do not run, and a vendor whose owner changed four months ago. The cheaper version is the open-source gateway alone, npx @portkey-ai/gateway, where you give up every feature the README footnotes as hosted-or-enterprise until the 2.0 merge lands.
  • You cannot run it and cannot buy Enterprise. Then OpenRouter with BYOK, configured as in Question 1: your key is tried first with no way to change that ordering, and “Never use shared capacity on this provider” stops a bad minute from moving traffic onto OpenRouter’s contract. The credential and the contract stay yours; the data path does not. This branch answers whose account pays the provider, not whose servers see the prompt — see Question 3.

It can be someone else, and you want one invoice, one integration and a catalog. Then OpenRouter. You give up 5.5% on credit purchases with a $0.80 minimum, an organization capped at ten members, workspace budgets on Enterprise only, credits that can expire at 365 days, and a default where unknown parameters are quietly ignored. Tighten what you can from the request side: require_parameters: true so a provider that cannot honour your parameters is not routed to, provider: { zdr: true } where retention matters, and, on BYOK, “Never use shared capacity on this provider” so a bad minute cannot move your traffic onto OpenRouter’s contract.

Three signals you picked wrong: your security review keeps returning to where prompts are stored and you are on a hosted plan (wrong shape, not wrong tier); nobody has upgraded the proxy in six weeks (self-hosting costs more than the license); you are weighing platform fees against an engineer’s time and the fee is losing (check whether you counted the on-call).

The question was never which of the three is best, but which of these your team already is: one that must hold its own keys, one that must not run its own infrastructure, or one that would rather buy a catalog than a contract. Answer that and the product falls out of it. We are building a gateway designed to keep your keys and contracts in your hands while taking the ops out of the middle, which is an opinion about that trade-off and not a fourth column in the table above. Whichever way you go, read the termination clause on the way in, not on the way out.