Embedding Models · Research

Best Open-Weight Embedding Models 2026: Benchmarks, Dimensions and VRAM Cost

ThreatFrontier poster showing Claude Code internals as a local agent runtime with tools permissions sessions and SDK
OP

AI security researcher · Updated Sep 12, 2026, 12:37 PM EDT

Dimension count, sequence length and model size decide your index memory, chunk limits and ingest hours. A framework that prices the retrieval quality you buy.

An embedding model is the lens through which your entire corpus is seen. It takes a span of text and returns a fixed-length list of numbers, positioned so that texts meaning similar things land near each other. If the model cannot tell two of your documents apart, no reranker and no larger generation model will recover the distinction, because the candidate set handed to them never contained the right document.

The choice matters more than teams expect, for a reason unrelated to quality scores: it is frozen into your index. Vectors from one model are meaningless in another model's space. Changing the embedding model is not a config edit, it is re-running inference over every chunk you have ever ingested and rebuilding the index. The generation model you can swap on a Tuesday. The embedding model you keep until you schedule a reindex.

What follows is a framework, not a ranked list. Ranked lists age badly: positions change as new checkpoints land, and any number printed here would be stale before you read it. What does not change is the set of properties that determine fit and cost.

The properties that actually matter, and what each costs

Dimension count drives your bill

Every vector has a fixed width. Higher dimensions carry more information and generally retrieve better. They also multiply everything downstream, linearly. Memorise the index size formula:

index_bytes = vectors x dimensions x bytes_per_component

Take a corpus that chunks down to 5 million vectors at 1024 dimensions in float32, four bytes per component:

5,000,000 x 1024 x 4 = 20,480,000,000 bytes, about 20 GB

That is raw vectors, before the index structure. A graph index such as HNSW adds neighbour links per vector, roughly vectors x links_per_vector x 4 bytes for 32-bit identifiers, which on a large corpus is not a rounding error. Low-latency search wants this in memory, so 20 GB is a machine-size decision, not a disk-space one. Halve the dimensions and the corpus needs about 10 GB; quarter them, about 5 GB, and latency falls too, since distance computation scales with dimension count.

Matryoshka: buying dimensions back after training

Dimension count used to be fixed at training time: for a smaller vector you picked a smaller model, or ran a reduction step that damaged quality unpredictably.

Matryoshka representation learning changes that, and it is the most practically useful recent development here. The model is trained so information is front-loaded: the first slice of the vector is itself a usable embedding, a longer slice is better, the full width best. Truncation degrades gracefully instead of falling off a cliff. Several widely used open families ship Matryoshka-trained checkpoints, and the major hosted APIs expose a dimension parameter built on the same idea.

Operationally this is a cost lever you pull after training, per deployment, without changing models. Embed once at full width and store truncated vectors at whatever your memory budget allows. Measure retrieval quality at each truncation point on your own data: the curve is typically flat for a while then bends, and you want to sit just before the bend.

Truncation is only safe on models explicitly trained for it: lopping components off an ordinary embedding destroys it. If the card does not say so, assume no.

Maximum sequence length is a hard ceiling on chunks

Every model has a maximum input length in tokens, and text beyond it is truncated, usually silently. Feed a document twice the limit and you get a vector representing the first half, indexed under the whole document's identity, with no error in your logs.

This constrains chunking directly. Chunk size must sit inside the limit with headroom for any instruction prefix:

chunks = corpus_tokens / (chunk_tokens - overlap_tokens)

Chunk size is a retrieval decision as much as a capacity one. Small chunks match precisely but fragment context. Large chunks preserve context and dilute the vector: one embedding of a long passage averages out everything in it, so a query can miss a document that answers it in a single buried sentence. Verify the real limit empirically, since tokeniser mismatches between your chunker and the model routinely cause silent overflow.

Model size and ingest throughput

Embedding a corpus is a batch job, and the one genuinely large compute expense in a retrieval system.

ingest_hours = total_chunks / (chunks_per_second x 3600)

Measure chunks_per_second on your own hardware, at your chunk length and batch size. Attention cost grows quadratically with sequence length, so throughput measured on short chunks overstates what you get on long ones.

Serving VRAM follows from the model's own published parameter count:

weights_bytes = parameters x bytes_per_parameter

Two bytes per parameter at fp16 or bf16, one at int8. Add activation memory, which grows with batch size and sequence length and is what actually triggers out-of-memory failures during ingest. Size the box from your model's published numbers, not from a table in an article.

Query-time embedding is a different regime: one short forward pass, negligible next to vector search and generation. If your corpus is small and static, ingest is a one-off and you can afford the larger model; if you re-ingest continuously, throughput may dominate the budget.

