AI Blog

OpenAI vs Cohere vs Voyage vs Qwen3: The Model You Cannot Cheaply Un-Choose

Swapping your LLM edits a prompt. Swapping your embedding model re-embeds the corpus, rebuilds the index and invalidates every retrieval number you have — vectors from two models are not comparable, so there is no gradual migration. That makes this the one choice in a RAG stack you make under lock-in, and the deciding numbers are bytes per vector and who controls the model lifecycle, not a leaderboard rank.

By Agentic AI Wiki 16 min read

Swapping your LLM edits a prompt. Swapping your embedding model re-embeds the corpus, rebuilds the index and invalidates every retrieval number you have ever measured — vectors from two models sit in different spaces and cannot be compared, so there is no gradual migration and no A/B test cheaper than the migration itself. This is the one component in a retrieval stack you choose under lock-in, which is why the deciding numbers are bytes per vector and who controls the model's lifecycle. Leaderboard rank is the least useful input on the table.

At a glance

Four models that cover the four postures actually available in 2026: the incumbent everyone already calls, the multimodal one, the one that optimises the storage bill, and the one you can put on your own disk and never lose.

ModelAccessDefault vectorList price
OpenAI text-embedding-3-large First-party API; Azure 3072 dims, float32 — 12 KiB $0.13 / 1M tokens
Cohere Embed v4 Cohere API, Bedrock, Azure AI Foundry, SageMaker 1536 dims, float32 — 6 KiB $0.12 / 1M text tokens; $0.47 / 1M image tokens
voyage-3.5 Voyage API; also via AWS Marketplace and Azure 2048 dims, int8 available — 2 KiB $0.06 / 1M tokens
Qwen3-Embedding-8B Open weights, Apache-2.0 up to 4096 dims, float32 — 16 KiB Your GPU, your electricity
Where each embedding model leans hardest A four-by-five grid comparing maximum input length, output dimensions, sub-float output types, non-text input and lifecycle control across OpenAI text-embedding-3-large, Cohere Embed v4, voyage-3.5 and Qwen3-Embedding-8B. Cohere leads on input length and images, voyage on compressed output, Qwen3 on lifecycle control, and OpenAI leads on nothing except ubiquity. Five axes, four models Max input per request Output dimensions Sub-float output Non-text input Lifecycle control OpenAI text-embedding-3-large ~8k tokens 3072 default, shortenable float only Text only Vendor's clock Cohere Embed v4 128k tokens 256 to 1536 int8, uint8, binary Images, inline with text Vendor's clock Voyage AI voyage-3.5 32k tokens 256 to 2048, Matryoshka int8, uint8, binary Text only Vendor's clock Qwen Qwen3-Embedding-8B 32k tokens up to 4096 Whatever you write yourself Text only Apache-2.0, frozen on disk Clear advantage on this axis Adequate Constraint you will feel
Nobody leads on every axis, and the axes are not equally load-bearing for you.

Two of those cells deserve to be read twice. Cohere's 128k input is a different order of magnitude from OpenAI's roughly 8k, and it changes what a "chunk" is allowed to be. Qwen3-Embedding-8B ranked first on the MTEB multilingual leaderboard when Qwen published it in June 2025, at 70.58 — the only entry here whose weights you can pin, mirror and still be running unchanged in 2031.

The choice you make once

What changing an embedding model actually touches The source corpus feeds two parallel embedding passes. The old model's index keeps serving live query traffic while the new model's index is built and shadowed, so both indexes are resident at once. Downstream, chunk size, top-k, reranker thresholds and every retrieval eval baseline have to be re-established against the new vector space before traffic can cut over. Source corpus every chunk, read again Embed pass model A, already paid Index A serving every query Embed pass model B, full corpus Index B shadow, unproven Query traffic unaware, unpaused Re-established against the new vector space before cutover, none of it transferable: chunk size · top-k · reranker threshold · hybrid weights · every retrieval eval baseline
Both indexes are resident at once, and nothing downstream of the vector space transfers.

Two models, two spaces, no bridge

