An image router decides which provider serves each image generation request, and what to do when that provider fails. It matters because the same image model is often served by its vendor, by cloud platforms and by hosted inference providers, and each of them accepts different sizes, aspect ratios, quality levels and reference images, at different prices. A good image router fails over between them without changing the image you asked for.
Routing text requests is well understood: an ordered list of providers, a retry policy, failover before the first byte of the answer. Images look similar and are not. This guide covers what makes multi-provider image generation different, how to route around it, and where safe fallback ends.
Why route image generation at all?
Three reasons show up in production, usually in this order.
- Availability. An image feature in a product (thumbnails, avatars, ad variants, product shots) breaks the same way a chat feature does when its one provider is throttled or down. A second provider for the same model keeps it working.
- Rate limits and throughput. Image endpoints have their own limits, often lower than text. A batch of a few thousand renders can exhaust one account's allowance; spreading across accounts or providers finishes it.
- Cost. The same model can be listed at different per-image rates on different providers, and the difference compounds at volume. The route order decides which rate most of your images are billed at.
What is not on the list is "quality". Routing between providers of the same model should not change quality at all. Routing between different models does, and is covered in AI image models compared.
One model, many hosts, different settings
Take one model as an example. Google documents its Nano Banana Pro model (gemini-3-pro-image) on the Gemini API with output sizes of 1K, 2K and 4K, 1K by default, and up to 14 reference images in total, of which up to 6 can be object references and up to 3 style references1. fal hosts the same model with the same three resolutions and lists ten aspect ratios from 21:9 to 9:162.
Other models vary more. OpenAI's GPT Image models take an exact WIDTHxHEIGHT size whose edges must be multiples of 16, with neither edge above 3840 pixels and the total between 655,360 and 8,294,400 pixels; resolutions above 2560x1440 are labelled experimental3. The same guide lists quality levels from low to max, with xhigh and max only on the 2.5 models3. A hosted provider of the same model may expose the size as a tier, as a ratio, or as a fixed list of pixel sizes.
The settings that differ from host to host fall into a short list:
| Setting | How it varies across providers | What goes wrong if ignored |
|---|---|---|
| Size | Exact pixels, resolution tiers (1K/2K/4K), or a fixed list | The provider rounds to its nearest size, or refuses |
| Aspect ratio | Different sets of supported ratios | A 21:9 banner comes back as 16:9 |
| Quality | Present on some models only, with different levels | A high request runs at the provider's default |
| Number of images | Different maximums per call | Fewer images than requested, with no error |
| Reference images | Different counts, roles and upload formats | References dropped or the call refused |
| Edits and masks | Some hosts take a mask, some only a prompt | The whole image is edited instead of one region |
| Seed | Taken by some hosts, ignored or refused by others | No reproducibility, without any signal |
Prices differ per image and per resolution
Image models are billed per image, not per token, and the rate depends on resolution and sometimes quality. For Nano Banana Pro on the Gemini API's standard paid tier, Google lists $0.134 per 1K or 2K image and $0.24 per 4K image4. fal lists $0.15 per image for the same model and bills 4K output at twice that rate2. Neither is better in general: which is lower depends on your resolution mix, and your own negotiated rates may differ from both list rates.
Two consequences for routing. First, the primary target is a cost choice as much as a reliability one, so put the provider whose rate you want on most traffic first. Second, a router that silently upgrades a request to a higher resolution on a fallback target to make it succeed also changes the cost, often by a multiple.
How should an image router fail over?
For text, a failover target either speaks the same request or is skipped. For images, a target can accept the request and quietly render something different: a nearest supported size, the default quality, fewer images, references ignored. The request "succeeds", and the image is wrong in a way no error code reports.
The rule that prevents this is simple to state: check every setting against what the target takes before calling it, and skip targets that cannot honour the request.
- Normalize the request into model-level settings: resolution tier, aspect ratio, quality, number of images, references with their roles, mask, seed.
- For each target in order, compare those settings with that provider's record for that model. A target that cannot take one of them is skipped before any call, with the reason recorded.
- Translate the settings into the provider's own fields: a tier where it takes tiers, a ratio where it takes ratios, pixels where it takes pixels, within its limits.
- Call, and fail over on provider failures (timeouts, rate limits, server errors) to the next target that passed step 2.
- When no target can honour the request, refuse it with a message that names what the model takes on each host, for example "renders at 1K and 2K, not 4K". No provider is called and nothing is billed.
Refusing is the honest outcome. An application asking for a 4K image for print does not want a 1K image that happens to succeed; it wants to know that none of its configured providers can render 4K for that model today.
Synchronous, queued and webhook providers
Providers do not agree on how an image request returns. Replicate's API is asynchronous by default: creating a prediction returns an id at once, a Prefer: wait header holds the request open (60 seconds by default), and a webhook can deliver the final result5. fal's queue returns a request id with status, result and cancel URLs, and can POST the result to a webhook when it finishes6. The Gemini and OpenAI image APIs answer within the HTTP request.
An image router has to present one behaviour to the application. Two workable choices:
- Synchronous to the caller. The router waits on queued providers on the caller's behalf and answers when the image is ready. Simple for fast models, but a client timeout can abandon an image the provider still renders and bills.
- Jobs for slow work. The router returns a job id and delivers the result by webhook or polling, whatever the provider does underneath. This is the right shape for 4K renders, large batches and video. Async media jobs and webhooks covers signatures, retries and idempotency.
Either way, provider output URLs often expire. Copy the image to storage you control before handing a link to your users.
Content policies, watermarks and seeds are not portable
Providers apply their own safety systems to prompts and outputs. OpenAI's image API exposes a moderation parameter with auto as standard filtering and low as less restrictive3; other hosts apply the vendor's or their own filtering with no setting at all. A prompt refused by one provider may be accepted by another, which is why a refusal on safety grounds should normally stop the request, not fail over until some provider accepts it.
Provenance marks differ too. Google states that every image generated by its Gemini image models carries a SynthID watermark1. If your compliance process depends on a mark like that, a route that falls back to a different model may produce images without it.
Seeds do not travel. A seed reproduces an image only within one provider's implementation of one model, and several providers take no seed at all. Caching image generation therefore means caching outputs: store the bytes against a hash of the normalized request (model, prompt, settings, references) and serve repeats from your storage, rather than hoping a seed reproduces the same image elsewhere.
A checklist for multi-provider image generation
- Each route serves one model, or names a second model only where any reasonable image is acceptable.
- The router holds a per-provider record of sizes, ratios, quality levels, image counts, references and seed support for every model it serves.
- A setting a target cannot take is refused before the call; the refusal names what the model takes.
- Failover happens on provider failures, never by quietly lowering resolution or quality.
- Safety refusals stop the request instead of searching for a provider that accepts it.
- Cost is estimated per image at the resolution and quality requested, before the call, against your own rates where you have them.
- Slow renders run as jobs with webhooks, and outputs are copied to your own storage.
- Each image's record names the provider and account that rendered it and every failed attempt.
The multimodal AI API guide covers the same concerns for video and audio, where the asynchronous part dominates.
How INFRO routes image requests
INFRO is a BYOK control plane: you connect your own provider accounts, and POST /v1/images/generations and /v1/images/edits route over them with the same routes, failover and request log as text. Image requests can be served by connections to OpenAI, Azure OpenAI, Google AI, Google Vertex AI, Together AI, OpenRouter, Runway, KIE, LaoZhang API, fal, Replicate and OpenAI-compatible endpoints, as listed in the image generation docs.
INFRO keeps a record of the settings each model takes on each provider, read from that provider's documentation. Before calling a target, the gateway checks resolution, aspect_ratio and quality against that record, and reference images by count and role. A setting the target cannot take is never sent: the next target is tried, and when no target can take it the request is a 400 naming what the model accepts, with no provider called and nothing billed. Settings are then sent in each provider's own form. Provider order comes from the route's targets, or for a request that names a model directly, from the order you connected providers; per-request fallbacks can name further image models, tried only after every connection for the first has failed.
{
"model": "google/nano-banana-pro",
"prompt": "A product shot of a ceramic mug on a linen tablecloth, morning light",
"resolution": "2K",
"aspect_ratio": "4:5",
"n": 1
}Each response names the provider and connection that rendered the image and carries usage.cost, an estimate of what your provider will bill, or null when no rate is known. POST /v1/estimates prices a request per image at its resolution and quality tier before you send it, and generated images are copied to INFRO storage behind signed links. Your providers bill you for the images; INFRO charges a subscription and takes no share of model spend. For creative teams, INFRO Studio runs the same routing with a provider order you set per model. The quickstart connects a first provider.
