m: 0 disables graph construction for vectors that are never searched directly
Setting m to 0 on a named vector tells Qdrant to skip HNSW graph construction entirely for that vector. It still stores the vectors, you can still retrieve them, and you can still score against them - you just cannot run an approximate nearest-neighbor search that originates from that vector. This is exactly what you want for a vector that is only ever used as a reranking field. In a ColBERT-style late-interaction setup, the multivector field is not used to find candidates; it is used to rescore a small set of candidates that were found by a cheaper first-stage retriever (dense or sparse). Building an HNSW graph for it would be wasted memory, wasted build time, and wasted index maintenance, because no query ever traverses that graph.
The mechanism matters because HNSW graph construction is the expensive part of indexing, not vector storage. For a multivector field with, say, 128 token vectors per point, building an HNSW graph over all those token vectors would be hundreds of times more expensive than for a single-vector field, and the resulting graph would be enormous. Since the field is only ever scored against a candidate set of, say, 100 points, the approximate search that HNSW provides is useless - you are doing exact MaxSim over 100 candidates, which is a few milliseconds at most. So m: 0 is not a limitation, it is the correct configuration. The same logic applies to any named vector that is only used for reranking or for exact scoring: set m: 0 to save the index cost and rely on the first-stage retriever to provide candidates. The only thing you lose is the ability to do a direct ANN search against that field, which is exactly the operation you have decided you do not need.
m: 0 on a named vector disables HNSW for that field only; other fields keep their own index configuration.
The vectors are still stored and still retrievable; you can still score against them with an exact distance.
The field cannot be the top-level query target in a query_points call unless you also provide a prefetch, because there is no index to search.
Memory savings can be substantial for multivector fields, where the graph would otherwise dominate the index footprint.
The trade-off is that you must always have a first-stage retriever feeding the reranker. If you ever need to search directly against the multivector field - for example, to evaluate recall of the reranker in isolation - you have to either use exact search over a small candidate set or temporarily build an index. This is a real constraint, and it is why some teams keep a separate small collection with an indexed multivector for evaluation. The common mistake is thinking m: 0 means the vector is disabled or ignored. It does not - it is stored, it participates in scoring, it just does not get a graph. Another common mistake is setting m: 0 on a vector that is actually used as a first-stage retriever, which results in queries that silently fall back to a full scan or fail, depending on the query shape. If you see unexpectedly slow queries on a collection with m: 0 on the query field, that is almost always the cause. Version note: the ability to set per-vector hnsw_config (including m: 0) has been available for several releases, but the exact interaction with multivector fields and with the prefetch/fusion API has evolved - check the release notes for your version.
Version-dependent: the per-vector hnsw_config override (including m: 0) and the multivector_config with MAX_SIM comparator are part of the qdrant-client 1.10+ API surface. On older versions, multivector support and per-vector index overrides were more limited or absent, so verify against your version before copying this configuration.
You set m: 0 on a named vector and now queries against that field are extremely slow. Explain what is happening and how to fix the query shape.
A teammate thinks m: 0 means the vectors are not stored. How would you demonstrate that they are still stored and still used in scoring?
You have a collection with a dense field and a ColBERT field, both indexed with m: 16. Memory is 3x over budget. What do you change first and what recall impact do you expect?
A new engineer adds a reranking field and forgets to set m: 0. Build time quadruples. Walk through how you would diagnose this and what the fix looks like.
Design a collection schema for a hybrid search system with dense, sparse, and ColBERT fields. Which fields get an index, which get m: 0, and how do you keep the total index memory under a fixed budget?
You need to support both a fast endpoint (dense only, top-10) and a high-quality endpoint (dense + ColBERT rerank, top-10) on the same collection. How do you configure the collection so both endpoints share storage but have different latency profiles?
A product decision requires direct ANN search on the ColBERT field for a new feature, but the memory budget cannot support a full HNSW graph over all token vectors. Propose a design that supports the feature without building a full graph, and quantify the recall/latency trade-off.
You must migrate a 500M-point collection from a single-vector schema to a dense + ColBERT schema with m: 0 on the reranker, with zero downtime. Describe the migration, including how you backfill the multivector field and how you validate reranker quality before cutover.