Migration guidesFrom Cloudflare AI Gateway
Moving off Cloudflare AI Gateway, when nothing is making you
There is no acquisition here, no maintenance mode and no deprecation notice. AI Gateway is generally available, was actively built through 2026, and its core is free on an account you already hold — so the question this page answers is not how to move but whether to. It starts with three numbers you can go and measure on your own gateway, two of which say stay.
INFRO is in private early access. The catalog, the docs, and the API contract are public today, and the gateway is deployed. The console opens with an early-access account, billing opens in stages, and anything beyond v1 is marked Later. Early access details
Where things stand
Nothing is forcing this
AI Gateway is generally available and was actively built through 2026 — spend limits in June, User Insights in August. The core is free on any Cloudflare account. If a page ever tells you otherwise, check it against the changelog rather than believing it.
The overlap is larger than it was
Both products sit in the request path, price every request, attribute spend to a user or a team, refuse a request at a dollar cap, and export OpenTelemetry. A year ago this comparison was gateway versus control plane. It is not any more.
One question decides it
Whether somebody has to defend the cost number to a person who did not produce it. If nobody does, the free gateway is the right tool and this guide should end here. If somebody does, that is what the rest of the page is about.
Each one is on your own gateway or in your own calendar, and each one produces an answer rather than a consideration. Two of the three end the decision in Cloudflare's favour, which is the honest distribution — most teams reading this should keep what they have.
Your cache hit rate
Analytics on your gateway, over a month that looked normal. Cloudflare reports it per gateway.
This is the one that can end the decision on its own. INFRO also has an exact-match response cache for chat completions, but it starts empty, is off until you turn it on, is keyed per project and key environment, and by default stores only deterministic requests (temperature 0 or a seed). Work out what share of your hits came from requests that fit that; the rest become provider calls after a move, billed by your provider. If that share is large, staying is the better answer and no feature on the rest of this page outweighs it.
Whether Unified Billing is on
Your gateway's settings. If Cloudflare is buying your inference, this is where it says so.
If it is on, you do not have a configuration problem, you have a procurement one. INFRO never buys inference, so a move means opening your own account with every provider you use, which takes as long as your vendor onboarding takes. Find out now rather than in week three.
How often somebody outside engineering asks about the number
Not a dashboard. Your last quarter of finance, procurement and pricing conversations.
If the answer is never, the free gateway is the right tool and this guide should end here — that is not a polite exit, it is the correct recommendation. A control plane earns a subscription at the point where a cost figure has to be defended to somebody who did not produce it, and not before.
This section is above the differences on purpose, and unlike the other guides in this set it is not pointing you at a third product. It is pointing you at the one you already run.
This section is above the mapping on purpose. Cloudflare AI Gateway is a good product that costs nothing to run, and the most common correct outcome of reading this page is that you close it and keep what you have. There is no acquisition here, no maintenance mode, and no deprecation notice to hurry you — the reasons below are not softeners before a rebuttal, they are the answer whenever one of them is true.
The move is worth considering when the cost figure has an audience: finance asking why the model bill moved, a customer-facing margin you have to hold, several teams sharing providers and disagreeing about who spent what. That is the point at which a number nobody has checked against an invoice stops being sufficient, and it is the only claim on this page that Cloudflare's own documentation does not already answer.
Stay where you are when
- The gateway is doing its job and no one is asking questions of the number. A control plane earns its price when somebody outside engineering has to act on the cost figure. If that has not happened, it has not earned it yet.
- You need guardrails or DLP on the request path. Cloudflare scans the prompt and the response for harmful content, and can block or flag sensitive data before it reaches a provider. INFRO's guardrails are pattern-based (PII, secrets, your terms, chat completions only); Cloudflare's safety-category guardrails have no equivalent.
- You are running Workers AI, or Cloudflare is buying your inference through Unified Billing. INFRO operates no inference and never buys any: before a move you would need your own accounts with each provider, which is a commercial step, not a configuration one.
- Your routing depends on conditional branches or percentage splits. INFRO's routes are priority or weighted targets over your own connections; an if/else on request content has no equivalent and would have to move into your application.
- Response caching is carrying real load on requests INFRO would not cache. INFRO's cache matches exact chat completion requests only, keyed per project and key environment, and by default only deterministic ones (temperature 0 or a seed); every request outside that goes to your provider again after a move.
- Being on one vendor is the point. One bill, one set of account roles, one support relationship is a legitimate reason to choose a platform gateway, and adding a second vendor undoes it.
If more than one of these is true, close this page. We would rather lose the evaluation than win it and be the wrong answer six weeks later.
Cloudflare's objects against ours, read from their public documentation on 20 September 2026 and checked against what the gateway actually implements. Five rows say we have nothing; those are the ones worth reading first.
| Cloudflare AI Gateway | What it does there | In INFRO |
|---|---|---|
| Gatewaydifferent | A named object on your Cloudflare account. It owns the logs, the cache, the rate limits and the spend rules; a second environment means a second gateway. | There is no gateway object. An organization owns policy and billing; projects, keys and a key's environment scope it. A second environment is a property of the key rather than a second endpoint. |
| `/compat/chat/completions`same shape | OpenAI-compatible chat under https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/compat, with models addressed as provider/model. | OpenAI-compatible chat under https://api.infro.io/v1, with models addressed as vendor/model. Same client, same request and response shape, including streaming, tool calls and structured outputs. |
| Provider-specific pathsdifferent | A path per provider that forwards to that provider's own API, so each one keeps its native request shape. | One normalised shape per modality: /chat/completions, /images/generations, /images/edits, /audio/speech, /audio/transcriptions, and /videos, which returns an async job. Provider-native APIs are not proxied — a call written against Anthropic's Messages API or Gemini's generateContent has to move to the compatible shape. |
| Stored provider keysdifferent | Keys held per gateway with aliases, selected per request with a cf-aig-byok-alias header, and used ahead of Unified Billing when both are present. | Connections held per organization, sealed, with health and last error visible. Which one serves a request is decided by the key's environment and the route, not by a header the caller sends. |
| Unified Billingnothing | Cloudflare buys the inference from the provider and bills you for it, with a fee on purchased credits. | Nothing, deliberately. INFRO never buys inference and never takes a share of model spend; your providers invoice you directly at your own rates. If Cloudflare is currently buying yours, you need your own provider accounts before a move is possible. |
| `cf-aig-metadata`different | Up to five string, number or boolean entries per request, sent as a header, appearing in logs and usable as a spend-limit dimension. | A metadata object in the request body, never forwarded upstream: user_id, session_id, and any number of keys under tags, filtered on the request log as tag.<key>. Anywhere you set the header today is an edit. |
| `cf-aig-custom-cost`different | Your negotiated input, output and cache rates, sent per request as a header, overriding the public model cost for that call. | Rates stored in the console per model and optionally per provider, applied to every request that matches, with usage.price_source on the response saying which rate produced the number. Included from the Team plan. |
| Spend limitssame shape | Dollar budgets over a rolling or fixed window, scoped by model, provider or custom metadata, evaluated before the provider is called, returning 429 at the cap or falling back to a cheaper model. Up to 20 rules per gateway. | Budgets at organization, project, member and key, evaluated before the provider is called, returning 402 budget_exceeded with alert thresholds you set. Scoped to the object model rather than to metadata, so a project's ceiling does not depend on the caller remembering a header. |
| Dynamic routingdifferent | A route graph composed in a visual editor or as JSON — conditional branches on the request body, headers or metadata, percentage splits, rate and budget nodes, published without a deploy. Available on the OpenAI-compatible endpoint. | Named routes with priority or weighted targets over your own connections, health-checked, with failover before the first byte of the response. There is no conditional branching on request content; an if/else route has to move into your application. |
| `cf-aig-max-attempts`different | Up to five retry attempts with a configurable delay and constant, linear or exponential backoff, set per request and working with any provider endpoint. | Retries and failover are route policy rather than per-request headers, so the behaviour is configured once in the console and applies to every caller of that route. A request that fails on every target reports each attempt on its trace. |
| Cachingdifferent | Responses served from Cloudflare's cache instead of the provider, for latency and for cost. | An exact-match response cache for chat completions, off by default and turned on per organization or project, with a per-request cache body field or X-INFRO-Cache headers where Cloudflare uses cf-aig-* headers. It does not cache other endpoints, and it is keyed per project and key environment, so nothing is shared between them. |
| Guardrails and DLPdifferent | Guardrails evaluate the prompt and the response against safety categories; DLP scans both for sensitive information and either replaces the response with a 400 or flags the finding on a cf-aig-dlp header. Neither feature page states how they are billed, so we do not say. | Pattern-based guardrails on chat completions: block, redact or flag PII, API keys and your own terms. No safety-category classifiers. |
| Workers AInothing | Cloudflare's own hosted models, called through the same gateway as third-party providers. | Nothing. INFRO operates no inference of its own — it routes to accounts you hold with providers. A workload on Workers AI has no destination here. |
| Logsdifferent | Prompts, responses, tokens, cost, duration and user agent, against a storage limit per gateway. When the limit is reached new logs stop being saved until older ones are deleted, or automatic deletion is enabled to drop the oldest. | Request metadata — status, model, provider, route, tokens, latency, estimated cost — kept for 7, 14, 30 or 90 days depending on plan. Prompt and completion capture is off by default and has its own, shorter window. |
| OpenTelemetry exportsame shape | Spans to your own collector following the GenAI semantic conventions, carrying gen_ai.usage.cost and any custom metadata as span attributes. | Spans pushed to your own collector from the request path, with the endpoint and headers set in the console. Included from the Team plan. |
Our reading of Cloudflare’s published documentation, not a trial or a benchmark. Their product moves quickly — spend limits arrived in June 2026 and User Insights in August — so check any row that decides something for you against their changelog rather than against this page. Every source and the date we opened it is listed at the foot.
Two arguments for the connection, and the model id keeps its shape. The work is in the headers: some become a body field, and the retry headers have nowhere to go at all, because retries here are route policy rather than something a caller sends.
Before · Cloudflare AI Gateway
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.CF_API_TOKEN,
baseURL:
`https://gateway.ai.cloudflare.com/v1/${process.env.CF_ACCOUNT_ID}` +
`/${process.env.CF_GATEWAY_ID}/compat`,
});
const completion = await client.chat.completions.create(
{
model: "anthropic/claude-opus-5",
messages,
},
{
headers: {
"cf-aig-metadata": JSON.stringify({
user_id: "user_8f21",
feature: "summarizer",
}),
"cf-aig-max-attempts": "3",
},
},
);After · INFRO
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.INFRO_API_KEY,
baseURL: "https://api.infro.io/v1",
});
const completion = await client.chat.completions.create({
// The model id keeps its shape: vendor, slash, model.
model: "anthropic/claude-opus-5",
messages,
// Annotations move out of headers and into the body. Recorded on the
// request, never forwarded upstream, and ignored by any OpenAI-compatible
// backend that does not know the field — so the same call still runs
// elsewhere.
metadata: {
user_id: "user_8f21",
tags: { feature: "summarizer" },
},
});
// Retries and failover are not here. They are route policy, set once in the
// console, so cf-aig-max-attempts has nothing to become.The base URL and the key
https://api.infro.io/v1, with an INFRO gateway key in the standard Authorization: Bearer header — so it is the baseURL and apiKey arguments your client already has. The account id and gateway id in the Cloudflare URL have no equivalent: an INFRO key already identifies the organization, the project and the environment it belongs to.
The model id does not change shape
Both address models as vendor, slash, model. The ids themselves still need checking — GET /v1/models lists exactly what your key can call, which is whatever your own connected accounts serve, and a model no connection covers returns 503 no_provider_connected naming the provider to connect rather than failing vaguely.
The headers come out
cf-aig-metadata becomes the metadata object in the body: user_id, session_id, and anything else under tags. cf-aig-max-attempts, cf-aig-retry-delay and cf-aig-backoff have nothing to become, because retry and failover are configured on the route rather than sent per request. cf-aig-custom-cost moves into the console once, and cf-aig-byok-alias is replaced by the key's environment.
The move does not have to be a cutover. Both gateways are ordinary HTTPS endpoints an OpenAI-compatible client can point at, so one service can run here while everything else stays where it is, and the two request logs can be read side by side for a week. That is also how to check the part of this page you should trust least — whether the two products agree about what a request cost — and it is worth doing before the decision rather than after it.
Four things, and the list is deliberately short. Spend limits, per-identity attribution, custom rates and OpenTelemetry export are all Cloudflare's too — this is what is left after the overlap.
- The estimate gets checked against the provider's own billing
- Cloudflare's spend-limit documentation says cost tracking is a best-effort estimation from token counts and model pricing, and to refer to your provider's dashboard for exact billing amounts. That is an accurate description of what a gateway knows on its own, and INFRO's per-request figure is an estimate on identical terms. What differs is the step after it: a daily pass reads your own OpenAI and Anthropic cost APIs with a separate admin credential you grant deliberately, stores the reported figure beside the estimate, and reports the variance. Two providers, on the Business plan — a provider with no adapter shows no variance rather than a variance of zero, Anthropic's endpoint excludes Priority Tier, and Bedrock, Vertex and Azure keep their cost in the surrounding cloud's billing.
- Your negotiated rates live in the control plane, not in a header
- Both products can price against the rates your contracts actually carry. On Cloudflare they travel per request in
cf-aig-custom-cost, which means every service that calls a model holds a copy of your commercial terms and a renegotiation is a deploy across all of them. Here they are entered once, per model and optionally per provider, by whoever owns the contract — andusage.price_sourceon every request says whether the number came from your rate, your rate for that provider, or the vendor's published one. Included from the Team plan. - The unit is an organization rather than a gateway
- A Cloudflare gateway is configured by whoever holds the Cloudflare account role, and per-request identity arrives as custom metadata or from Access. INFRO has organizations, projects, environments and keys with their own scope, five roles, model allowlists at organization, project and key level, and an audit log of who changed which policy and when — all of it on the entry plan. It matters at the point where several teams share providers and the question becomes which team may call this model and who approved that. Directory SSO and SCIM are included from the Business plan.
- A long render is a job, not a held-open request
- Video generation is submitted with
POST /v1/videosand returns a job you read withGET /v1/jobs/{id}or receive on a signed webhook, and the finished media is re-hosted behind a signed expiring URL so it outlives the provider's own retention window. It is metered and attributed exactly like a chat completion, which is the part that matters for a media-heavy product: the spend that is hardest to see is usually the spend that is not shaped like a token.
What does not come across
There is no importer, and the last item on this list is the one that decides schedules. Read it before you commit to a date.
- Your logs. There is no importer and none is planned. Export anything you need from the gateway before you stop sending traffic to it — and remember that its log is a storage cap rather than a time window, so what is there may already be shorter than you think.
- Cached responses. Entries in another product's cache do not move; INFRO's cache starts empty and fills from your own traffic, and it matches exact requests only, never similar ones.
- Safety-category guardrail policies. There is nowhere for them to land: INFRO's guardrails match patterns (PII, secrets and your own terms) and classify nothing.
- Workers AI models. INFRO routes to provider accounts you hold and operates no inference, so a workload on Cloudflare's own models has no destination.
- Dynamic route graphs. Priority and weighted targets carry a fallback chain across, but conditional branches and percentage splits do not — those have to be rebuilt in your application or left behind.
- Unified Billing. If Cloudflare is buying your inference today, you need your own accounts with each provider first. That is a commercial step with its own lead time, not a configuration change, and it is the one thing on this list that can hold up a move for weeks.
If the cost number has an audience
That is the case this product is built for, and it is the only one on this page that Cloudflare’s own documentation does not already answer. The API contract is published in full, including the parts that do not exist yet, so you can decide before writing anything. Or tell us what you are running — if the answer is that you should stay on the gateway you have, that is the answer you will get.
Sources
Every statement on this page about Cloudflare comes from one of these, with the date we read it. Nothing is inferred from a trial, a benchmark, or a conversation — and where a page did not settle something, the guide says so instead of guessing.
- Cloudflare AI Gateway — Pricingread 2026-09-20
- Cloudflare AI Gateway — Spend limitsread 2026-09-20
- Cloudflare AI Gateway — Unified Billingread 2026-09-20
- Cloudflare AI Gateway — Dynamic routingread 2026-09-20
- Cloudflare AI Gateway — Bring your own keysread 2026-09-20
- Cloudflare AI Gateway — Custom costsread 2026-09-20
- Cloudflare AI Gateway — Request handlingread 2026-09-20
- Cloudflare AI Gateway — Loggingread 2026-09-20
- Cloudflare AI Gateway — Custom metadataread 2026-09-20
- Cloudflare AI Gateway — User Insightsread 2026-09-20
- Cloudflare AI Gateway — OpenTelemetry integrationread 2026-09-20
- Cloudflare AI Gateway — OpenAI-compatible chat completionsread 2026-09-20
- Cloudflare AI Gateway — Supported providersread 2026-09-20
- Cloudflare AI Gateway — Guardrailsread 2026-09-20
- Cloudflare AI Gateway — Data loss preventionread 2026-09-20
- Cloudflare changelog — Control AI costs with spend limitsread 2026-09-20
- Cloudflare changelog — User Insightsread 2026-09-20