Multilingual capability

Either the model was trained on your languages or it was not. An English-centric model given French or Hindi produces vectors, without complaint, that cluster poorly. Read the card's training data description. Cross-lingual retrieval, where an English query should find a Japanese document, is a stronger requirement than multilingual support and needs its own test.

Domain fit

General-purpose models underperform on corpora that are not general. Code, legal contracts, clinical notes and jargon-heavy internal documentation have vocabulary and structure that general training data underrepresents. A model strong in aggregate can be mediocre on your domain, and a smaller domain-appropriate model can beat a larger general one. If your corpus is specialised, weight your own evaluation above any published average.

Asymmetric search and instruction prefixes: the silent failure

This one is common, costly, and produces no error.

Retrieval is usually asymmetric: a short question matched against a long passage that answers it. Many models are trained for this and expect queries and documents to be embedded differently, typically by prepending an instruction or prefix. Some families use a query prefix only, some distinct prefixes for each, some a task instruction string, some none at all where adding one hurts.

Get it wrong and nothing breaks. You get vectors. Search returns results. Quality is quietly worse, sometimes dramatically, and with no error and no symptom the team spends weeks tuning chunk sizes and rerankers to recover ground lost in a missing prefix string.

Enforce this in code review:

  • Follow the card's usage section exactly, including whitespace.
  • Put prefix logic behind separate embed_query and embed_document functions, so no caller can embed a query as a document.
  • Store the prefix configuration alongside the index. It is part of the index's identity.
  • Add a prefix-correctness case to your evaluation: embed a known pair correctly and incorrectly and confirm the scores differ. If they do not, your wrapper is wrong.
  • Never mix conventions within one index.

Reading a leaderboard without being misled

MTEB, the Massive Text Embedding Benchmark, is the right place to start a shortlist and the wrong place to finish one. It aggregates across task families: retrieval, reranking, classification, clustering, semantic similarity, pair classification, summarisation, bitext mining. The headline number averages all of them. If you are building retrieval, most are irrelevant, and a model can climb the aggregate on clustering strength while being unremarkable at what you need. Filter to the retrieval subset, then to datasets resembling your domain, before comparing anything.

Read small gaps as noise. Two models within a point of each other on an aggregate tell you nothing about which serves your corpus better; variance across datasets dwarfs the difference.

Benchmark contamination is real. Public benchmarks are visible to everyone training models, optimising against them is hard to avoid and harder to detect from outside, and a model tuned for a public set has not necessarily learned anything that transfers to your documentation.

Positions also move constantly, so check the current leaderboard yourself rather than trusting any list, including this one. The leaderboard narrows the field to three or four. Your own evaluation picks the winner.

The families worth knowing

By role, not by number. Check current sizes, dimensions and context limits on each model's own card, since they change across releases.

General-purpose retrieval. The BGE, E5 and GTE families are the workhorses of open-weight retrieval, each shipping several size tiers so you can move along the quality-versus-throughput curve without changing ecosystems. Start here unless you have a reason not to. Most publish clear prefix guidance, and several offer Matryoshka-capable checkpoints.

Long-context. Checkpoints in the Jina and Nomic families target longer inputs, for documents that resist clean chunking. Useful when your unit of retrieval is genuinely long, less useful than it sounds otherwise.

Multilingual. Several of the above ship explicitly multilingual variants, and the Qwen embedding family is built with broad language coverage in mind. Pick from this group rather than hoping a general model generalises.

Code. Code-specialised models exist across several families and materially outperform general ones on code search. Indexing a repository, use one.

Lightweight and edge. The sentence-transformers ecosystem hosts many small, fast CPU-capable models, and is the standard tooling layer for loading the families above. For high-volume ingest or on-device work, a small model that is good enough beats one you cannot afford to run.

Open weights versus hosted APIs

Hosted APIs are trivially easy to start with: a key, one call, no GPU. That convenience is real.

The cost has three parts. First, data control: every document you index passes through a third party. For many organisations the corpus is the sensitive asset, more so than any individual query, and shipping it wholesale to an external provider is a data-transfer decision deserving the same review as any other. Retention terms matter, and so does whether the provider may let your corpus inform anything else.

Second, recurring cost. Hosted embedding is priced per token and ingest is your large token volume. Re-embedding after a chunking change is a fresh bill, which discourages the experimentation that improves retrieval.

Third, lock-in. A provider can deprecate a model version, and switching means a full reindex on their timetable.

Self-hosting inverts this. The corpus stays inside your perimeter, ingest is a fixed compute cost you control, re-embedding is free at the margin, and the weights sit on your disk indefinitely. You pay in serving infrastructure and operational attention.

The cost arithmetic, worked

