Serving dense embedding and reranking models in production involves fundamentally different hardware and execution bottlenecks than autoregressive LLM text generation. While generative decoder models are memory-bandwidth-bound during single-token autoregressive decoding, embedding models (such as BGE-M3, ModernBERT, GTE-Qwen2, and Snowflake Arctic) and cross-encoder rerankers operate purely in encoder or forward-pass pooling mode. They are compute-bound and latency-critical.
In retrieval-augmented generation (RAG) and enterprise search architectures, embedding engines must balance two conflicting traffic profiles: sub-10-millisecond latency for single-query online retrieval, and multi-thousand-token-per-second throughput for bulk corpus ingestion. Four primary open-source serving engines dominate production deployments today: Hugging Face Text Embeddings Inference (TEI), Infinity, Qdrant FastEmbed, and vLLM (pooling mode). Each implements a distinct architectural philosophy across batching mechanics, runtime dependencies, model co-location, and hardware targets.
The Embedding Serving Bottleneck: Token Packing and Padding Waste
Standard deep learning serving frameworks batch incoming inference requests by request count. In text embedding pipelines, where document chunk lengths vary widely (from short 15-token search queries to 512-token or 8,192-token document passages), fixed request batching forces quadratic padding overhead. If an engine pads all sequences in a batch of 32 to the length of the longest 512-token document, over 70% of Tensor Core compute can be wasted calculating attention over padding tokens.
Dedicated embedding engines solve this through token-budget dynamic batching and FlashAttention integration. Instead of batching by request count, the engine batches by cumulative token count, packing heterogeneous sequence lengths into continuous memory buffers.

Hugging Face Text Embeddings Inference (TEI)
Hugging Face Text Embeddings Inference (TEI) is a purpose-built inference binary written entirely in Rust. It serves dense embeddings, cross-encoder rerankers, sequence classification models, and SPLADE-style sparse embeddings with minimal execution overhead.
Architectural Characteristics
- Rust Runtime and Candle/Safetensors Backend: TEI bypasses the Python runtime entirely during the request lifecycle. It compiles directly against custom CUDA kernels, FlashAttention-2, and Hugging Face Candle or PyTorch C++ bindings.
- Token-Level Dynamic Batching: Incoming requests enter an asynchronous queue where they are sliced and packed into batches bounded by maximum token budgets rather than request counts. This eliminates padding waste and saturates GPU compute.
- Streaming Tokenization: Tokenization runs concurrently in Rust on CPU worker threads using
tokenizers, streaming pre-allocated token IDs directly into GPU staging buffers. - Single-Model Isolation: TEI is strictly designed as a single-model container. To serve an embedding model and a reranker, teams deploy two isolated container instances.
Operational Trade-Offs
TEI achieves the lowest p99 tail latency and highest raw throughput for standalone, single-model GPU deployments. Its memory footprint is minimal (often under 2 GB of VRAM for base BERT models), and it exposes native gRPC and OpenAI-compatible REST endpoints. However, its strict single-model design increases container management overhead when operating complex multi-stage retrieval pipelines.
Infinity
Infinity is an asynchronous inference server designed to serve multiple embedding, reranking, and multimodal retrieval models from a unified endpoint. Maintained by Michael Feil, it combines an async Python control plane with high-performance C++ and Rust execution backends.
Architectural Characteristics
- Multi-Engine Execution Layer: Infinity allows teams to toggle backends per model, supporting PyTorch, ONNX Runtime, TensorRT, and Hugging Face Optimum.
- Multi-Model Co-Location: Unlike TEI, a single Infinity instance can host multiple models concurrently (for example, a dense embedding model, a cross-encoder reranker, and a CLIP image embedder) on the same GPU, sharing the CUDA context.
- Broad Architecture Coverage: Infinity natively supports dense text embeddings, cross-encoders, multimodal CLIP and CLAP models, and late-interaction vision-document models such as ColPali and ColQwen2.
- Async Dynamic Batching: It implements continuous queue batching in Python using asynchronous workers, matching token-level sorting to minimize inter-sequence padding.
Operational Trade-Offs
Infinity is the most versatile solution for teams running composite RAG pipelines that require embeddings, rerankers, and multimodal encoders without provisioning separate GPU nodes for each model. The multi-model co-location reduces infrastructure spend on small-to-medium clusters. However, its Python-based request coordination introduces slightly higher per-request overhead at extreme concurrency compared to pure Rust runtimes.

