A recall regression lands in your retrieval-augmented pipeline. The eval that was green last quarter now misses documents it used to surface. The reflex is to blame the embedding model and schedule a retrain. Often that is the wrong lever entirely. If your vector index is built on IVF-PQ — the default index type in FAISS for anything past a few million vectors — the recall you observe is not a fixed property of your embeddings. It is a property of a lossy approximation whose behaviour depends on how the index was trained, how aggressively it compresses vectors, and how well the queries you serve today resemble the data the index was fit to. All three of those things drift after you deploy. A retrain of the embedder touches none of them. That is the misconception worth correcting up front: IVF-PQ recall is an index-tuning problem masquerading as a model problem. Understanding the mechanism tells you which of the two you are actually looking at. What’s worth understanding about IVF-PQ first? IVF-PQ is two techniques stacked. The name is literal: an inverted file (IVF) sits on top of product quantization (PQ). They solve different parts of the same problem, which is that exhaustive nearest-neighbour search — comparing a query against every vector — gets prohibitively slow and memory-hungry as the corpus grows. The inverted-file step handles where to look. During index construction, k-means clustering partitions the vector space into nlist cells, each with a centroid. Every vector gets assigned to its nearest centroid. At query time, instead of scanning all vectors, the index compares the query to the nlist centroids, picks the closest nprobe cells, and only searches inside those. If you have a million vectors in 4,096 cells and probe 16 of them, you have cut the candidate set to roughly one sixty-fourth of the corpus before you compare a single full vector. The product-quantization step handles how much each comparison costs. PQ splits each vector into m sub-vectors and, for each sub-space, learns a small codebook of 2^nbits representative centroids. A vector is then stored not as its raw floats but as m codebook indices — a compact code. A 768-dimensional float32 vector is 3,072 bytes; the same vector as an m=64, nbits=8 PQ code is 64 bytes. Distances are approximated by looking up precomputed sub-space distances rather than doing full arithmetic. In practice this means IVF-PQ turns exhaustive similarity search into a bounded-latency lookup, cutting query latency and index memory footprint by large factors — at a measurable recall cost, because both steps discard information. This behaviour is documented in FAISS’s published index guidance and reproducible on any corpus you own (benchmark-class: measure it against your own data before trusting a rule of thumb). What is the difference between the IVF partitioning step and the PQ compression step? They fail in different ways, which is why keeping them mentally separate matters when you debug. IVF is a routing approximation. It can send a query to the wrong cell. If a query vector sits near a cell boundary, its true nearest neighbour may live in an adjacent cell you did not probe. Raising nprobe widens the search and recovers those misses — at linear latency cost. The failure mode is missed cells. PQ is a representation approximation. Even when the right vector is inside a probed cell, its stored code is lossy, so the approximate distance can rank it below a worse-but-better-quantized neighbour. Raising nprobe does nothing for this; the vector was already in the candidate set and still got misranked. The failure mode is distance error. This split is the single most useful thing to internalise. When recall is low, the question is not “how do I raise recall” but “which of the two approximations is costing me the misses” — because the levers are disjoint. Confusing them is why teams push nprobe to the point where latency regresses while the real loss was in the code size all along. How do nlist, nprobe, m, and nbits trade recall against latency and memory? Four parameters, two of them fixed at build time, two of them tunable at query time. Getting the roles straight prevents most of the thrashing. Parameter Set at Governs Raise it → Lower it → nlist Build Number of IVF cells Faster per-probe scan, finer partitions, needs more training data Coarser cells, cheaper training, lower ceiling on recall/latency trade nprobe Query Cells searched per query Higher recall, higher latency (roughly linear) Lower latency, lower recall m Build PQ sub-vectors (code length) Higher recall, larger index memory, slower distance calc Smaller footprint, more distance error nbits Build Bits per sub-code (codebook size) Higher recall, larger codebooks Smaller codebooks, coarser quantization The trap is that only nprobe is adjustable at query time. nlist, m, and nbits are baked into the index; changing them means a rebuild, which needs representative training data and a maintenance window. So when recall looks wrong, nprobe is the knob the library exposes, and teams reach for it because it is the only lever that does not require a rebuild. That accessibility is exactly what makes it the wrong first move when the loss is a PQ representation problem — you can push nprobe to nlist (full scan of every cell) and still not recover recall that was lost to an undersized m. A rough working intuition, worth verifying on your own corpus rather than adopting blind: nlist on the order of the square root of the vector count is a common starting point; m should divide the embedding dimension cleanly; nbits=8 is the near-universal default because it keeps codebook lookups cache-friendly. These are starting points for a sweep, not settled values — the same discipline a well-scoped hyperparameter sweep in an AI proof-of-concept applies to any tunable system. When does an IVF-PQ recall drop indicate a retrieval issue, not an embedding-model problem? This is where the mechanism pays off in a live incident. A recall regression in a retrieval-augmented system has two broad causes, and they call for opposite responses. If the embedding model itself degraded — because you swapped model versions, changed the tokenizer, or the domain shifted so far the embeddings no longer separate — then the geometry of the vector space changed and a retrain or re-embed is the correct fix. But if the model is unchanged and recall still fell, the geometry is intact and the loss is downstream, in how the index approximates that geometry. A retrain there is wasted compute that leaves the actual defect in place. Use this diagnostic before you touch either the model or the index: Run a brute-force baseline on a sample. Compute exact nearest neighbours for a few hundred current queries with a flat (non-quantized) search. If the flat baseline surfaces the right documents but IVF-PQ does not, the embeddings are fine and the loss is in the index. If the flat baseline also misses them, the problem is upstream in the model or the data. Check whether misses are missed cells or misranks. Force nprobe = nlist on the failing queries. If recall recovers, you were under-probing (IVF routing). If it does not, the loss is in the PQ codes (representation) and only a rebuild with larger m/nbits helps. Diff the query distribution against the training distribution. IVF centroids were fit to a snapshot. If live queries have drifted into regions the training data underpopulated, cells there are coarse and recall is structurally low regardless of nprobe. Only the first branch of the first bullet points at the model. Everything else is an index decision. This is why we treat the retrieval layer as part of the eval-coverage map in a reliability audit, not as a black box behind the model — the retriever has its own failure surface, and it drifts on its own schedule. How does query-distribution drift degrade IVF-PQ recall after deployment? The IVF centroids and PQ codebooks are trained once, on whatever data you had at build time. They are frozen. Your queries are not. When the distribution of live queries moves — a new product line, a seasonal shift, a language your training set underrepresented — queries start landing in cells whose centroids were fit sparsely, or in regions of the space where the PQ codebook has poor resolution. The index has not changed and the embeddings may be perfectly good, but recall for the drifted segment falls because the approximation was never tuned for that region. In our experience auditing production retrieval, this is the most common cause of a “the model got worse” complaint where the model, on inspection, did nothing at all (observed across engagements; not a benchmarked rate). A drift monitor for an IVF-PQ retriever should therefore watch more than embedding statistics. It should track the recall delta between IVF-PQ and a periodic brute-force sample on current traffic, the distribution of which cells queries route to (a shift toward previously-cold cells is an early signal), and the fraction of queries whose nearest centroid distance exceeds the distribution seen at training time. Those signals fire before end-users notice, which is the whole point of monitoring. Where such monitors belong in the broader serving picture is easier to reason about once you have mapped the machine-learning serving path end to end, and drift entering through the retrieval hop is one of the places an LLM orchestration pipeline quietly loses quality. What recall and latency metrics should a reliability audit measure? A retrieval layer needs its own line in the eval-coverage inventory, with metrics that make the recall-for-speed trade explicit rather than hidden. When we scope a production-AI reliability audit — the kind of engagement our R&D and validation services exist to run — the retriever gets the same instrumentation rigour as the model. The four measurements that matter: recall@k versus a brute-force baseline. Not recall in the abstract — recall relative to exact search on the same embeddings, so you isolate the index’s contribution from the model’s. p95 retrieval latency. The tail, not the mean, because nprobe blows up the tail first and that is what users feel. Index memory per million vectors. The footprint you bought with PQ compression; it caps how large the corpus can grow before a re-shard. Recall delta after query-distribution drift. The gap between recall on training-era queries and recall on current traffic — the metric that tells you when to rebuild rather than retrain. Track those four over time and the “is it the model or the index?” question answers itself from the dashboard instead of from a war room. FAQ How does IVF-PQ work in practice? IVF-PQ combines two approximations. The inverted-file step partitions the vector space into nlist cells and searches only the closest nprobe of them at query time, so you avoid scanning the whole corpus. The product-quantization step compresses each vector into a compact code of m sub-codes so distance comparisons are cheap. Together they turn exhaustive similarity search into a bounded-latency lookup, cutting latency and memory by large factors at a measurable recall cost. What is the difference between the inverted-file (IVF) partitioning step and the product-quantization (PQ) compression step? IVF is a routing approximation: it can send a query to a cell that does not contain the true nearest neighbour, and raising nprobe recovers those misses. PQ is a representation approximation: even inside the right cell, a lossy code can misrank vectors, and nprobe does nothing for it — only a larger m or nbits (a rebuild) helps. They fail differently, so their fixes are disjoint. How do the nlist, nprobe, m, and nbits parameters trade recall against latency and memory? nlist (cells) and m/nbits (code size) are fixed at build time; nprobe (cells searched) is tunable at query time. Raising nprobe lifts recall at roughly linear latency cost. Raising m or nbits lifts recall but grows index memory and requires a rebuild. Because only nprobe is adjustable live, teams over-use it even when the real loss is in the frozen code size. When does an IVF-PQ recall drop indicate a retrieval issue rather than an embedding-model problem? Run a brute-force baseline on a sample of current queries. If exact search surfaces the right documents but IVF-PQ misses them, the embeddings are fine and the loss is in the index — a retrain is wasted. If the brute-force baseline also misses them, the problem is upstream in the model or the data. Forcing nprobe = nlist further separates an IVF routing miss from a PQ representation loss. How does query-distribution drift degrade IVF-PQ recall after deployment, and what should the drift monitor watch? IVF centroids and PQ codebooks are frozen at build time; live queries drift. When traffic moves into sparsely-trained cells or poorly-resolved code regions, recall for that segment falls even though the embeddings are unchanged. The drift monitor should watch the recall delta against a periodic brute-force sample on current traffic, shifts in which cells queries route to, and the fraction of queries whose nearest-centroid distance exceeds the training-time distribution. What recall and latency metrics should a reliability audit measure for an IVF-PQ retriever? Four: recall@k relative to a brute-force baseline on the same embeddings, p95 retrieval latency (the tail nprobe inflates first), index memory per million vectors, and the recall delta between training-era queries and current traffic. Tracked over time, these distinguish an index-tuning need from a model-retrain need without a war room. The next time a retrieval eval regresses, resist the retrain reflex long enough to run the brute-force baseline. If the loss is in the index, you have a quantization and partitioning decision to make — a recall-stability failure that a production-AI validation pack is built to catch, so the retrieval layer is audited on its own drift schedule rather than assumed to inherit the model’s.