Grafy Blog
All postsTry Grafy free
← All posts

A model catalogue that updates itself

The Grafy team · Aug 29, 2026 · 11 min read
ai model catalogopenrouter apivertex aillm pricingmodel deduplication
A model catalogue that updates itself

A hard-coded list of AI models is stale the week it merges. Labs ship on no schedule anyone else controls, aggregators re-price monthly, a model you route to quietly stops being served, and the same model shows up on two platforms at two different prices — so the list in your source file is now both incomplete and wrong, and nobody notices until a customer does.

Grafy’s catalogue is fetched rather than written. What follows is the plumbing: how often it refreshes, what happens when the network is down, how two copies of one model are recognised as one, which copy survives, and why a provider’s own model list is not treated as the truth about what it will serve.

1Fetch2Merge3Dedup4Rank
Fetch → Merge → Dedup → Rank
TWO COPIES, ONE MODELvertex/gemini-3.7-flash$0.30 per 1M inno release date of its ownkept — cheaper per tokenopenrouter/google/gemini-3.7-flash$0.42 per 1M inreleased 2026-01-28superseded — hidden everywherecanonical key: gemini-3.7-flashGemini 3.7 FlashGoogle · 2026-01-28 · the date came from the copy that lostValueRecomputed at startup and on every six-hour refresh, so a price move changes which copy you are routed to without a deploy.
The same model on two platforms. The cheaper copy is kept, the pricier one is hidden everywhere — and the survivor inherits the release date only its hidden twin knew.

Six hours, one cache, and an answer when the network is out

The cloud half of the catalogue is the aggregator’s live model list, read on a six-hour disk cache. The unfiltered endpoint returns chat models plus a handful of multimodal ones; the full media catalogue only appears behind an output-modality filter, so image, video, music and transcription pages are fetched and merged in by id.

Two failure rules matter more than the happy path. A media page that fails must not drop the chat list — it is skipped, and the rest of the merge proceeds. And on a network failure the last cached list is returned, so the catalogue never disappears offline. A product whose model list empties itself because a third party had a bad minute is worse than one showing a slightly stale list.

Every six hours the refresh runs again, and everything downstream — price tiers, the duplicate merge, the popular shelf — is recomputed from the new list. No deploy is involved in any of it.

The same model, two providers, two prices

A frontier model is frequently served both by the lab’s own cloud partner and by an aggregator, and the two prices are rarely the same. Listing both is the naive answer, and it is a bad one: it doubles the length of every picker with rows that are not choices, and it invites the reader to pick the expensive one by accident.

So copies are grouped and only the cheapest survives. Text-family models are compared across the two text platforms by per-token cost. Media models — image, video, music and 3D — are compared across four platforms by per-generation cost, grouped per kind, so an image model and a video model can never fuse on a shared name.

The loser is not deleted, it is superseded: hidden from every list, and refused if a client sends its id back. That second half is the one that matters for billing — a picked model arriving from a browser must not be quietly charged and routed to the copy that lost.

What counts as “the same model”

Matching is done on a canonical key that strips serving noise and nothing else: the platform prefix, the publishing org, and the suffixes platforms append to the same weights — -maas, :free, :nitro, :extended, :online. What is left is lower-cased and punctuation-normalised.

It deliberately does not strip variant words. Merging gemini-3.7-flash served by two platforms is correct; merging flash into pro because both are Gemini would be a catastrophe of a different order — a user picks one model and is billed for and served another. The key is conservative on purpose, and it errs toward listing a duplicate rather than fusing two genuinely different models.

The guard that stops a false merge

One provider’s browse ids canonicalise to their last path segment, which means several genuinely different models can share a tail like image-to-video. Left alone, that would merge unrelated models into one row and hide real options.

The guard is small and worth stating: a canonical key claimed twice by the same provider is ambiguous, not a duplicate. If a group’s runtimes are not all distinct, the group is skipped entirely rather than resolved by a tiebreak. A duplicate row is a cosmetic problem; a wrong merge routes a paying run to the wrong model.

A date belongs to the model, not to the copy that won

Only one platform publishes real release dates. So when the cheaper copy of a model is the one from a platform that publishes none, reading the date off the surviving row alone would report no release date for a model whose hidden twin knew it exactly — and the newest-first ordering in the model picker would push a brand-new model to the bottom of the list.

Both date lookups therefore resolve across every copy sharing a canonical key, and the winner inherits whatever any copy knows. It is the same idea as the merge itself, applied to metadata: the fact belongs to the model, not to the row that happened to be cheapest this week.

Absence from a list is not evidence

The obvious way to prune a catalogue is against the provider’s own published model list. Measured against this deployment, that would have deleted models that work. Every partner model served through the big cloud — Claude, Llama, DeepSeek, Qwen, Grok — is listed by none of its regions, and several of the cloud’s own preview ids are missing too.

