Skip to content

AI-200 · Domain 2: Develop AI solutions by using Azure data management services · 33% of the exam

Task 2.1: Develop AI solutions by using Azure Cosmos DB for NoSQL

The Python SDK and queries, indexing policies, consistency levels and request units, storing embeddings and running vector search, and the change feed processor.

Study it

  • Cosmos DB for NoSQL with the Python SDK: containers, partition keys and queries

    Partly covered by: SQL vs NoSQL, Database Sharding

  • Request units, indexing policies and consistency levels

    Partly covered by: Consistency Models

  • Embeddings and vector search in Cosmos DB: vector policies, indexes and VectorDistance

    Partly covered by: Vector Databases, Approximate Neighbours

  • The change feed processor: leases, start time and estimating lag

    Lesson coming

Sample questions

Try each one before opening the answer. Every option is explained, with the Microsoft documentation page that proves it.

Question 1 · choose 1

A container in Azure Cosmos DB for NoSQL will hold about two million product embeddings of 1,536 dimensions each. Similarity queries search across the whole container, and the team wants the lowest latency and RU charge per query while keeping recall high. Which vector index type should the indexing policy use for the embedding path?

  1. Aflat
  2. BquantizedFlat
  3. CdiskANN
  4. DNo vector index, relying on VectorDistance over the stored vectors
Show the answer and why
  • Aflat

    Incorrect

    A flat index supports at most 505 dimensions, so it can't index 1,536-dimension vectors at all.

  • BquantizedFlat

    Incorrect

    quantizedFlat is still a brute-force search; Microsoft suggests it when the vectors in scope number 50,000 or fewer.

  • CdiskANN

    Correct

    DiskANN is generally the most performant index type when a search is scoped to more than 50,000 vectors, with high recall at low RU cost.

  • DNo vector index, relying on VectorDistance over the stored vectors

    Incorrect

    Without a vector index every search is a full scan, with much higher latency and RU charges.

flat (up to 505 dimensions) gives exact results, quantizedFlat compresses vectors but still scans them, and diskANN builds an approximate nearest neighbor index that suits large vector sets. The vector index must be on a path that the container's vector policy defines.

Question 2 · choose 1