An embedding is a coordinate in a space that one particular model invented during training. Cosine similarity between a vector from model A and a vector from model B is not a weak signal; it is a category error, in the same way that a latitude compared against a Fahrenheit reading is. There is no projection you can learn cheaply that fixes this, no dual-write period where both models serve the same index, and no way to migrate ten percent of the corpus and measure. The unit of change is the whole corpus.

Every other component in the stack degrades gracefully by comparison. A generation model can be swapped behind a router and evaluated on live traffic. A reranker sits on top of retrieval and can be turned off. A vector database can be dual-written and cut over per collection. The embedding model is the only one where the migration is atomic and the rollback is "did you keep the old index".

The bill is not the problem

People price this migration as an API charge, which is the small part:

# 20M chunks at ~400 tokens each
tokens = 20_000_000 * 400          # 8.0e9

# The embed pass, at list price
openai_3_large = tokens / 1e6 * 0.13   # $1,040
voyage_3_5     = tokens / 1e6 * 0.06   # $  480

# The part that is not the bill:
#   both indexes resident until cutover  ->  2x vector storage
#   every retrieval baseline             ->  re-measured from zero
#   top-k, reranker cut-off, hybrid mix  ->  re-tuned per index
#   rollback                             ->  only if you kept index A

A thousand dollars is nothing. Six weeks of an engineer re-tuning top-k and reranker thresholds, re-labelling a golden set because the old relevance judgements were made against different neighbours, and defending a change that moves some queries backwards is the actual price. Teams do not avoid re-embedding because it is expensive in dollars. They avoid it because it is expensive in confidence.

Which means the choice compounds in one direction

If the migration is this awkward, the rational move is to pick the model whose constraints you will not outgrow, not the one that is 1.5 points ahead this quarter. The constraints that bite later are input length (you will want bigger chunks), output width (you will want a smaller footprint), modality (a scanned PDF will arrive) and lifecycle (the model will be deprecated). Quality rank, the thing every comparison leads with, is the constraint that ages best on its own — a two-point retrieval gap closes when you fix chunking, and it never becomes a migration.

The four, and what each is actually for

OpenAI text-embedding-3-large — the default that stopped being the frontier

It is on every tutorial, in every framework's default configuration, and it is the model your team already has a key for. It is also the widest vector in this comparison at 3072 float32 dimensions, capped at roughly 8k tokens of input, text only, float only, and the most expensive per token at $0.13. Matryoshka training means you can ask for 1024 or 256 dimensions and cut storage proportionally with modest quality loss — which most teams never do, because the default works and nobody owns the vector-store line item.

Pick it when retrieval is a supporting feature rather than the product, your corpus is small enough that storage is a rounding error, and the value of "nobody has to evaluate anything" exceeds the value of the difference. That is a real and common situation. Just make it a decision rather than a default.

Cohere Embed v4 — the one that deletes a pipeline

Embed v4 takes text and images in the same request, interleaved, with a 128k-token input window, configurable output from 256 to 1536 dimensions, and int8, uint8 and binary output types. Text is $0.12 per million tokens; images are billed separately at $0.47 per million image tokens.

The reason to choose it is not a benchmark delta. It is that a slide, a chart, a scanned invoice or a screenshot can be embedded as what it is, rather than being pushed through an OCR-and-layout pipeline that you then have to own, monitor and re-run when the parser improves. If your corpus is genuinely visual, Embed v4 removes a whole subsystem from your architecture — and a subsystem removed beats two points of nDCG every time. If your corpus is plain text, you are paying twice the price of voyage-3.5 for capability you will never call.

voyage-3.5 — the one that reads the storage bill

voyage-3.5 supports 2048, 1024, 512 and 256 dimensions through Matryoshka learning, with float, int8, uint8, binary and ubinary output, a 32k input window, and the lowest list price here at $0.06 per million tokens. Voyage's own figure for the combination it recommends — int8 at 2048 dimensions — is an 83% reduction in vector-database cost against float at 3072 dimensions, at higher retrieval quality. The cost half of that claim is not a benchmark; it is division. 2048 bytes against 12,288 bytes is 83.3%, and you can verify it with a calculator.

