Throughput, not just accuracy, decides whether your vector pipeline survives contact with production traffic. Picking the best embedding model for throughput means balancing tokens-per-second, batch behavior, and dimension size against your retrieval needs. This guide lays out an ordered path to evaluate and ship an embedding model under real load.
1. Define your throughput profile
Start with numbers, not model cards. Capture peak and steady-state documents per second, average document size in tokens, and whether ingestion is streamed or batched. A nightly bulk load of 10M paragraphs tolerates different tradeoffs than a user-facing service embedding 500 queries per second with p99 latency budgets.
Compute required tokens/sec: docs_per_sec * avg_tokens_per_doc. If you need 2,000 docs/sec at 512 tokens each, that’s ~1M tokens/sec. Few hosted embedding endpoints sustain that on a single key without sharding. This reality narrows the field faster than any leaderboard.
Record your constraints explicitly:
{
"peak_docs_per_sec": 2000,
"avg_tokens_per_doc": 512,
"p99_latency_budget_ms": 200,
"batch_size": 128
}
2. Shortlist by dimension and architecture
Vector search cost scales with dimension. A 1536-dim index costs 4x the memory and approximate-search compute of a 384-dim one for the same number of vectors. For many retrieval tasks, a well-trained 384- or 768-dim model holds recall within a point or two of larger ones. The best embedding model for throughput is often the smallest model that meets your recall bar.
Open-source models (BGE-small, GTE-base, E5-small) deployed on your own GPUs give you fixed cost and full batch control. Hosted APIs offload ops but impose rate limits and per-token pricing. If you serve multiple models, an OpenAI-compatible gateway simplifies client code—n4n.ai exposes one endpoint covering 240+ models and falls back automatically when a provider is rate-limited, which is useful when A/B testing candidates.
Dimension also affects payload size over the wire. A 768-dim float vector is 3KB; a 1536-dim one is 6KB. At 10k queries/sec that difference is 30MB/s vs 60MB/s of pure vector traffic before any document text.
3. Build a representative benchmark harness
Synthetic “lorem ipsum” lies. Sample 50k real documents from your pipeline and embed them with the same chunking you ship. Measure wall-clock time and p99 per-batch latency, not just provider-reported stats.
import asyncio, time
from openai import AsyncOpenAI
client = AsyncOpenAI(base_url="https://api.n4n.ai/v1", api_key="KEY")
async def embed_batch(model, texts):
t0 = time.monotonic()
resp = await client.embeddings.create(model=model, input=texts)
dt = time.monotonic() - t0
return dt, resp.usage.total_tokens
async def run(model, batches):
for b in batches:
dt, toks = await embed_batch(model, b)
print(f"{model}: {toks/dt:.0f} tok/s, {dt*1000:.1f} ms/batch")
# batches = [list_of_128_docs, ...] built from real corpus
Run this for each shortlisted model at your production batch size. The best embedding model for throughput will show near-linear scaling up to the provider’s max batch tokens, then plateau or error.
4. Measure batch scaling and concurrency
Single-request latency is irrelevant; pipelines batch. Increase batch size from 8 to 128 and watch tokens/sec. Many hosted models cap input at 8k or 32k tokens per request—exceeding that throws errors, not slowness. Split intelligently.
def chunk_tokens(docs, max_tokens=32000):
out, cur, t = [], [], 0
for d in docs:
cur.append(d); t += len(d.split()) # approximate; use real tokenizer
if t >= max_tokens:
out.append(cur); cur, t = [], 0
if cur: out.append(cur)
return out
Drive concurrency with asyncio.gather across shards to saturate the endpoint. Note provider rate limits: you may need multiple API keys or a gateway that honors client routing directives to spread load. Concurrency without batching wastes connections; batching without concurrency leaves GPU lanes idle.
5. Account for tokenization and preprocessing
Embedding APIs hide tokenization, but local models don’t. A fast transformer can be bottlenecked by a slow tokenizer or PDF text extraction upstream. Profile the full stage. Some multilingual models tokenize non-Latin scripts character-by-character, inflating token counts and dropping throughput.
If you cache embeddings for static documents, forward provider cache-control hints. Gateways that forward those hints (like the n4n.ai endpoint) let you skip re-embedding unchanged content, effectively boosting throughput without model changes. This is especially valuable for documentation sites where 80% of chunks are stable across builds.
6. Validate retrieval quality under load
Throughput wins mean nothing if recall collapses. Build a query set with known relevant docs. Embed your corpus with candidate models, load into a vector store, and measure recall@10.
# eval sketch
hits = index.query(embed(query), top_k=10)
recall = sum(1 for q in queries if q.relevant in hits[q]) / len(queries)
A 384-dim model hitting 0.91 recall vs a 1536-dim at 0.93 may be worth 3x throughput. The best embedding model for throughput is the one that keeps recall above your product threshold at the highest tokens/sec. Run this eval at concurrency equal to production, because quantization or batch padding can subtly shift outputs.
7. Ship with fallback and routing
Production breaks. Providers degrade. Design the client to handle 429s with backoff and to switch models on failure. If you use a gateway, set routing directives to prefer a primary model and fall back to a same-dimension secondary. Per-token usage metering lets you track cost per million docs embedded.
Honor cache-control on repeated content. For incremental indexing, only embed changed chunks. This operational discipline often beats squeezing another 5% from the model.
8. Pre-ship checklist
- Real-corpus benchmark at production batch size and concurrency
- Tokens/sec vs dimension tradeoff documented with p99 latencies
- Recall@k validated within 1pt of target under load
- Fallback path and routing directives tested against injected 429s
- Cache hints configured for static or repeated content
Pick the smallest model that passes the bar. Throughput is a system property, not a model label.