You created a Cosmos DB for NoSQL container with a vector embedding policy for /contentVector and a quantizedFlat vector index. The indexing policy includes the root path /* and excludes only /_etag/?. Inserting documents costs noticeably more RUs and takes longer than expected. Which change to the indexing policy addresses this?

  1. ASet indexingMode to lazy
  2. BSet indexingMode to none
  3. CAdd /contentVector/* to excludedPaths
  4. DReplace the root path /* with /contentVector/? in includedPaths
Show the answer and why
  • ASet indexingMode to lazy

    Incorrect

    New containers can't select lazy indexing, and lazy indexing can return inconsistent or incomplete query results.

  • BSet indexingMode to none

    Incorrect

    None disables indexing for the container, so filtered queries would lose their indexes.

  • CAdd /contentVector/* to excludedPaths

    Correct

    Leaving the vector path under the regular range index makes every insert index each vector element; excluding it lowers insert RU charges and latency.

  • DReplace the root path /* with /contentVector/? in includedPaths

    Incorrect

    That would index only the vector path, the one path that shouldn't be in the range index, and drop every other property from it.

Vector properties are handled by the vector index, not by the range index on /*. Adding the vector path to excludedPaths keeps the range index from indexing every array element of every embedding.

Question 3 · choose 1

A retrieval step runs SELECT c.id, c.text, VectorDistance(c.embedding, @q) AS score FROM c ORDER BY VectorDistance(c.embedding, @q). The application keeps only the five best matches, yet each call consumes many RUs. What should you change in the query?

  1. APass true as the third argument of VectorDistance
  2. BReplace ORDER BY with a WHERE clause on the score alias
  3. CAdd ORDER BY c._ts DESC as a second sort key
  4. DAdd TOP 5 to the SELECT clause
Show the answer and why
  • APass true as the third argument of VectorDistance

    Incorrect

    True forces a brute-force calculation that ignores the vector index, which raises the cost.

  • BReplace ORDER BY with a WHERE clause on the score alias

    Incorrect

    Similarity search ranks results with ORDER BY VectorDistance; filtering on a computed score doesn't limit the scan.

  • CAdd ORDER BY c._ts DESC as a second sort key

    Incorrect

    A second sort key doesn't limit the result count and isn't part of a vector search.

  • DAdd TOP 5 to the SELECT clause

    Correct

    Microsoft advises always using TOP N in vector queries; without it the search tries to return many more results and costs more RUs.

VectorDistance returns a similarity score that the query orders by. Limiting the result with TOP N keeps the search from returning, and charging for, more matches than the application needs.

Question 4 · choose 1

A Cosmos DB account uses Strong as its default consistency. A chat app reads conversation history right after writing each turn and must always see its own latest writes, but it doesn't need every user to see every other user's writes at once. Reads are the largest share of the RU bill. Which default consistency level meets the requirement at the lowest read cost?

  1. ABounded staleness
  2. BEventual
  3. CSession
  4. DStrong, with autoscale throughput on the container
Show the answer and why
  • ABounded staleness

    Incorrect

    Bounded staleness reads still cost about twice as many RUs as reads at the weaker levels.

  • BEventual

    Incorrect

    Eventual is cheap but gives no read-your-writes guarantee, so a turn could be missing right after it was written.

  • CSession

    Correct

    Session guarantees read-your-writes within a client session and avoids the doubled read charge of the two strongest levels.

  • DStrong, with autoscale throughput on the container

    Incorrect

    Autoscale changes how throughput is provisioned, not the RU charge of each strong read.

Strong and bounded staleness reads cost roughly twice the RUs of the other levels. Session consistency uses a session token so a client always reads its own writes, which is what a single user's chat needs. Recreate SDK clients after changing the account default.

Question 5 · choose 2

A Python service must react to new and updated items in a Cosmos DB for NoSQL container, resume from where it stopped after a restart, and spread the work across several instances. Which two approaches work for a Python solution? (Choose TWO.)

  1. ABuild a change feed processor with the Python SDK's builder and a lease container
  2. BRead in all versions and deletes mode on an account that uses periodic backup
  3. CRead the change feed with the pull model, persisting continuation tokens and splitting the work by FeedRange
  4. DSet a time to live on the container so that changed items are pushed to the service
  5. EUse an Azure Functions Cosmos DB trigger with a lease container
Show the answer and why
  • ABuild a change feed processor with the Python SDK's builder and a lease container

    Incorrect

    The change feed processor library is available only in the .NET and Java SDKs.

  • BRead in all versions and deletes mode on an account that uses periodic backup

    Incorrect

    All versions and deletes mode requires continuous backup, and it isn't needed to see creates and updates.

  • CRead the change feed with the pull model, persisting continuation tokens and splitting the work by FeedRange

    Correct

    The pull model is the documented option for Python; continuation tokens bookmark progress and FeedRanges parallelize consumers.

  • DSet a time to live on the container so that changed items are pushed to the service

    Incorrect

    TTL deletes expired items; it doesn't deliver changes, and latest version mode doesn't show deletes at all.

  • EUse an Azure Functions Cosmos DB trigger with a lease container

    Correct

    The trigger runs on the change feed and keeps its progress in a lease container, and it supports Python functions.

Inserts and updates are captured in latest version mode. In .NET and Java the change feed processor manages leases for you; Python uses the pull model with manually persisted continuation tokens, or an Azure Functions trigger that handles leases.

Question 6 · choose 1

A Python service looks up a user profile by its id and partition key on every request by running SELECT * FROM c WHERE c.id = @id with the partition key set. Profiles are about 1 KB. How do you make each lookup as cheap as possible?

  1. AKeep the query and add a composite index on id and the partition key
  2. BKeep the query and run it with enable_cross_partition_query set to true
  3. CChange the account's default consistency to Strong
  4. DCall read_item with the item ID and partition key instead of running a query
Show the answer and why
  • AKeep the query and add a composite index on id and the partition key

    Incorrect

    Even with an index, a query that filters on id and partition key isn't treated as a point read.

  • BKeep the query and run it with enable_cross_partition_query set to true

    Incorrect

    Fanning out across partitions adds cost; the partition key is already known.

  • CChange the account's default consistency to Strong

    Incorrect

    Strong consistency roughly doubles the RU charge of every read.

  • DCall read_item with the item ID and partition key instead of running a query

    Correct

    A point read of a 1 KB item costs about 1 RU, the cheapest way to read in Cosmos DB.

Point reads, key/value lookups on an item's ID and partition key, are the most efficient reads, and their cost depends mainly on item size. In the API for NoSQL they're made through the SDK or REST API, not through a query.

Question 7 · choose 1

A query returns documents for one category sorted with ORDER BY c.category ASC, c.updatedAt DESC, and it fails until the indexing policy supports the sort. The policy currently has only the default range indexes. Which composite index do you add?

  1. A(updatedAt DESC, category ASC)
  2. B(category ASC, updatedAt ASC)
  3. CNo composite index; add an included range path for /updatedAt/?
  4. D(category ASC, updatedAt DESC)
Show the answer and why
  • A(updatedAt DESC, category ASC)

    Incorrect

    The path sequence must match the ORDER BY clause; reversing it leaves the query unsupported.

  • B(category ASC, updatedAt ASC)

    Incorrect

    A composite index supports the same directions, or the opposite direction on every path, but not a mix like this one.

  • CNo composite index; add an included range path for /updatedAt/?

    Incorrect

    ORDER BY on two or more properties always needs a composite index; range indexes alone don't serve it.

  • D(category ASC, updatedAt DESC)

    Correct

    The composite paths match the ORDER BY sequence and directions, so the index supports the query.

Composite indexes are required for ORDER BY on more than one property. The order of the paths and their directions must match the clause (or be the exact opposite on all paths). Adding the index triggers an online index transformation.

Question 8 · choose 1

A FastAPI service calls Cosmos DB from async endpoints with the synchronous azure.cosmos.CosmosClient. Under load, request latency spikes and the event loop stalls. What's the recommended fix?

  1. ACreate a new synchronous CosmosClient inside each request handler and close it after use
  2. BSwitch to azure.cosmos.aio.CosmosClient, created once and closed with async with
  3. CRaise the container's provisioned throughput
  4. DSet preferred_locations to the nearest region
Show the answer and why
  • ACreate a new synchronous CosmosClient inside each request handler and close it after use

    Incorrect

    The SDK should be one client instance reused for the app's life; new clients per request add overhead and still block.

  • BSwitch to azure.cosmos.aio.CosmosClient, created once and closed with async with

    Correct

    The async client is the one to use in async frameworks; the sync client blocks the event loop.

  • CRaise the container's provisioned throughput

    Incorrect

    More RU/s doesn't stop blocking I/O calls from stalling the event loop.

  • DSet preferred_locations to the nearest region

    Incorrect

    Preferred locations improve latency and failover, but the blocking calls remain.

Don't use the sync CosmosClient inside an async event loop. The async client lives in azure.cosmos.aio, needs aiohttp installed explicitly, and must be closed, preferably with async with.

Question 9 · choose 1

In a Cosmos DB container that stores chat sessions, only items marked as temporary drafts should be deleted automatically, 24 hours after their last change; every other item must stay until the app deletes it. How do you configure time to live?

  1. ALeave the container's TTL unset and give draft items a ttl of 86400
  2. BSet the container's default TTL to -1 and give draft items a ttl of 86400
  3. CSet the container's default TTL to 86400 and give other items a ttl of null
  4. DRun a nightly query that deletes drafts older than 24 hours
Show the answer and why
  • ALeave the container's TTL unset and give draft items a ttl of 86400

    Incorrect

    If the container has no TTL, an item's ttl property has no effect, so drafts would never expire.

  • BSet the container's default TTL to -1 and give draft items a ttl of 86400

    Correct

    With -1 on the container nothing expires by default, and items with their own ttl expire that many seconds after their last change.

  • CSet the container's default TTL to 86400 and give other items a ttl of null

    Incorrect

    Setting an item's ttl to null isn't supported; non-expiring items would need -1 instead.

  • DRun a nightly query that deletes drafts older than 24 hours

    Incorrect

    This works, but it spends RUs on a query and deletes that TTL performs for you as a background task.

DefaultTimeToLive on the container enables TTL: missing or null turns it off, -1 means items don't expire unless they set their own ttl, and n expires items n seconds after their last modification. Expired items disappear from queries at once and are purged in the background.

Question 10 · choose 1

When a user saves a conversation, your Python code must create a conversation item and update a summary item so that either both changes are saved or neither is. Which design lets you do this with a transactional batch in Cosmos DB for NoSQL?

  1. APut the items in different containers that share a database
  2. BGive the items different partition keys and set Strong consistency
  3. CStore both items under the same partition key value
  4. DWrite the items in parallel and retry whichever write fails
Show the answer and why
  • APut the items in different containers that share a database

    Incorrect

    A batch runs against one container and one partition key.

  • BGive the items different partition keys and set Strong consistency

    Incorrect

    Consistency levels govern reads; they don't make writes across partition keys atomic.

  • CStore both items under the same partition key value

    Correct

    A transactional batch groups point operations that share the same partition key and commits or rolls them back together.

  • DWrite the items in parallel and retry whichever write fails

    Incorrect

    Retrying doesn't make the two writes atomic; one can still succeed while the other fails.

Cosmos DB offers ACID transactions with snapshot isolation within one logical partition. Transactional batch, available in the SDKs, is the code-based way to use them; stored procedures are the JavaScript alternative.

Question 11 · choose 2

Cosmos DB metrics for a container show about 3 percent of requests ending in 429, and users report no latency problems. Another container shows 20 percent 429s while its overall RU usage looks low. Which two statements are correct? (Choose TWO.)

  1. AThe first container likely needs no action; 1 to 5 percent 429s with acceptable latency means its RU/s are fully used
  2. BThe application sees every 429 in the metrics as an error
  3. CDoubling the RU/s of the second container is the first step
  4. DOn an autoscale container, a 429 always means it has already reached its maximum RU/s
  5. EFor the second container, check Normalized RU Consumption by PartitionKeyRangeID for a hot partition
Show the answer and why
  • AThe first container likely needs no action; 1 to 5 percent 429s with acceptable latency means its RU/s are fully used

    Correct

    Microsoft treats this range as healthy when partitions are evenly distributed and latency is fine.

  • BThe application sees every 429 in the metrics as an error

    Incorrect

    The SDKs retry 429s automatically, typically up to nine times, so many never reach the application.

  • CDoubling the RU/s of the second container is the first step

    Incorrect

    Microsoft recommends finding the root cause, such as a hot partition, before changing RU/s.

  • DOn an autoscale container, a 429 always means it has already reached its maximum RU/s

    Incorrect

    Autoscale containers can return 429s even when they haven't scaled to the maximum RU/s.

  • EFor the second container, check Normalized RU Consumption by PartitionKeyRangeID for a hot partition

    Correct

    One physical partition at 100 percent while others are low points to a hot partition despite low overall usage.

A small share of 429s shows a workload using its provisioned throughput. A large share with low overall usage usually means a hot partition: one logical key range drawing most requests to one physical partition, which has only its share of the RU/s.

Question 12 · choose 1

In a test container with a diskANN vector index, you load 300 embeddings. Vector queries work but cost far more RUs than the team expected from the documentation. Why?

  1. AdiskANN indexes always cost more than full scans for the same query
  2. BBelow 1,000 indexed vectors, Cosmos DB runs a full scan instead of using the index
  3. CThe vector search feature takes 15 minutes to enable, and queries until then are full scans
  4. DThe container uses shared database throughput
Show the answer and why
  • AdiskANN indexes always cost more than full scans for the same query

    Incorrect

    The index type isn't the cause; with this few vectors the query doesn't use the index at all.

  • BBelow 1,000 indexed vectors, Cosmos DB runs a full scan instead of using the index

    Correct

    quantizedFlat and diskANN need at least 1,000 vectors for accurate quantization; with fewer, a full scan with higher RU charges runs.

  • CThe vector search feature takes 15 minutes to enable, and queries until then are full scans

    Incorrect

    A query can't use vector search before the feature is enabled at all; the cost here comes from the small vector count.

  • DThe container uses shared database throughput

    Incorrect

    Vector indexing isn't supported on shared-throughput accounts at all, so this container couldn't have a vector index.

Quantization-based indexes need enough data. With fewer than 1,000 vectors, the engine falls back to scanning, so test RU costs with a realistically sized data set.

Practise domain 2 →Practise all domains →