FastEmbed (Qdrant)
FastEmbed from Qdrant represents a fundamentally different architectural pattern: an embedded, in-process runtime rather than a client-server microservice.
Architectural Characteristics
- Zero-PyTorch Dependency: FastEmbed is packaged as a lightweight Python and Rust library that executes models exclusively via ONNX Runtime. It eliminates the 2+ GB PyTorch dependency tree.
- In-Process Execution: Applications import FastEmbed directly into their ingestion or search processes. Vectors are generated locally in memory without HTTP or gRPC serialization hops.
- CPU and Quantization Optimization: FastEmbed defaults to quantized INT8 and FP32 ONNX model artifacts optimized for x86 AVX-512 and ARM NEON instruction sets, allowing high-throughput embedding generation on standard cloud CPUs.
- Built-in Model Hub: The library maintains an internal registry of pre-quantized embeddings, sparse text models (BM42, SPLADE), and cross-encoder rerankers.
Operational Trade-Offs
FastEmbed is the optimal choice for serverless environments (such as AWS Lambda or Google Cloud Functions), edge devices, and batch data ingestion pipelines where deploying and monitoring a dedicated GPU inference cluster is cost-prohibitive. It eliminates network latency and connection pooling overhead. Its limitation is scalability for massive multi-GPU parallel processing, where dedicated microservice engines with hardware schedulers are required.
vLLM (Pooling / Embedding Mode)
vLLM is primarily known as an autoregressive text generation engine, but its pooling runner (--task embedding) supports dense representation extraction for large decoder-based embedding models.
Architectural Characteristics
- Tensor Parallelism for 7B+ Embedders: Frontier embedding models built on modern decoder architectures (such as NV-Embed-v2, Qwen2-7B-Instruct-Embedding, and SFR-Embedding) exceed the memory limits of single standard GPUs when processing 32k context windows. vLLM provides out-of-the-box Megatron-style Tensor Parallelism across multi-GPU nodes.
- PagedAttention Context Allocation: For long-context document embedding (up to 32k or 128k tokens), vLLM manages intermediate attention memory blocks dynamically, preventing out-of-memory crashes on bursty document batches.
- Unified Serving Infrastructure: Teams already operating vLLM clusters for generative models can reuse the same deployment patterns, monitoring stacks, and OpenAI API abstractions.
Operational Trade-Offs
For standard BERT, RoBERTa, or ModernBERT models (100M to 500M parameters), vLLM carries unnecessary architectural weight and higher latency overhead than TEI or FastEmbed. However, for 7B+ parameter frontier embedding models requiring distributed multi-GPU execution across long context windows, vLLM remains the primary production solution.
Architecture and Feature Comparison
Runtime and Deployment Model
- Hugging Face TEI: Pure Rust microservice compiled with Candle and FlashAttention-2; strictly one model per container instance.
- Infinity: Python async control plane with Rust/C++ backends (PyTorch, ONNX, TensorRT); supports multi-model co-location on a single GPU.
- FastEmbed: In-process embedded Python and Rust library powered by ONNX Runtime; no external service deployment required.
- vLLM (Pooling): Python and C++/CUDA microservice; supports multi-GPU Tensor Parallelism for large decoder models.
Supported Model Topologies
- Hugging Face TEI: Dense text embeddings, cross-encoder rerankers, sequence classification, and SPLADE sparse embeddings.
- Infinity: Dense text embeddings, cross-encoder rerankers, CLIP/CLAP multimodal encoders, and ColPali/ColQwen2 late-interaction models.
- FastEmbed: Dense text embeddings, BM42 and SPLADE sparse vectors, and cross-encoder rerankers.
- vLLM (Pooling): Dense decoder-based pooling embeddings and encoder-decoder feature extraction.
Hardware and Distributed Scaling
- Hugging Face TEI: Optimized for single-GPU Tensor Core throughput; scales horizontally via multi-container replication.
- Infinity: Single-GPU and multi-device support with mixed precision (FP16, FP8, INT8 via TensorRT/ONNX).
- FastEmbed: Optimized for CPU vectorization (AVX-512, ARM NEON) and lightweight GPU execution; scales across local worker threads.
- vLLM (Pooling): Multi-GPU Tensor Parallelism across NVLink and InfiniBand for 7B+ parameter embedding models.
Engineering Decision Matrix
Selecting an embedding serving engine depends on model scale, latency budgets, and infrastructure topology:
- Choose Hugging Face TEI when building dedicated, high-throughput search or vector ingestion pipelines on single-GPU instances using sub-1B parameter models (BGE, E5, ModernBERT, GTE). It offers the lowest p99 tail latency and highest GPU token saturation.
- Choose Infinity when running composite RAG pipelines requiring co-located dense embeddings, cross-encoder rerankers, and multimodal vision models (CLIP or ColPali) on shared GPU hardware with flexible TensorRT or ONNX backends.
- Choose FastEmbed when operating serverless microservices, edge runtimes, CPU-only cloud nodes, or local ingestion workers where eliminating network hops, PyTorch container dependencies, and dedicated cluster maintenance is paramount.
- Choose vLLM when serving large 7B+ decoder-based embedding models across distributed multi-GPU clusters requiring Tensor Parallelism and long-context memory management.
Sources
- Hugging Face Text Embeddings Inference Documentation
- Hugging Face TEI GitHub Repository
- Infinity GitHub Repository (michaelfeil/infinity)
- Accelerating Embedding and Reranking Models on AMD Using Infinity (Hugging Face Blog)
- Qdrant FastEmbed Documentation and Guide
- FastEmbed GitHub Repository (qdrant/fastembed)
- Serving Embedding Models in vLLM Documentation
- vLLM GitHub Repository