The quality half is a vendor's number on a vendor's evaluation and should be treated as such. But the asymmetry is what matters: if the quality claim is merely not worse, the storage arithmetic alone decides the question for any corpus large enough to have a vector-store line item.

Qwen3-Embedding-8B — the one you can freeze

Apache-2.0 weights, up to 4096 dimensions, a 32k input window, 100-plus languages, and the top of the MTEB multilingual leaderboard at 70.58 when Qwen published it in June 2025. It is also 8 billion parameters you now have to serve, at 16 KiB per vector if you take the full width, on hardware you provision for an embedding workload whose shape is bursty by nature — quiet during serving, saturated during a re-index.

You do not pick this for the leaderboard position. You pick it for the one property nothing on the API side can offer: the model cannot be deprecated out from under you. A checkpoint on your own storage is the only version pin that actually holds, and for a corpus you intend to keep for a decade, that is a different kind of argument than a price per million tokens. The 0.6B and 4B members of the same family exist precisely so that this posture does not require an 8B serving budget.

Cross-cutting comparison

Storage is the axis that compounds

Bytes stored per vector at each model's default output Horizontal bars comparing storage per vector: Qwen3-Embedding-8B at 4096 float32 dimensions needs 16,384 bytes, OpenAI text-embedding-3-large at 3072 float32 needs 12,288 bytes, Cohere Embed v4 at 1536 float32 needs 6,144 bytes, and voyage-3.5 requested as int8 at 2048 dimensions needs 2,048 bytes — an eight-fold spread before any quality argument is made. Bytes per vector, at each model's default output 4 KiB 8 KiB 12 KiB 16 KiB Qwen3-Embedding-8B 4096 dims, float32 16,384 B OpenAI text-embedding-3-large 3072 dims, float32 12,288 B Cohere Embed v4 1536 dims, float32 6,144 B voyage-3.5 2048 dims, int8 2,048 B Same corpus, same index, same query path — eight times the storage from top row to bottom
Eight times the storage from the top row to the bottom, before anyone argues about quality.

The embed pass is charged once; the vectors are stored forever, and on managed vector databases the price is a function of bytes resident and bytes searched. Across the four defaults, the same twenty-million-chunk corpus is 328 GB of raw vectors under Qwen3 at full width, 246 GB under OpenAI, 123 GB under Cohere and 41 GB under voyage-3.5 at int8. That difference does not appear on the model invoice at all — it appears on a different vendor's bill, which is exactly why it survives so many model comparisons unmentioned.

Three of the four give you a lever here and it is nearly free to pull: Matryoshka training means shorter vectors degrade gracefully rather than catastrophically, and int8 output typically costs a fraction of a point of recall for a four-fold reduction. The teams paying the most for storage are almost always the ones that never passed a dimensions or embedding_types argument, not the ones that picked the wrong model.

Quality differences are smaller than your chunking

Every one of these models will be within a few points of the others on a public retrieval benchmark, and the ranking will reorder between benchmarks, domains and languages. Meanwhile the gap between a naive 512-token fixed-width chunker and one that respects document structure is routinely larger than the gap between the best and worst model here — and the gap between no reranker and a reranker is larger still. If you have not yet tuned chunking, the model comparison is measuring your chunker.

This is also why MTEB rank is a bad primary input: it is a leaderboard that models are now trained with knowledge of, on tasks that are not yours, aggregated in a way that hides the domain you care about. Use it to build a shortlist of three. Decide between them on 200 queries from your own corpus with your own relevance judgements, which is a two-day job and the only measurement that transfers.

Multimodality is an architecture change wearing a benchmark's clothes

Only Cohere takes an image here. That reads like one row in a matrix and behaves like a fork in the pipeline. The text-only path requires a parsing stage — OCR, layout reconstruction, table extraction, figure captioning — that has its own failure modes, its own vendor, its own bill and its own upgrade treadmill, and that quietly determines your retrieval ceiling because nothing downstream can recover information the parser dropped. Embedding the page directly does not make that problem disappear so much as move it inside a model you do not have to operate.

