Store embeddings and run vector similarity search in Cosmos DB
Two declarations, one container, one chance
A document in a vector-enabled container is an ordinary Azure Cosmos DB for NoSQL item with one unusual property on it: a long array of numbers.
Listing 1: one item, holding its own text, its metadata, and its embedding
{
"id": "handbook-2026-p42",
"tenantId": "contoso",
"title": "Employee handbook 2026",
"page": 42,
"text": "Expense claims must be submitted within 30 days...",
"embedding": [0.0123, -0.0456, 0.0789]
}
The embedding array is truncated here; a real one from a text model carries 1,536 or 3,072 numbers. That colocation is the point of the feature. Microsoft describes it as storing vectors directly in the documents alongside your data, so that the vectors are stored in the same logical unit as the data they represent[1]. One query can therefore return both the similarity ranking and the title and page your application needs to cite the answer, with no second lookup into another store.
The previous page in this domain, querying Cosmos DB with the Python SDK, covers getting items out when you know an id or can write a predicate. This page covers the case where you can do neither, because the thing you are looking for is semantically like your question rather than equal to any value you can name. That is still a search, in the same sense that page uses the word: the engine has to consider candidates. It is not an address. Everything here assumes you can already write a Cosmos DB query in Python and bind a parameter to it; by the end you will be able to declare the two policies a vector container needs, pick an index type your embedding's dimension count actually permits, write and scope the query that ranks against it, and tell which of those decisions you cannot take back.
The feature is off until you turn it on
Vector indexing and search is an account capability, not something a container inherits. You enable it on the account page under Settings then Features, selecting Vector Search for NoSQL API, or from the CLI:
az cosmosdb update \
--resource-group <resource-group-name> \
--name <account-name> \
--capabilities EnableNoSQLVectorSearch
Microsoft notes the registration request is autoapproved, but it might take 15 minutes to take effect[1], which is long enough to look like a broken deployment if you are not expecting it.
The container vector policy: what the vector IS
With the capability on, a container needs a vector policy before it can run a similarity search. It is a vectorEmbeddings array, one entry per vector property, and Microsoft documents four fields: path (required, the property holding the vector), datatype, dimensions, and distanceFunction. The defaults are float32, 1536 dimensions, and cosine.
One detail bites people before they ever run a query, so take it at first sight rather than in a troubleshooting list later. Microsoft's prose writes the second field as datatype, all lower case, while every JSON sample on the same pages writes it as dataType. JSON keys are case sensitive, so those are not interchangeable. Copy the spelling from the samples, dataType, which is what the Python walkthrough's own policy object[2] uses.
The accepted values for that field are the other place the documentation is not of one mind, and it is worth knowing which way it splits. The integrated vector store page[1] lists float32, float16, int8, and uint8, adds a note that using float16 instead of float32 can reduce the storage footprint of vectors by 50 percent with some reduction in accuracy, and ships a two-path policy sample whose second path is declared float16. The performance-tuning page[3] devotes a table row to float16 and calls it the first precision reduction to try. Meanwhile the shared Azure-and-Fabric vector database page[4] lists only float32 (default), int8, and uint8, with float16 absent. Two pages support it — one ships a working two-path policy sample declaring float16, the other recommends it as the first precision reduction to try — while the third page's parameter list omits it entirely. Treat float16 as available on the Azure Cosmos DB for NoSQL surface, and confirm against the page for your exact surface before you build a storage estimate on it. The page that omits it is the shared Azure-and-Fabric one, and that is the lesson worth carrying past this one field: these pages run near-identical prose under different path shapes, so a sentence that matches what you were looking for proves nothing about whether you are reading the page that governs your surface. Check the URL, not just the wording.
Listing 2: a container vector policy with two vector paths
{
"vectorEmbeddings": [
{
"path": "/embedding",
"dataType": "float32",
"distanceFunction": "cosine",
"dimensions": 1536
},
{
"path": "/coverImageVector",
"dataType": "float16",
"distanceFunction": "dotproduct",
"dimensions": 100
}
]
}
Each path gets at most one policy, though a container may hold several policies as long as they all target different paths. The distanceFunction value is the metric the engine uses to compare two vectors, and Microsoft documents three for a container policy: cosine, which runs from −1 for least similar to +1 for most similar; dot product, from −∞ to +∞; and euclidean, where 0 is most similar. Match it to the metric your embedding model is scored with rather than picking by taste. For Azure OpenAI text embeddings that is normally cosine, which is also the field's default, and Microsoft's own embeddings article says Azure OpenAI embeddings often rely on cosine similarity[5] to compare a document with a query.
One name collision is worth flagging here. Microsoft also publishes a distance functions explainer[6] that defines Manhattan distance alongside Euclidean, cosine and dot product. Manhattan is explained there as mathematics, not offered as a distanceFunction value; the container policy accepts the three named above.
The indexing policy: how the vector is SEARCHED
The vector policy alone will let a similarity query run, but not efficiently. The container's indexing policy carries a separate vectorIndexes array that names the same path and picks an index type, and Microsoft is direct about what it buys: vector searches have lower latency, higher throughput, and less RU consumption when applying a vector index[7].
The same policy should also push that path out of the ordinary index. An embedding is a large array that no WHERE clause will ever filter on, and the default policy indexes every property of every item. Microsoft states the consequence plainly: the vector path is added to the excludedPaths section to ensure optimized performance for insertion, and not adding the vector path to excludedPaths results in a higher request unit charge and latency for vector insertions[2]. Excluding the path from the standard index does not disable the vector index on it. They are different index structures over the same property, which is exactly what the figure below lays out.
Listing 3: creating the container with both policies, in Python
# Both policies are passed at CREATE time. There is no later edit for them.
container = db.create_container_if_not_exists(
id=CONTAINER_NAME,
partition_key=PartitionKey(path='/tenantId'),
indexing_policy=indexing_policy, # excludedPaths + vectorIndexes
vector_embedding_policy=vector_embedding_policy) # vectorEmbeddings
That single call is where the page's title earns the word chance. Both objects are supplied at creation, and the Python walkthrough[2] says why in one sentence: you set both the container vector policy and any vector indexing policy when you create the container because you can't modify it later. How firm that really is turns out to be the one thing the documentation argues with itself about, and the last section of this page takes it apart properly. For now, plan every choice below as permanent.
Choosing the index type: the cap decides before the cost does
Read the dimension cap before you read anything else about the three index types, because it is the only one of their differences that can remove an option outright.
Azure Cosmos DB for NoSQL publishes three vector index types with a maximum dimension count each: flat at 505, quantizedFlat at 4,096, and diskANN at 4,096. Those numbers appear in the same table on both the indexing policy reference[7] and the integrated vector store page[1]. Set them beside the shape of a real embedding and the consequence is immediate: the vector policy's own default of 1,536 dimensions already exceeds 505, and text-embedding-3-large runs as high as 3,072, so flat cannot index either at any corpus size. The exact-recall option that reads so attractively in the comparison table is unavailable to most text-retrieval workloads before cost, latency or corpus size enter the conversation at all. The figure below places both of those sizes on a single axis against the three caps; everything to the right of the 505 mark is flat's blind spot.
What each type actually does
All three answer the same question, which stored vectors are nearest to this one, and they differ in what they consult to answer it.
flatstores the vectors on the same index as other indexed properties and scans them. Microsoft calls searches against it brute-force, producing 100 percent accuracy or recall, meaning it is guaranteed to find the most similar vectors in the dataset.quantizedFlatalso scans, but over quantized (compressed) vectors. Accuracy might be slightly less than 100 percent because the vectors are compressed before being added to the index, and in exchange the search should have lower latency, higher throughput and lower RU cost than the same search on aflatindex.diskANNis a separate index built for vectors using DiskANN, a suite of high-performance vector indexing algorithms developed by Microsoft Research. It is an approximate nearest neighbors index, so the accuracy might be lower thanquantizedFlatorflat[7], and it offers some of the lowest latency, highest throughput and lowest RU cost queries in exchange. Microsoft's performance page describes it as a graph the search walks, which is why the sharding option later in this page talks about one graph per tenant.
That ordering is a real trade, not a ranking. Exact, compressed-and-exact, and approximate are three different answers to "how sure do you need to be", and only the first is a guarantee.
The 50,000 figure, and the honest version of it
Beyond the caps, Microsoft points quantizedFlat and diskANN at different corpus sizes using a threshold of roughly 50,000 vectors. Below it, quantizedFlat; above it, diskANN.
The threshold is genuinely useful and its denominator is not settled, so do not build a precise rule on it. The integrated vector store page[1] counts the vectors scoped to your search. The shared Azure-and-Fabric page[4] counts them per physical partition. The performance-tuning page[3] hedges across both, writing the sweet spot as fewer than about 50,000 vectors per search scope or partition. Those are not the same measurement: a large container that every query scopes tightly is under the threshold on the first reading and possibly over it on the second. Two of the three — the integrated vector store page and the shared Azure-and-Fabric page — also call the number a general guideline and tell you to test your own scenario, which is the instruction to follow when the denominator matters to your decision.
The floor nobody mentions until it bites
Both compressed types have a minimum. quantizedFlat and diskANN require that at least 1,000 vectors are inserted[1] so the quantization stays accurate, and below that a full scan is executed instead. A development container with 50 test documents therefore does not exercise the index you declared, and its RU numbers tell you nothing about production. Benchmark above the floor or do not benchmark.
Precision, as a second lever on the same axis
The dataType you declared in the vector policy is a cost lever as well as a description. Microsoft's published trade-off is float32 at baseline storage with full precision, float16 at half the storage with a small recall impact for most text workloads, and int8 at a quarter of the storage with a moderate impact, aimed at write-heavy workloads where insert cost matters most. The recommendation is to try float16 first and move to int8 only after validating recall on your own benchmark set[3]. Some of the lost recall can be bought back at query time rather than at write time, which the next section covers.
The build-time knobs, briefly
Both compressed types accept optional index build parameters. quantizationByteSize sets the bytes used per quantized vector, range 1 to 512, defaulting to a system-decided value, and larger values raise accuracy at the cost of RU and latency. indexingSearchListSize sets how many vectors are searched during index build, range 10 to 500, default 100, and applies to diskANN only. A quantizerType of product is the default; spherical is documented as public preview, so treat it as something to watch rather than something to standardise on.
Writing the query: ORDER BY is the search
A vector search is one system function used twice in one statement, and the second use is the one that matters.
Listing 4: the baseline indexed vector search
SELECT TOP 10 c.title, VectorDistance(c.embedding, @embedding) AS score
FROM c
ORDER BY VectorDistance(c.embedding, @embedding)
Microsoft calls this the simplest indexed vector search query[3] and says it uses the vector index and the distance function configured in the container's vector embedding policy. The occurrence in SELECT projects a number your application can rank or threshold on. The occurrence in ORDER BY is what makes the statement a nearest-neighbor search at all: ordering by distance is the operation an index over vectors exists to accelerate, and the function's own optional flag, described below, is defined in terms of how the value is used in an ORDER BY expression. The diagram below traces that one statement end to end, from the user's question to the ranked rows, so you can see which stage each clause is answerable for.
One thing about that listing is not optional. Microsoft attaches an Important callout to it: always use a TOP N clause[1], because otherwise the vector search tries to return many more results and the query costs more RUs and has higher latency than necessary. A vector query without TOP N is not a query that returns everything cheaply; it is the same ranking work spread over a far larger result set.
A note on how the function is spelled
You will meet this function under two spellings and they are one function. The Azure documentation set writes it VectorDistance, in the integrated vector store page[1], the indexing reference, the hybrid search page and the Python walkthrough alike. The query-language reference titles it VECTORDISTANCE in upper case, and then uses VectorDistance in one of its own examples. This guide uses VectorDistance, the form that appears in every Azure-scoped page and in the Python query strings you would copy. Do not read the upper-case spelling as a different or newer function.
The full signature
VectorDistance(<vector_expr_1>, <vector_expr_2>, <bool_expr>, <obj_expr>)
The query-language reference[8] gives the two required arguments as the stored vector path and the query vector, and two optional ones:
| Argument | Default | What it does |
|---|---|---|
bool_expr | false | true forces a brute-force search. false uses any index defined on the vector property, if one exists. |
obj_expr | none | An object literal of query-time options, listed below. |
The options object accepts distanceFunction (Cosine, DotProduct, Euclidean) to override the metric for this query, dataType (Float32, Float16, Int8, Uint8), and three tuning numbers. searchListSizeMultiplier raises the DiskANN search list size, quantizedVectorListMultiplier raises the quantized candidate list, and both improve recall at the cost of RU and latency; Microsoft gives 5, 10 and 20 as typical values. filterPriority takes a float between 0.0 and 1.0 and shifts a filtered diskANN query's balance between matching the WHERE clause and searching the vectors, with a higher priority biasing toward filter matches[3] for fewer RUs and a small recall cost.
One notation detail here will look like a typo the first time you meet it, and it is not. The option values are capitalised — Cosine, Float32 — while the container vector policy takes the same values in lower case, cosine and float32, in every JSON sample Microsoft ships. The Python walkthrough muddies it further: its parameter table writes the policy defaults as Float32 and Cosine while the policy sample directly below it uses lower case. Copy the case from a sample of the surface you are actually writing, lower case in the policy and capitalised in this options object, rather than from a prose table.
Those overrides are the query-time half of the precision decision from the previous section: cheaper vectors on disk, then a larger candidate list at read time when a particular query needs the recall back.
Sort direction is not yours to reason out
Every published example orders by a bare VectorDistance(...) with no ASC or DESC, and Microsoft describes the result as sorted in order of most similar to least similar. It is tempting to add a direction by reasoning about the metric, since cosine reports +1 for the most similar pair while euclidean reports 0, so the two would seem to need opposite sorts. Do not. Follow the published form, which is the same in every example regardless of which metric the policy declares.
Passing the query vector from Python
The query vector is an ordinary query parameter carrying a list of numbers. You embed the user's question with the same model that produced the stored vectors, then bind the result.
Listing 5: the same search from the Python SDK
# query_embedding comes from the SAME model and dimension count as the stored vectors.
query_embedding = embed("how long do I have to file an expense claim?")
for item in container.query_items(
query=(
'SELECT TOP 10 c.title, c.page, '
'VectorDistance(c.embedding, @embedding) AS score '
'FROM c '
'ORDER BY VectorDistance(c.embedding, @embedding)'
),
parameters=[{"name": "@embedding", "value": query_embedding}],
partition_key="contoso"): # scope the search; see the next section
print(item["title"], item["page"], item["score"])
That mirrors the Python walkthrough's own query[2], which binds the embedding as @embedding through the parameters list exactly the way any other Cosmos DB parameter is bound. Two things in it are worth naming. The dimension count of query_embedding has to match the dimensions the policy declares: each of the three metrics compares two vectors coordinate by coordinate, and the policy fixes the length on the stored side, so a query vector of any other length has nothing to line up against. And score is your own alias on the projected value, not a system field, so an application that thresholds on it is reading a number it asked for.
Scoping and filtering: tenants, predicates, and citable rows
The cheapest vector search is the one that never looks at another tenant's vectors, and the partition key is still how you arrange that.
Nothing about vector search changes the scope rungs this domain runs on. A query that supplies the partition key value is an in-partition query; one that does not fans out. Microsoft puts a number on why that matters here: a vector search of TOP 10 against a diskANN index scoped to a single partition key is estimated at up to about 45 RUs, and the same search cross-partition costs that much multiplied by the number of partitions hit[3], with the guidance that fan-out dominates cost and you should scope by partition key whenever possible. Those RU figures are Microsoft's own rough estimates and the page says so; the ratio is the durable part, not the number.
Partition key design for a multitenant corpus
The obvious key, one partition per tenant, runs into a hard ceiling: a logical partition holds at most 20 GB, and an embedding-heavy tenant reaches that faster than a document store would. Microsoft's recommended shape for this is a hierarchical partition key, for example /tenantId then /userId then /documentId, which removes the per-tenant ceiling because each combination is its own logical partition while still letting a query prune other tenants' partitions.
Scope the search to the full hierarchical key when the application knows all its levels, and to at least the top-level path when it does not. The figure below sets the three cases side by side: how much of the container the engine still has to consider when a query supplies none of the key, only its top level, or all of it. There is one piece of operational fine print worth carrying into a design review: Microsoft asks you to contact the team at cosmossearch@microsoft.com to configure the account[1] if you want vector search on collections with hierarchical partition keys. That is a lead time, not a config flag.
A diskANN index can then be sharded to match, using the vectorIndexShardKey property on the index entry. Microsoft describes sharded DiskANN as building a separate DiskANN index graph per logical partition key value rather than one global graph[3], so a tenant-scoped search stays inside that tenant's graph. The shard key can be the container's partition key, the first level of a hierarchical key, or a separate property.
Listing 6: a diskANN index sharded by tenant
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [{ "path": "/*" }],
"excludedPaths": [
{ "path": "/_etag/?" },
{ "path": "/embedding/*" }
],
"vectorIndexes": [
{
"path": "/embedding",
"type": "diskANN",
"vectorIndexShardKey": ["/tenantId"]
}
]
}
JSON does not support comments, so nothing above is annotated; note that excludedPaths and vectorIndexes name the same /embedding path, which is the arrangement the first section described.
Filtering by metadata inside the search
Scope narrows which partitions are consulted. A WHERE clause narrows which items inside them qualify. Microsoft states that vector search can be combined with all other supported query filters and indexes by using WHERE clauses[1], which is what makes a filtered retrieval a single round trip rather than a fetch-then-filter in application code.
Listing 7: filtered semantic retrieval with the fields a citation needs
SELECT TOP 5 c.id, c.title, c.page, c.text,
VectorDistance(c.embedding, @embedding) AS score
FROM c
WHERE c.tenantId = @tenantId AND c.category = 'policy'
ORDER BY VectorDistance(c.embedding, @embedding)
On a filtered diskANN query the filterPriority option from the previous section is the knob for rebalancing the two halves when results come back weak. Microsoft suggests 0.0 as a starting point that runs the similarity search and post-filters the candidates, 0.5 as balanced, and 1.0 as prioritising candidates that match the filter, which tends to converge faster at lower RU cost.
Why the projection list is part of the retrieval design
The SELECT list in Listing 7 is doing more work than it looks. Because the embedding lives in the same item as title, page and text, one query returns the ranking and everything the application needs to quote a passage and attribute it. Drop those fields from the projection to save bandwidth and you have signed up for a second round of reads keyed by id before you can show a citation, which costs more than the bytes you saved.
The practical rule for a retrieval-augmented generation pipeline is to project exactly the fields the answer will cite, plus the score, and nothing else. The score earns its place because it is your only means of dropping weak matches before they reach the model: a top-5 query always returns five rows, however unrelated they are to the question, and only a threshold on the projected value stops the fifth from being passed off as evidence.
Hybrid search: when semantic ranking alone misses the term
Semantic similarity is bad at exact tokens. Ask a vector index for "error MFA-4013" and it will happily return passages about authentication failures generally, because that is what the embedding of the phrase is near. Hybrid search is Azure Cosmos DB for NoSQL's answer, and it works by running both kinds of search and fusing their rankings.
Microsoft describes the two halves plainly. Vector search uses machine learning models to understand the semantic meaning of queries and documents. Full-text search scores documents on the presence and frequency of words and terms using Best Matching 25 (BM25), which the page calls effective for straightforward keyword searches. The results are then combined using the RRF function[9], Reciprocal Rank Fusion, described as a rank aggregation method that merges the rankings from multiple search algorithms to produce a single unified ranking.
The word rank is the part to hold on to. RRF combines positions in two ranked lists, not raw scores, which is what lets a cosine distance and a BM25 score be merged at all when they share no units and no scale. The diagram below shows that shape: one query scored down two independent paths, and a fusion step that reads list positions rather than either score.
What the container needs first
Hybrid search is not a query you can simply write against a vector container. Microsoft's own sequence is: enable the vector indexing and search feature; create a container with a vector policy, a full text policy, a vector index and a full text index; insert data with text and vector properties; then run hybrid queries. The indexing reference adds the second capability toggle, noting you must enable the Full Text & Hybrid Search for NoSQL API feature to specify a full text index[7].
Listing 8: the full text policy, alongside the vector policy already on the container
{
"defaultLanguage": "en-US",
"fullTextPaths": [
{
"path": "/text",
"language": "en-US"
}
]
}
The indexing policy then carries a fullTextIndexes array naming that same /text path, next to the vectorIndexes array naming /embedding. Four declarations in total, and Microsoft's requirement is symmetric for both: a full text indexing policy must be on the path defined in the container's full text policy, exactly as a vector index must be on the path in the vector policy.
The query shape
SELECT TOP 10 *
FROM c
ORDER BY RANK RRF(VectorDistance(c.embedding, @queryVector),
FullTextScore(c.text, @term1, @term2))
ORDER BY RANK is a distinct clause from the plain ORDER BY used for a pure vector search, and RRF takes the component scoring functions as its arguments. FullTextScore takes the text path followed by the search terms.
Weights are optional and go last, as an array with one number per component score. Microsoft's example for weighting the vector half twice as heavily as BM25 adds the array [2, 1] as the final argument to RRF[9]:
SELECT TOP 10 *
FROM c
ORDER BY RANK RRF(VectorDistance(c.embedding, @queryVector),
FullTextScore(c.text, @term1, @term2),
[2, 1])
The positional pairing is the thing to get right: the first weight applies to the first component score listed, so reordering the functions without reordering the weights silently reverses your intent. Nothing errors, the ranking just changes.
Reach for hybrid when your corpus contains identifiers, product names, error codes or other tokens a reader would type verbatim, and stay with a pure vector query when queries are natural-language paraphrases of the content. The cost of hybrid is not only RU; it is two more declarations on a container that, as the next section explains, you may not be able to amend later.
What you cannot change later, and where the docs disagree
Almost everything in a Cosmos DB indexing policy is editable on a live container. The vector parts are the exception, and the size of that exception is the one question this feature's documentation answers two different ways.
Start with the part that is not in dispute, because it is the frame that makes the rest legible. A container's indexing policy can be updated at any time[7], and the update triggers an online, in-place index transformation that does not affect write availability, read availability or provisioned throughput. The hybrid search page states the carve-out from the other direction, noting that other indexes still remain mutable. So the default expectation for anything in an indexing policy is changeable, and vectors are the thing that breaks it.
The two readings, side by side
Five Microsoft pages speak to whether a vector policy or vector index can change after the container exists, and they fall into two camps.
| Reading | Pages | What they say |
|---|---|---|
| Create a new container | index-policy, gen-ai/hybrid-search, how-to-python-vector-index-query | Vector policies and vector indexes are immutable after creation; to make changes, create a new collection. The Python page puts it as supported on new containers only, because you can't modify it later. |
| Drop and re-add | vector-search, gen-ai/vector-search-performance-tips | You can add new path configurations or remove existing ones, but you cannot change the settings of a vector embedding policy or vector indexing policy directly; to do so you must first drop the existing vector policy or index, then add it back with new configuration. |
Both camps agree on the sharp bit: there is no in-place edit of a vector policy's or vector index's settings. They disagree on what remains available instead, and specifically on whether adding or removing a vector path, and dropping and re-adding a policy, are things you can do to a container that already exists.
Do not settle this by publication date. The drop-and-re-add wording currently sits on the most recently updated page in the set, and it is still the minority reading; the other four interleave behind it rather than falling neatly into an older block. A single recent page contradicting three consistent siblings is at least as likely to be a documentation error as a behaviour change, and treating recency as evidence is precisely how a reader ends up planning a migration around a capability that may not be there.
Notice instead where the hedging sits, because it is not symmetric. All three pages on the create-a-new-container side qualify the rule with currently — Currently, vector policies and vector indexes are immutable after creation — which is Microsoft signalling that this particular answer is expected to move. Neither page on the drop-and-re-add side hedges at all, and the performance-tuning page states its version with an always: you can always add new path configurations or remove existing ones, but you cannot change the settings directly. So the reading this page tells you to design around is the one its own sources mark as provisional, and the reading you cannot yet rely on is the one stated flatly. Read that as a reason to re-check the wording before you migrate, not as a reason to prefer whichever sentence sounds more confident.
The engineering position that is correct under both readings
Design as though the vector policy and the vector index are fixed at container creation. That assumption costs you nothing if the drop-and-re-add path does exist and saves you an unrecoverable position if it does not. Concretely:
- Decide the embedding model, and therefore the
dimensions, before you create the container. A later model change is a new container and a full re-embed of the corpus. - Pick the index type for the corpus you expect, not the one you have on day one. A container that grows past the point where
quantizedFlatis the right answer is the exact scenario the disagreement above leaves you unable to plan for confidently. - Build the re-ingest path early. If it is routine to create a container, replay the corpus and switch an alias in configuration, the question of whether the policy is mutable stops being load bearing.
- Check the current wording on the integrated vector store page[1] before you commit a plan that needs the drop-and-re-add behaviour to be real.
The other things you cannot undo or exceed
Microsoft publishes a short list of current limitations on the same page, and three of them shape designs rather than merely constraining them.
- Enabling vector indexing and search on a container cannot be reversed. It is a one-way door on the container, separate from the account-level capability.
- Shared throughput is out. At this time vector indexing and search are not supported on accounts with shared throughput, so a database-level RU allocation is incompatible with the feature.
- Wildcards and array nesting are out. Wildcard characters and vector paths nested inside arrays are not supported in the vector policy or the vector index, so the embedding has to be a plain top-level property.
One more is a throughput planning note rather than a limit: Microsoft says the rate of vector insertions should be limited, and that very large ingestion in excess of 5 million vectors in a short period might require more index build time. A backfill that finishes without errors can still leave the index catching up behind it.
Exam-pattern recognition
Questions on this subtopic tend to hand you a scenario with one number in it that has already decided the answer. Find the number first.
The dimension count is the most common decider
A stem that names an embedding model or its output size, then asks which vector index type to configure, is usually testing the 505-dimension cap on flat. Any dimension count above 505, which includes every common text embedding, eliminates flat outright, and the remaining choice between quantizedFlat and diskANN is made on corpus size around the 50,000-vector mark. An option offering flat for its exact recall on a 1,536-dimension vector is the distractor built for people who read the recall column and stopped.
Watch for its mirror image too: a stem with a small corpus and a small vector, where flat genuinely is available and exact recall is genuinely wanted. The cap removes options, it does not remove the type.
"We need to change it" stems
A scenario where a team wants to swap the distance function, change dimensions or move from quantizedFlat to diskANN on a container already holding data is testing whether you know this is not an ordinary indexing policy update. The answer that survives is the one involving a new container and re-ingesting the data. Be careful with any option asserting flatly that the policy simply can be edited in place; no reading of the documentation supports that, which is what makes it a clean distractor even while the docs remain split on the drop-and-re-add path.
Query-shape stems
Given a query that projects VectorDistance in SELECT but sorts by something else, or one that omits TOP N, the defect is in the clause, not the function. Ordering by VectorDistance is what performs the nearest-neighbor search, and Microsoft's Important callout about always using TOP N is a favourite source of "why is this query so expensive" scenarios. A missing TOP N costs RUs and latency; it does not produce an error, so the symptom in the stem will be cost, not failure.
If the query returns unrelated results with no error at all, look at whether the query vector came from the same model and dimension count as the stored ones, and look at whether the container is scoped correctly.
Cost and latency stems
Three causes cover most of them. A query with no partition key value is a cross-partition fan-out, and Microsoft's guidance is to scope by partition key whenever possible. A container whose vector path is missing from excludedPaths pays a higher request unit charge and latency on every insert, which shows up as expensive writes rather than expensive reads. And a container under 1,000 vectors is running a full scan regardless of the index type declared on it, which is the answer to a stem where a development environment's RU numbers do not match production's.
Retrieval-quality stems
When semantic search misses an exact identifier, product code or error string, the answer is hybrid search: a full text policy and full text index alongside the vector ones, and an ORDER BY RANK RRF(...) query fusing VectorDistance with FullTextScore. When results are merely a little weak on a diskANN index, the answer is query-time tuning, searchListSizeMultiplier or quantizedVectorListMultiplier, before anything structural. When a filtered diskANN query returns poor matches, filterPriority is the named knob.
And when the scenario is about citing sources in a generated answer, the answer is in the projection: the embedding and its source fields live in one item, so the query that ranks the chunks is the same query that returns the id, title and page the citation needs.
The three vector index types, and what actually decides between them
| Consideration | flat | quantizedFlat | diskANN |
|---|---|---|---|
| What it stores | The vectors themselves, on the same index as other indexed properties | Quantized (compressed) vectors on the index | A separate DiskANN index graph built specifically for vectors |
| Max dimensions | 505 | 4,096 | 4,096 |
| How the search runs | Brute-force scan of every candidate vector, exact k-nearest-neighbor | Brute-force scan, but over compressed vectors | Approximate nearest neighbor over the graph |
| Recall | 100 percent, guaranteed to find the most similar vectors | Slightly under 100 percent, because vectors are quantized before indexing | High but approximate, and tunable at query time |
| Where Microsoft points it | Small, focused searches, especially combined with query filters and partition keys | Around 50,000 vectors or fewer in the set your query covers | More than about 50,000 vectors in the set your query covers, up to multi-million scale |
| Minimum vectors to index | None | 1,000, below which a full scan runs instead | 1,000, below which a full scan runs instead |
| Where it is the wrong choice | Any embedding over 505 dimensions, which includes most text models | A corpus that keeps growing past the scoped threshold | A container too small to fill a graph, or one needing guaranteed exact recall |
Decision tree
Sharp facts the exam loves — give these one last read before exam day.
Cheat sheet
Sharp facts the exam loves — scan these before test day.
- A container's vector embedding policy declares the vector path, data type, distance function, and dimensions
To store embeddings you define a vector embedding policy at container creation listing each vector's path, dataType (for example float32), distanceFunction (cosine, dotproduct, or euclidean), and dimensions. The dimensions must equal the embedding model's output size, and the policy is set when the container is created.
Trap Planning to attach or change a vector embedding policy on a container that already exists.
5 questions test this
- You are modeling a container in Azure Cosmos DB for NoSQL for an assistant that answers questions from safety bulletins. A colleague proposes one item per bulletin, holding an array of chunk objects w
- You are creating an Azure Cosmos DB for NoSQL container for a media-archive assistant. An Azure OpenAI deployment produces the embeddings, and the team cannot change that deployment or the number of d
- A compliance team keeps policy bulletins in Azure Cosmos DB for NoSQL and edits them constantly. Today an Azure Function reads the change feed, calls a Microsoft Foundry embedding deployment, and writ
- You are creating an Azure Cosmos DB for NoSQL container for a veterinary triage service. Each item must carry both a clinician's typed symptom note and a photo of the affected area, along with shared
- You are creating an Azure Cosmos DB for NoSQL container for a retrieval workload. Your deployment script writes an indexing policy that defines a diskANN vector index on an embedding property, but the
- The policy's distance function must match how similarity is computed and the model's recommended metric
The distanceFunction chosen in the embedding policy (cosine, dotproduct, euclidean) defines how VectorDistance ranks similarity, so it must align with the embedding model's recommended metric — for example cosine for normalized text embeddings. Mismatching it degrades retrieval relevance.
Trap Assuming any distance function ranks a given model's embeddings equally well.
2 questions test this
- You are writing the vector embedding policy for a container that will hold embeddings of support-article chunks in Azure Cosmos DB for NoSQL. The chunks vary widely in length, so their vectors differ
- You are creating an Azure Cosmos DB for NoSQL container for a media-archive assistant. An Azure OpenAI deployment produces the embeddings, and the team cannot change that deployment or the number of d
- Embeddings are stored as an array property in the same item as their source content and metadata
A vector is a numeric array field on the document, co-located with the chunk text and its metadata (id, title, page). Storing them together lets one query return both the similarity ranking and the fields needed to ground and cite an answer.
5 questions test this
- You are modeling a container in Azure Cosmos DB for NoSQL for an assistant that answers questions from safety bulletins. A colleague proposes one item per bulletin, holding an array of chunk objects w
- A compliance team keeps policy bulletins in Azure Cosmos DB for NoSQL and edits them constantly. Today an Azure Function reads the change feed, calls a Microsoft Foundry embedding deployment, and writ
- You are creating an Azure Cosmos DB for NoSQL container for a veterinary triage service. Each item must carry both a clinician's typed symptom note and a photo of the affected area, along with shared
- A nightly job loads embeddings into an Azure Cosmos DB for NoSQL container whose vector embedding policy declares the embedding path, its dimensions, and its distance function. The vector search query
- You are designing storage for a grounded assistant on Azure Cosmos DB for NoSQL. A colleague proposes a lean container holding only an id and an embedding, with each chunk's text and metadata left in
- The indexing policy defines a vector index of type flat, quantizedFlat, or diskANN
Separate from the embedding policy, the indexing policy's vectorIndexes specifies a vector index type per path: flat (exact brute-force), quantizedFlat (compressed vectors for less storage and faster scan), or diskANN (graph-based approximate nearest neighbor for large collections).
Trap Assuming the vector embedding policy also creates the vector index.
7 questions test this
- You create a container in Azure Cosmos DB for NoSQL for a field-service platform. One property holds 1,536-dimension embeddings of roughly 9 million incident reports that are searched across all depot
- You design a container in Azure Cosmos DB for NoSQL for a pharmaceutical label review tool. The draft model stores one document per label with an array of chunk objects, each chunk carrying its own em
- You plan to add semantic retrieval to an existing Azure Cosmos DB for NoSQL account that has never stored vectors. Your Python deployment script will create a new container whose indexing policy speci
- You develop a clinical-trial protocol assistant on Azure Cosmos DB for NoSQL. Protocol chunks carry 1,536-dimension embeddings, every search is filtered to a single trial holding about 8,000 vectors,
- You are creating a container in Azure Cosmos DB for NoSQL whose depot-scoped semantic searches will run against a quantizedFlat vector index over 1,536-dimension embeddings. Bench tests put recall sli
- Your team is creating an Azure Cosmos DB for NoSQL container for semantic search over 1,536-dimension embeddings indexed with diskANN. A pilot showed recall against exhaustive results below what revie
- You develop a Python retrieval service on Azure Cosmos DB for NoSQL that stores 1,536-dimension chunk embeddings for a maritime logistics knowledge base. The container will hold roughly 12 million vec
- diskANN is a graph ANN; quantizedFlat is a compressed scan; flat is exact
flat computes exact distances by scanning every candidate vector — accurate but costly at scale. quantizedFlat still scans, but over quantized (compressed) vectors, cutting RU and latency at a small accuracy cost. diskANN builds a true graph-based approximate-nearest-neighbor index that scales to millions of vectors at low latency. Choose diskANN for very large collections, quantizedFlat for a mid-size compressed scan, and flat only for small sets or when exact recall is required.
Trap Choosing flat for a million-vector collection because it is the most accurate.
7 questions test this
- You create a container in Azure Cosmos DB for NoSQL for a field-service platform. One property holds 1,536-dimension embeddings of roughly 9 million incident reports that are searched across all depot
- Your production Azure Cosmos DB for NoSQL container serves semantic search over 1,536-dimension embeddings through a diskANN vector index. Before a release you must measure how often the served result
- You develop a clinical-trial protocol assistant on Azure Cosmos DB for NoSQL. Protocol chunks carry 1,536-dimension embeddings, every search is filtered to a single trial holding about 8,000 vectors,
- Your team builds a Python service on Azure Cosmos DB for NoSQL that matches free-text laboratory requests against a controlled vocabulary of roughly 450 approved test names, each stored as a 384-dimen
- You are creating a container in Azure Cosmos DB for NoSQL whose depot-scoped semantic searches will run against a quantizedFlat vector index over 1,536-dimension embeddings. Bench tests put recall sli
- Your team is creating an Azure Cosmos DB for NoSQL container for semantic search over 1,536-dimension embeddings indexed with diskANN. A pilot showed recall against exhaustive results below what revie
- You develop a Python retrieval service on Azure Cosmos DB for NoSQL that stores 1,536-dimension chunk embeddings for a maritime logistics knowledge base. The container will hold roughly 12 million vec
- The vector path is typically excluded from the standard index while covered by the dedicated vector index
Because a raw embedding array is large, teams add its path to excludedPaths in the standard index to avoid needless write RU, while defining the vectorIndexes entry that actually powers similarity search on that same path.
- VectorDistance() computes similarity between a stored vector and a query vector in a SQL query
The VectorDistance(c.embedding, @queryVector) system function returns the distance or similarity between a stored embedding and a supplied query vector using the container's configured metric, and can be projected as a score in the SELECT clause.
5 questions test this
- You develop a retrieval service over an Azure Cosmos DB for NoSQL container whose vector embedding policy declares the euclidean distance function. The service projects VectorDistance as an aliased sc
- You develop a Python retrieval service that queries an Azure Cosmos DB for NoSQL container, projecting VectorDistance as an aliased score and ordering by the same expression. The service calls an Azur
- You develop a semantic retrieval feature over an Azure Cosmos DB for NoSQL container whose vector embedding policy declares cosine as the distance function, holding several hundred thousand indexed ch
- Your team is designing the response contract for a semantic retrieval API backed by an Azure Cosmos DB for NoSQL container that carries a vector embedding policy on the chunk embedding path. A reviewe
- You develop a retrieval-augmented generation service over an Azure Cosmos DB for NoSQL container. For each question it retrieves the 10 nearest chunks and passes all of them to the model. On narrow qu
- ORDER BY VectorDistance(...) with TOP k performs the k-nearest-neighbor search using the vector index
A query of the form SELECT TOP @k c.text, VectorDistance(c.embedding, @q) AS score FROM c ORDER BY VectorDistance(c.embedding, @q) returns the k most semantically similar items and engages the vector index for efficient nearest-neighbor retrieval - approximate on a diskANN index, exact on a flat one.
Trap VectorDistance in SELECT alone does not use the vector index for ranking; the ORDER BY VectorDistance clause is what drives the k-NN search.
4 questions test this
- You review the semantic retrieval query that an Azure Cosmos DB for NoSQL microservice issues on every user turn. The query projects VectorDistance as an aliased score and orders by the same expressio
- You prototype semantic retrieval on a new Azure Cosmos DB for NoSQL container that carries a vector embedding policy on the embedding path but no vector index, and that holds roughly 400 chunk documen
- You develop a Python service that runs semantic search over an Azure Cosmos DB for NoSQL container partitioned by libraryId. Each request must search a caller-supplied set of eight libraries, so a sin
- You develop a retrieval component for an Azure Cosmos DB for NoSQL container. Its query selects the top 10 chunk texts and projects VectorDistance against the caller's query embedding as an aliased sc
- The query vector is passed as a parameter and the projected score enables ranking and thresholding
You pass the query embedding as a query parameter (a numeric array) and project VectorDistance as an aliased score, letting the application rank matches and optionally drop results beyond a similarity threshold before sending context to the model.
5 questions test this
- You develop a Python service that queries an Azure Cosmos DB for NoSQL container for semantically similar chunks on every request. The current build formats the 1,536-element embedding returned by an
- You develop a retrieval service over an Azure Cosmos DB for NoSQL container whose vector embedding policy declares the euclidean distance function. The service projects VectorDistance as an aliased sc
- Your team is designing the response contract for a semantic retrieval API backed by an Azure Cosmos DB for NoSQL container that carries a vector embedding policy on the chunk embedding path. A reviewe
- You develop a Python service that runs semantic search over an Azure Cosmos DB for NoSQL container partitioned by libraryId. Each request must search a caller-supplied set of eight libraries, so a sin
- You develop a retrieval-augmented generation service over an Azure Cosmos DB for NoSQL container. For each question it retrieves the 10 nearest chunks and passes all of them to the model. On narrow qu
- Filtered vector search combines a WHERE metadata predicate with ORDER BY VectorDistance
To restrict semantic retrieval to a subset (for example one tenant or document category), add a WHERE clause on indexed metadata alongside ORDER BY VectorDistance. Cosmos applies the filter and returns the top-k nearest within that scope — the core metadata-filtered RAG pattern.
8 questions test this
- You are adding grounded retrieval to a clinical policy assistant that stores policy chunks and embeddings in Azure Cosmos DB for NoSQL. The retrieval query filters on the department and orders by Vect
- You maintain a document-retrieval API on Azure Cosmos DB for NoSQL. The container holds several million chunks partitioned by libraryId, and each request searches inside exactly one library. The retri
- You develop a multitenant contract-review assistant on Azure Cosmos DB for NoSQL. All tenants' clause chunks and embeddings live in one container. The service runs an unfiltered top-10 similarity sear
- You maintain an IT service-desk assistant on Azure Cosmos DB for NoSQL. Each item holds an article chunk and its embedding, and the container already has a full-text policy and index on the chunk text
- You design a per-project drawing-search container in Azure Cosmos DB for NoSQL. Chunks carry 1,536-dimension embeddings from Azure OpenAI, every query filters on projectId so a single search covers on
- Your team runs a product-support retrieval service on Azure Cosmos DB for NoSQL. Millions of article chunks span 40 product lines, and every query filters on one productLine value before ordering by V
- A knowledge-base assistant on Azure Cosmos DB for NoSQL stores each passage with two embeddings on separate vector paths: one built from the passage text and one from its parent document's summary. Hy
- An investigations assistant ranks case notes in Azure Cosmos DB for NoSQL with ORDER BY RANK RRF over FullTextScore and VectorDistance. Reviewers now want the ten returned notes presented newest first
- Returning source metadata (id, title, page) with each match is what enables grounded citations
Because embeddings live in the same document as their source fields, the vector query projects document id, title, and page next to the score. The application uses that returned metadata to ground the generated answer and attach an accurate citation to each retrieved chunk.
3 questions test this
- A travel-support assistant shows a match strength beside each citation, computed from the similarity value that its filtered vector query projects from Azure Cosmos DB for NoSQL. After the team rebuil
- An e-learning assistant answers with citations drawn from lesson chunks in Azure Cosmos DB for NoSQL, using a filtered vector query that projects only the lesson id, the lesson title, and the item's p
- An investigations assistant ranks case notes in Azure Cosmos DB for NoSQL with ORDER BY RANK RRF over FullTextScore and VectorDistance. Reviewers now want the ten returned notes presented newest first
- Cosmos supports hybrid search that fuses full-text and vector ranking with Reciprocal Rank Fusion
Beyond pure vector search, Cosmos DB for NoSQL offers full-text search (for example FullTextScore) and hybrid queries that blend keyword and vector relevance using Reciprocal Rank Fusion (RRF), improving recall when lexical and semantic matches differ.
Also tested in
References
- Integrated vector store in Azure Cosmos DB for NoSQL
- Index and query vector data in Python - Azure Cosmos DB for NoSQL
- Tips for optimizing vector indexing and search performance in Azure Cosmos DB for NoSQL
- Vector database - Cosmos DB (in Azure and Fabric)
- Understand embeddings in Azure OpenAI
- Vector distance functions in Azure Cosmos DB for NoSQL
- Indexing policies in Azure Cosmos DB
- VECTORDISTANCE - Azure Cosmos DB for NoSQL query language reference
- Use hybrid search in Azure Cosmos DB for NoSQL