So the rule is: absence from a list is not evidence; a refusal to serve is. A model is marked unavailable only when a real request comes back no such model or no access, written from the request path, which is the only source that can be trusted about it.

And the verdict expires rather than sticking. Access restored on the provider’s side heals itself within one window, with no deploy and no manual list to edit — the same reasoning that makes the whole catalogue a fetch instead of a file.

The shelf follows a maker who renames its line

The Popular shelf shows one flagship per recognisable family, and it is resolved against the live catalogue rather than pinned to ids, because a pinned shelf empties itself with every release.

Choosing the flagship is a ranked comparison: stable before preview, then the newest major generation, then flagship before cut-down variant, then the newest point release, and finally the shortest id as a tiebreak — which is how gpt-5.2 beats gpt-5.2-chat-0711.

The order of those terms was learned the hard way. Ranking the variant word above the generation made the shelf answer to the naming of years past: every Gemini shipped since 2.5 is a Flash, a word the list reads as cut-down, so the shelf held Gemini 2.5 Pro while three newer releases piled up unnoticed in the tail. Below the generation, the same word still does its real job — gpt-5.2 over gpt-5.2-mini — but it can no longer pin a family to a release nobody has used in a year. Comparing only the major number is what keeps Mistral Medium 3.1 the Mistral people mean, rather than losing the slot to Small 3.2.

Value is a share, not a price

The cheapest band of each kind is marked Value, and it is defined as a proportion of that kind’s catalogue — 30% by default, configurable, clamped between 5% and 90% — rather than a price ceiling.

A fixed ceiling like “half a cent an image” has to be retuned by hand every time providers move, and it quietly empties the tier when they all move together. A share stays meaningful with no maintenance.

Two prices are deliberately excluded from the tier rather than ranked. A model whose published rate is missing falls back to a house estimate and is not eligible, because the studio must never advertise a model as cheap on a guess. And a negative rate is the aggregator’s sentinel for depends where this routes on its meta-routers — the opposite of cheap. Read as a plain number it sorted below zero, which briefly made those the cheapest thing in the catalogue: tagged free, estimated at one credit, and first pick for automatic routing. They are now unknown, never free and never value. The spend gate that consumes these tiers is described in lowest-cost model routing.

A worked example: the day a new Gemini lands

Google publishes gemini-3.8-flash. Within six hours the refresh picks it up from the live list with its real publication date attached.

It appears in every picker immediately, at the top, because the default order is newest first. Its price is compared against its own kind and it earns a tier. Its family already exists on the popular shelf, and it has a newer major generation than the model sitting there, so it takes the slot from 3.7 without a line of code changing. If the same model also arrives through the other platform at a higher price, that copy is superseded within the same refresh, and the surviving row keeps whichever release date either copy knew.

The work done by a human in that sequence is zero.

Compared with a curated list

Curating eight models by hand is genuinely better on day one. The names are right, the descriptions are yours, nothing weird is on screen. The cost shows up later, and it shows up as three separate bills.

You pay it first in lag: the model everyone is discussing this week is not in your product until someone opens a pull request. You pay it again in price drift: a curated id keeps routing to a copy that stopped being the cheapest one months ago, and nothing tells you. And you pay it a third time in dead entries, because a model withdrawn by its provider stays in your list until it fails in front of a user.

A fetched catalogue trades that for a different kind of work — the merge rules, the guards and the ranking described above — but it is work you do once rather than every release. The same instinct runs through workflows that never ask you to export: the maintenance a product avoids is maintenance its users were paying for.

Frequently asked questions

How quickly does a newly released model appear?

Within one refresh window, so at most six hours after the aggregator lists it — no deploy and no code change. It arrives with its published release date, which is what puts it at the top of a newest-first picker rather than somewhere in the middle of an alphabetical list.

What happens if a provider’s API is down at refresh time?

The last cached list is served, so the catalogue never empties. A single media page failing is skipped without affecting the chat list, and a provider contributing zero models is logged rather than allowed to fail the whole refresh. Stale beats absent.

Why can I not see a model I know is available?

Most likely another platform serves the same model more cheaply, so the copy you were looking for is superseded and hidden. You are not losing access to the model — the row that remains is the same weights at a lower price. The other possibility is that a real request to it came back no access, which marks it unavailable until that verdict expires.

Could two different models ever be merged by mistake?

The canonical key strips only serving noise — platform prefixes and suffixes like :free or -maas — and never variant words, so flash and pro stay distinct. On top of that, a key claimed twice by the same provider is treated as ambiguous and skipped entirely. The design accepts a duplicate row rather than risk a wrong merge.

Is the Value tier just the cheapest models?

It is the cheapest 30% of each kind, compared only within that kind, since media models are priced per generation and text models per call. Models with no published price are excluded rather than ranked on a house estimate, and meta-routers whose cost depends on where they land are excluded too.

Open Chat and press the model name — whatever is listed there was fetched, priced and ranked within the last six hours.

Read next

More from the Grafy blog.

← Back to all posts