The honest caveat: it also makes the failure opaque. When a parser mangles a table you can look at the parse. When a multimodal embedding misses the number in the corner of a chart, there is nothing to inspect. Choose the visual path when your documents are visual, not because it sounds more modern.

Lifecycle is the deprecation you cannot ride out

When a generation model is retired you change a string, re-run your evals and absorb some behaviour drift. When an embedding model is retired, you re-embed the corpus — the migration this whole post is about, on the provider's schedule rather than yours. Every API model here carries that exposure; the open-weight one does not, because a checkpoint on disk has no end-of-life date. That is the single strongest argument for open weights in the retrieval layer, and it has nothing to do with cost or privacy.

The mitigation, if you stay on an API — and most teams should — is to keep the ingredients of a re-embed permanently ready: the chunk text stored alongside the vectors rather than only in the source system, an embed job that can run end-to-end from cold, and a retrieval eval set that is version-controlled and re-runnable in an afternoon. Teams that hold those three can absorb a forced migration in a week. Teams that do not discover during the deprecation window that they cannot reproduce their own index.

When to pick which

SituationPickBecause
Retrieval is a feature, corpus under a few million chunksOpenAI text-embedding-3-largeThe difference will not repay the evaluation time. Pass dimensions=1024 and move on.
Corpus is slides, scans, screenshots, chartsCohere Embed v4Deletes the parsing subsystem rather than optimising it, and 128k input lets a chunk be a document.
Tens of millions of chunks and a vector-store bill you can seevoyage-3.5, int8Lowest price per token and a quarter of the bytes; the storage saving dwarfs the token saving.
Data residency, air-gap, or a corpus you must serve for a decadeQwen3-Embedding-8BThe only option with no deprecation date. Start at 0.6B or 4B unless you have measured the need for 8B.
Heavily multilingual, especially non-Latin scriptsQwen3 or Cohere, shortlisted; decide on your own queriesMultilingual rank moves most between benchmarks, so this is the case where public numbers transfer worst.
You have not tuned chunking yetNone of them — fix chunking firstOtherwise the comparison is measuring your chunker, and you will re-embed again afterwards anyway.

FAQ

Can I migrate embedding models incrementally, one collection at a time?

You can migrate one index at a time if your corpus is partitioned into indexes that are never searched together. You cannot mix models within a single searchable space: similarity between vectors from different models is meaningless, so a partially migrated index returns nonsense for the fraction it has not caught up on.

Does a smaller vector always mean worse retrieval?

Not proportionally. Models trained with Matryoshka representation learning concentrate the most important information in the leading dimensions, so truncation degrades gently — and quantisation-aware training makes int8 output close to free in quality terms. Measure it on your own queries; the loss from 2048 float to 2048 int8 is usually far smaller than teams expect, and the storage saving is exactly four-fold.

Is MTEB rank useless?

It is useful for exclusion and misleading for selection. A model far down the table is unlikely to surprise you; the ordering of the top ten does not predict which one wins on your corpus. Use it to pick three candidates, then spend two days building 200 labelled queries from your own data — that measurement is the one that survives contact with production.

What actually happens when an API embedding model is deprecated?

You get a notice window, and then you re-embed everything before it closes. There is no version pin that helps, because the old vectors stay valid only as long as the endpoint that produced compatible ones stays up. Keep chunk text stored next to your vectors and keep your embed job runnable from cold, or the window will find you unable to rebuild your own index.

Should I self-host embeddings to save money?

Rarely for cost alone. At $0.06 per million tokens an eight-billion-token corpus embeds for a few hundred dollars, which does not pay for a GPU. Self-host for lifecycle control, data residency or a genuinely enormous re-embed cadence — and if it is only cost, a 0.6B model on a CPU box will already be cheap enough that the 8B one is irrelevant.

Further reading

On this wiki:

Sources: