Embeddings in ML Systems: How to Train, Serve and Version Vectors
Embeddings for system design: what they are, how two-tower and contrastive models learn them, embedding tables, serving and refreshing vectors, versioning.
An embedding is a dense vector of numbers (typically 64 to 1,536 of them) that represents an item, a user, a query, a piece of text or an image, so that similar things end up close together. Embeddings are how ML systems handle ids with millions of values, compare text and images by meaning, and retrieve a thousand good candidates out of a billion in milliseconds. This guide covers how they are learned, stored, served and refreshed, which is what system design interviews probe.
What an embedding gives you
- Compression: a user id with 500 million values becomes a 128-number vector instead of a 500-million-wide one-hot column.
- Similarity: distance between vectors (cosine similarity or dot product) measures relatedness, so "find items like this" becomes a nearest-neighbour search.
- Transfer: an embedding learned on one task (say watch history) is a strong feature for another (say notifications).
- Cross-modal matching: text and images embedded in one space let a text query find photos.
How embeddings are learned
| Method | Training signal | Typical use |
|---|---|---|
| Embedding layer in a model | The model's own task loss (click, purchase) | Id features in ranking models |
| Two-tower (dual encoder) | Pull users towards items they engaged with, push away others | Candidate retrieval for recommendations and search |
| Contrastive learning | Two views of the same thing should match (image + caption) | Visual search, multimodal retrieval |
| Co-occurrence (word2vec style) | Items that appear in the same sessions are similar | Item-to-item recommendations |
| Graph embeddings | Nodes close in a graph should be close in space | People You May Know, fraud rings |
| Pretrained text / image encoders | Large-scale pretraining, optionally fine-tuned | Semantic search, RAG, classification features |
The two-tower model
The workhorse of retrieval. One tower encodes the query side (user, context, or search text), the other the item side. Training uses (user, item engaged) pairs as positives and other items in the batch as negatives. Because the towers only meet at a final dot product, item vectors can be precomputed and indexed, and only the user vector is computed at request time.
In-batch negatives over-penalise popular items (they appear as negatives more often), so production systems correct the logits by item frequency, and mix in hard negatives: items that look relevant but weren't chosen.
Serving embeddings
- Item vectors live in an approximate nearest neighbour index (HNSW, IVF-PQ) for retrieval, and in a key-value store for lookup as ranking features.
- User vectors are either precomputed daily (cheap, stale) or computed per request from recent behaviour (fresh, costs a model call).
- Embedding tables inside ranking models can be huge: 1 billion ids × 64 floats × 4 bytes is 256 GB, so they are sharded across parameter servers or GPUs, and rare ids are hashed together.
- Quantisation (float32 to int8, or product quantisation) cuts index memory 4× or more with a small recall loss.
Index sizing: 200M items × 256 dims
float32 : 200M × 256 × 4 B ≈ 205 GB → shard across ~4-8 machines
int8 : 200M × 256 × 1 B ≈ 51 GB → fits on 1-2 large machines
PQ (32 B per vector) ≈ 6.4 GB → one machine, lower recall; rerank exact
Query cost: ~1-10 ms per ANN search at recall@100 ≈ 0.95 (tuned)Refreshing and versioning
Embeddings from different model versions live in different spaces: a user vector from model v2 compared to item vectors from v1 is meaningless. So:
- Tag every stored vector with the model version that produced it.
- On a new model, re-embed the whole corpus into a new index in the background.
- Switch user-side and item-side together (blue-green), and keep the old index until the new one is verified.
- New items between full rebuilds are embedded on arrival with the current model and inserted incrementally.
Re-embedding a large corpus is a real batch job: 200M items at 2,000 items per second per GPU is about 28 GPU-hours. Budget for it whenever you change the encoder.
Evaluating embeddings
- Retrieval metrics: recall@k against held-out engagements (did the item the user actually watched appear in the top 500?).
- Downstream impact: offline ranking metrics or an online test using the new candidates.
- Sanity checks: nearest neighbours of known items, clustering by category, and drift in the vector distribution between versions.
Where it’s used
Two-tower retrieval over a catalogue of hundreds of millions of items, with user vectors refreshed from the current session.
Text chunks embedded with a pretrained encoder and searched by meaning; see RAG.
Contrastively trained image embeddings find visually similar products; see visual search.
In an interview
- Use a two-tower model for retrieval and explain why item vectors can be precomputed.
- Size the index and propose quantisation or sharding if it doesn't fit.
- Explain negatives: in-batch, popularity correction and hard negatives.
- Say how you re-embed and swap indexes when the encoder changes.
Frequently asked questions
What is an embedding?
A dense vector of numbers that represents an item, user, text or image so that similar things are close together. Embeddings compress huge id spaces and let systems search by similarity.
What is a two-tower model?
A retrieval model with one network encoding the user or query and another encoding items, trained so engaged pairs score highly. Item vectors can be precomputed and indexed for fast nearest-neighbour search.
What happens to embeddings when you change the model?
Vectors from different model versions are not comparable, so the whole corpus must be re-embedded into a new index, and query and item sides switched together.
Further reading
- Sampling-Bias-Corrected Neural Modeling for Large Corpus Item RecommendationsYi et al., Google, RecSys 2019
- Efficient Estimation of Word Representations in Vector SpaceMikolov et al., 2013