Take the same 5 million chunks through each lever:

float32, 1024 dims:  5,000,000 x 1024 x 4 = about 20 GB
float32,  512 dims:  5,000,000 x  512 x 4 = about 10 GB
float32,  256 dims:  5,000,000 x  256 x 4 = about  5 GB

Quantization reduces bytes_per_component, not dimensions.

Scalar quantization maps each float32 component to an int8, one byte instead of four. At 1024 dimensions:

5,000,000 x 1024 x 1 = about 5 GB

A four-fold reduction, usually at small recall cost.

Binary quantization reduces each component to a single bit:

5,000,000 x 1024 / 8 = about 0.64 GB

A thirty-two-fold reduction, with distance becoming a very fast Hamming computation. Recall drops more noticeably, which is why binary quantization is almost always paired with rescoring: sweep the binary index for a generous candidate set, then rescore those candidates against full-precision or scalar-quantized vectors and return the top k. Only the rescoring set needs the expensive representation resident. This pattern is standard in production and supported natively by most serious vector databases.

The levers compose: truncate to 512 dimensions and quantize to int8 and the same corpus fits in about 2.5 GB, down from 20 GB. Whether recall survives is an empirical question about your data.

A selection matrix

SituationPrioritise
Large corpus, tight memoryMatryoshka support and quantization; moderate dimensions
Small corpus, quality firstLargest model you can serve; full precision; no truncation
Continuous high-volume ingestThroughput and model size over peak benchmark quality
Long documents, hard to chunkSequence length, then verify long-input quality
Non-English or cross-lingualExplicit multilingual training; test cross-lingual pairs
Code or specialised domainDomain-specific model; weight your own evaluation heavily
Sensitive or regulated corpusOpen weights, self-hosted; hosted embedding is a data transfer
Edge, on-device or CPU-onlySmall model, low dimensions, quantized from the start
Prototype, days not weeksHosted API, but abstract the interface and plan migration

Evaluating properly on your own data

This is a day of work, and it saves a reindex that costs far more.

Build a labelled set. Collect 50 to 200 real queries, ideally from actual users, and identify the documents that genuinely answer each. This is the expensive part and the part you cannot skip: a synthetic set generated from your own documents measures how well the model matches text to itself, not questions to answers.

Hold everything else constant. Same chunking, overlap, preprocessing and store settings across every candidate. The most common evaluation error is comparing two models under two chunking configurations and blaming the model.

Measure recall at k and MRR. Recall at k asks whether the relevant document appeared in the top k, which is what the generation model needs; mean reciprocal rank asks how high. Set k to what you will really put in context, and measure both across every candidate.

Check the prefixes. Confirm each candidate's conventions are implemented exactly as its card specifies. A model evaluated with wrong prefixes looks worse than it is, and you may reject the best option on your own bug.

Only then look at cost. Compute index size, ingest time and serving VRAM for candidates that cleared the quality bar. Often two are indistinguishable on quality and differ several-fold on cost, which makes the call obvious.

Migration reality

Assume you will change models eventually, and build so it is a scheduled operation, not a crisis.

  • Version the index. The name or namespace should carry the model identifier and version. Two models must never write into the same index.
  • Record the configuration next to the data. Model name, exact revision, dimension count, truncation setting, quantization mode, prefixes, chunk size, overlap, tokeniser. Store it with the index, not in a wiki. Six months on this is the difference between a clean rebuild and archaeology.
  • Keep the source text. Re-embedding needs the original chunks. If you stored only vectors, migration means reprocessing source documents, and that is when you find some are gone.
  • Plan the cutover. Dual-write into old and new indexes and switch reads when the new one completes, or build offline and swap atomically. Both need ingest capacity budgeted ahead.
  • Re-evaluate on the same labelled set, kept in version control.

Closing checklist

  1. Profile the corpus: documents, token volume, languages, domain, growth rate, sensitivity.
  2. Decide self-hosted versus hosted, treating data control as a first-class input.
  3. Set the memory budget, then work vectors x dimensions x bytes_per_component backwards to the dimension and precision you can afford.
  4. Filter the current MTEB leaderboard to retrieval tasks resembling your domain; take three or four candidates in your size class.
  5. Check each candidate's sequence length against your chunk size, and its prefix conventions against what you will implement. Prefer Matryoshka-capable checkpoints if memory is tight.
  6. Build the labelled query set. Measure recall at k and MRR under identical chunking.
  7. Compare index size, ingest hours and serving VRAM for the survivors, and test quantization on the winner before committing hardware.
  8. Version the index and record the configuration beside it.

The model you pick shapes every retrieval your system performs for as long as the index lives. A day spent measuring on your own data is the cheapest insurance available.