Study Guide · AI-200

AI-200 Cheat Sheet

354 entries · 27 chapters · 4 domains

Develop containerized solutions on Azure

Manage container images in Azure Container Registry

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Image digests are immutable, content-addressable identifiers

A manifest digest is a unique SHA-256 hash of the image's manifest, and every image or artifact, tagged or not, has its own, so referencing an image as repository@sha256:... always resolves to the exact same build even if a tag is later moved. Deploying by digest guarantees predictable, immutable image selection.

Trap Assuming a version-string tag is just as immutable as a digest.

9 questions test this
Tags are mutable pointers that can be reassigned

An ACR tag, including a version-looking tag such as v1.2, can be repushed to point at a different manifest at any time, so deploying by tag does not guarantee a reproducible build.

12 questions test this
The latest tag floats to the most recent push that carries it

The latest tag is simply the tag Docker and the registry assume when a command names none, so it moves only when a push actually carries it and not whenever any newer image is pushed. Because it is reused rather than unique it is a stable tag, and Microsoft's tagging guidance is to avoid deploying from stable tags because they keep receiving updates.

Trap Believing latest always points to the highest semantic version.

5 questions test this
Unique per-build tags enable traceable rollback

Best practice is to tag each build with a unique value such as a build ID or Git commit hash, so any deployed version is traceable and you can roll back to an exact, unchanged image.

7 questions test this
Stable tags roll forward for base-image patching

A stable tag such as major.minor is deliberately re-pointed to the newest patched build so images that consume it pick up OS and framework fixes; it trades reproducibility for automatic patching and is typically used on base images, not deployments.

Locking a tag or manifest prevents overwrite or delete

Running az acr repository update against one tag (--image myrepo:tag) or manifest digest (--image myrepo@sha256:...) sets that image's lock attributes: --write-enabled false makes it immutable so it can be neither overwritten nor deleted, while --delete-enabled false blocks only deletion and still allows the image to be updated. Locking a released production image protects it from accidental change.

Trap Assuming --delete-enabled false also stops the image from being overwritten.

6 questions test this
az acr import copies images server-side without Docker

az acr import pulls an image from another registry (Docker Hub, MCR, or another ACR) directly into the target registry, so it needs no local Docker daemon and no docker pull followed by docker push.

Trap Thinking the image has to be pulled locally and pushed again to land in the target registry.

10 questions test this
Import by digest to preserve an exact build

Importing with source repository@sha256:... rather than by tag copies a specific immutable manifest, guaranteeing the imported image is byte-identical to the intended source build.

Trap Assuming az acr import only works with publicly accessible source images.

5 questions test this
Deleting a tag leaves the manifest consuming storage

Removing or overwriting a tag does not delete the underlying manifest and layers; the resulting untagged (dangling) manifest keeps consuming registry storage until it is explicitly purged.

Trap Thinking that untagging an image reclaims its storage.

8 questions test this
acr purge and retention policies remove stale images

An acr purge command, usually run as a scheduled ACR Task, deletes tags that match a repository and tag regex (--filter) and are older than a duration (--ago), and by default it removes only the tag references, so --untagged is needed to delete the dangling manifests too. A Premium-tier retention policy is the filter-free alternative, automatically deleting every untagged manifest a set number of days after it becomes untagged.

Trap Expecting a plain acr purge to reclaim the manifests behind the tags it deleted.

9 questions test this
Soft delete allows recovery of deleted artifacts

When the soft-delete policy is enabled, deleted manifests and tags are retained for a configurable window and can be restored before they are permanently removed.

Build and run images with ACR Tasks

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

az acr build builds in the cloud and pushes automatically

az acr build submits the build context to a quick task that builds the image on ACR-managed compute and pushes it to the registry, so no local Docker engine is required to produce and store an image.

Trap Assuming az acr build needs Docker installed on the developer machine.

6 questions test this
az acr task run executes a defined task on demand

az acr task run triggers an already-created task immediately, independent of its automatic triggers, which is useful for validating a task definition before wiring up commit or base-image triggers.

az acr build takes a build context plus --file and --platform

The positional argument of az acr build is the build context, which may be a local folder (uploaded as a tarball, honoring .dockerignore), a remote Git URL such as https://github.com/org/repo.git#branch:folder, or the URL of a remote tarball; -f/--file names the Dockerfile relative to that context rather than requiring it at the context root. --platform Linux/arm64 targets an architecture other than the default Linux/amd64, and --no-push compiles the image for validation without publishing it to the repository.

Trap Assuming the Dockerfile must sit at the root of the supplied context and be named exactly Dockerfile.

7 questions test this
Base-image update trigger rebuilds on FROM dependency change

A base-image-update trigger tracks the image referenced in the Dockerfile FROM instruction and automatically rebuilds the dependent image whenever that base OS or runtime image is updated in the registry, enabling automated patching.

Trap Choosing a schedule trigger to react to base-image updates.

13 questions test this
Base-image tracking follows a stable tag, not a digest

Base-image update triggers depend on the FROM instruction referencing a stable tag; if the Dockerfile pins its base image by digest, that base can never change and the trigger will never fire.

Trap Pinning the base image by digest and still expecting the base-image update trigger to fire.

5 questions test this
Source-commit trigger fires from a Git webhook

Creating a task with a Git context registers a webhook on the linked GitHub or Azure Repos repository and rebuilds the image on each commit to the tracked branch, because --commit-trigger-enabled defaults to True. The pull-request trigger is a separate trigger on the same context and is disabled by default until you pass --pull-request-trigger-enabled true.

Trap Expecting a commit trigger to also react to base-image updates.

9 questions test this
Git-triggered tasks need a repository access token

Creating a source-triggered task requires a Git personal access token so ACR can set the webhook and read the source repository. The required GitHub scopes depend on visibility: repo:status plus public_repo for a public repository, and full repo control for a private one; on Azure DevOps the required scope is Code (Read).

The --context fragment pins which branch and folder a task watches

az acr task create --context https://github.com/org/repo.git#main:src binds the definition to exactly one branch (#main) and one subfolder (:src), so a push to any other branch is ignored even though the webhook exists. az acr task list-runs --registry --name then lists past executions with their TRIGGER column (Commit, Manual, Image Update, or Timer), which is how you confirm what actually started a given run.

Trap Expecting a task pinned to main to fire when a feature branch is pushed.

7 questions test this
Timer trigger runs a task on a cron schedule

A scheduled (timer) trigger runs the task on a fixed cron schedule regardless of source or base-image changes, which suits periodic rebuilds or a recurring purge job but cannot guarantee a rebuild at the moment a dependency changes.

Trap Using a schedule trigger when the requirement is to rebuild exactly when a base image changes.

8 questions test this
Multi-step tasks define build, push, and cmd steps in YAML

A multi-step task uses an acr-task.yaml file to run ordered build, push, and cmd steps (for example build the image, run tests, then push) within a single task execution.

8 questions test this

Deploy containers to Azure App Service

Read full chapter
  • App Service pulls from ACR with a managed identity and AcrPull
  • WEBSITES_PORT tells App Service which container port to route to
  • Continuous deployment redeploys on a new image push
  • App settings surface as container environment variables
  • Connection strings are injected with type prefixes
  • az webapp config appsettings set merges named keys and restarts the app
  • Key Vault references resolve secrets at runtime
  • Key Vault references require an identity with Get permission
  • A versionless reference picks up rotated secrets
  • Slot swap gives zero-downtime releases
  • Deployment-slot settings stay with the slot on swap

Unlock with Premium — includes all practice exams and the complete study guide.

Deploy applications to Azure Container Apps

Read full chapter
  • The environment is the shared secure boundary for apps
  • VNet integration is set at environment creation
  • Container Apps Jobs and their trigger types
  • Workload profiles choose the compute tier inside one environment
  • Template changes create a new revision
  • Single versus multiple revision mode controls active revisions
  • Revision suffixes label revisions for reference
  • Traffic weights split ingress across revisions
  • Revision labels give a stable test URL
  • Weights are set with az containerapp ingress traffic set and must total 100
  • Ingress exposes an app on a target port
  • Secrets are referenced by env vars via secretref
  • Pull from a private ACR with a Container Apps managed identity

Unlock with Premium — includes all practice exams and the complete study guide.

Event-driven scaling with KEDA

Read full chapter
  • minReplicas 0 plus an event scaler enables scale-to-zero
  • Only HTTP, TCP, and event rules can scale to zero
  • The azure-servicebus scaler scales on queue depth
  • Scaler auth uses managed identity or a secret
  • Topic-based scaling requires topicName plus subscriptionName
  • KEDA supports many event-source scalers
  • An HTTP scale rule scales on concurrent requests
  • Several rules on one app are OR-ed, never AND-ed
  • minReplicas and maxReplicas bound autoscaling
  • Scale-rule metadata sets the per-scaler threshold

Unlock with Premium — includes all practice exams and the complete study guide.

Deploy to AKS with manifest files

Read full chapter
  • az aks get-credentials wires kubectl to the cluster
  • kubectl context selects the active cluster
  • The --admin flag returns certificate-based cluster-admin access
  • kubectl apply reconciles declared desired state
  • A Deployment manages replicas via a pod template
  • RollingUpdate replaces pods gradually
  • Injecting config and secrets into AKS pods via manifests
  • CPU/memory requests and limits in an AKS pod spec
  • A LoadBalancer Service gets an Azure public IP
  • A Service routes by label selector
  • az aks update --attach-acr grants pull access
  • ImagePullBackOff signals a pull or auth failure

Unlock with Premium — includes all practice exams and the complete study guide.

Monitor and troubleshoot AKS and Container Apps

Read full chapter
  • kubectl describe surfaces pod events first
  • kubectl logs --previous reads a crashed container's output
  • CrashLoopBackOff means repeated container exits
  • Liveness probe failures restart the container
  • Readiness probe traffic-gating vs liveness restart
  • Diagnosing OOMKilled (137) and Pending/Unschedulable pods
  • Container Apps logs land in Log Analytics tables
  • az containerapp logs show streams live output
  • System logs carry platform events, console logs carry process output
  • Container Insights collects AKS metrics and logs
  • kubectl exec tests in-pod end-to-end connectivity
  • NetworkPolicy can silently block pod traffic

Unlock with Premium — includes all practice exams and the complete study guide.

Develop AI solutions by using Azure data management services

Connect to and query Azure Cosmos DB for NoSQL with the SDK

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

CosmosClient is the SDK entry point, built from the account endpoint plus a credential and reused for the app lifetime

The azure-cosmos CosmosClient is constructed from the account URI and a credential — either the account key/resource token or a Microsoft Entra token via DefaultAzureCredential. A single CosmosClient is thread-safe and should be created once and reused, because per-request clients waste connections and warm-up cost.

Trap Constructing a fresh CosmosClient per request instead of reusing one for the app's lifetime.

5 questions test this
Item operations with Microsoft Entra ID require a Cosmos DB data-plane RBAC role, not just a management role

Passing DefaultAzureCredential authenticates with Entra ID, but reading or writing items also requires a Cosmos DB data-plane role assignment (for example Cosmos DB Built-in Data Reader or Data Contributor) scoped to the account. Azure RBAC management roles such as Contributor grant control-plane access only and do not authorize data operations.

Trap Owner/Contributor on the account does not grant data-plane read/write; you must assign a Cosmos DB built-in data role.

4 questions test this
Cosmos SDKs connect in Gateway (HTTPS) or Direct (TCP) mode; the Python SDK uses Gateway mode

Gateway mode routes every request through the account's HTTPS gateway on port 443, which is firewall-friendly, while Direct mode opens TCP connections straight to backend replicas for lower latency and higher throughput. The .NET and Java SDKs support both modes; the Python and JavaScript SDKs operate in Gateway mode.

Trap Expecting to switch the Python SDK into Direct mode for lower latency.

3 questions test this
Enabling multi-region (multi-master) writes on CosmosClient

Multi-region writes are enabled at the ACCOUNT level, and the client must then opt in as well. Microsoft's Python instruction is to set multiple_write_locations=True in the client initialization AND set preferred_locations to the regions the data is replicated into, ordered by preference: CosmosClient(url, credential, multiple_write_locations=True, preferred_locations=['West US','East US']). enable_endpoint_discovery defaults to True, so the SDK routes to the first available region in that list and falls back across regions on a regional event. You order the list yourself, shortest distance or best latency first; it is .NET's ApplicationRegion that auto-populates preferred locations by geo-proximity, not the Python argument.

Trap Enabling multiple write regions rules out Strong consistency (a multi-write account supports at most Bounded Staleness), and the conflict-resolution policy reconciles concurrent writes but does NOT do the region routing.

3 questions test this
The SDK models the account → database → container hierarchy as client-side proxy objects

From a CosmosClient you obtain a DatabaseProxy via get_database_client(db_id) and a ContainerProxy via get_container_client(container_id); these proxies are lightweight client-side references to a named resource. Obtaining one does not confirm the resource is there: Microsoft describes a DatabaseProxy as an interface to a database that could, or couldn't, exist in the service yet, so a mistyped database or container name surfaces only when you call a real operation on the proxy.

Trap Treating a returned ContainerProxy as proof the container actually exists.

3 questions test this
Each container has a partition key path whose value routes point operations and scopes queries

A container is created with a partition key path (for example /customerId), and each item's value at that path determines its logical partition. The SDK uses the partition key to route point reads and writes to the owning partition and to confine a query to a single physical partition when supplied.

6 questions test this
The SDK raises typed exceptions such as CosmosResourceNotFoundError (404) and CosmosResourceExistsError (409)

Resource errors surface as typed exceptions — CosmosResourceNotFoundError for a missing item/container (HTTP 404) and CosmosResourceExistsError for a create conflict (HTTP 409) — so code branches on the exception type instead of parsing status codes. Convenience calls like create_container_if_not_exists absorb the 409.

Optimistic concurrency with _etag and If-Match

Cosmos DB items carry a system _etag that changes on every write; to prevent a lost update, read the item, then issue a conditional replace passing that etag (the if-match request header, expressed in the current Python SDK as the etag keyword argument plus match_condition=MatchConditions.IfNotModified on replace_item or upsert_item). If another writer changed the item first, the server rejects the replace with HTTP 412 Precondition Failed and the app re-reads and retries. This is single-region item-level concurrency control, separate from the multi-region conflict-resolution policy.

A point read (read_item by id and partition key) is the cheapest, lowest-latency single-item fetch

read_item(item=id, partition_key=pk) performs a point read that retrieves one item directly from its partition, typically costing about 1 RU for a 1-KB document. When you know both the id and the partition key, a point read is always preferable to a query.

Trap SELECT * FROM c WHERE c.id=@id runs the query engine and costs more RUs than an equivalent point read.

6 questions test this
query_items runs a SQL query through the query engine and returns a paged iterator

container.query_items(query=..., parameters=...) executes a SQL query and returns a paged iterable of matching items. Queries engage the indexing and query engine and are billed per RU based on the work performed, which exceeds a point read when fetching a single known item.

Trap Reaching for query_items to fetch one item whose id and partition key are already known.

8 questions test this
Passing partition_key confines a query to one partition; omitting it fans out cross-partition

Supplying partition_key=value to query_items scopes execution to a single logical partition, which is cheaper and faster. Without it (or with enable_cross_partition_query=True in older SDKs) the query fans out to every physical partition, raising RU cost and latency.

Trap Omitting partition_key and still expecting the query to touch a single partition.

2 questions test this
Parameterized SQL passes values via a parameters list, preventing SQL injection

You author queries with @-prefixed placeholders and pass a parameters list of {"name": "@id", "value": v} entries to query_items, with the leading @ included in the name. Parameterization avoids string concatenation and is what provides robust handling and escaping of user input, preventing accidental exposure of data through SQL injection. Query plans are cached on the CLIENT, not by the service, keyed on the SQL query string, which is why an unparameterized query misses that cache; Microsoft documents the cache as enabled by default for the Java SDK 4.20.0+ and Spring Data 3.13.0+, and the documented Python lever for skipping the query-plan call is passing partition_key instead.

Trap Believing the service caches query plans, so a concatenated SQL string costs no more than a parameterized one.

4 questions test this
Cross-partition queries execute per-partition and merge into pages; in Python only streamable ones resume by continuation token

The SDK runs a cross-partition query as parallel sub-queries per physical partition and merges results into pages; a continuation token resumes the next page after the client stops iterating. ORDER BY and aggregates across partitions require the SDK to gather and merge partial results, and in the Python SDK those are exactly the queries continuation tokens do NOT cover: cross-partition tokens are supported for streamable queries such as SELECT * FROM c WHERE ..., while aggregate cross-partition queries (sorting, counting, distinct) do not support continuation tokens. Separately, no SDK supports continuation tokens for GROUP BY, or for DISTINCT without an ORDER BY.

Trap Expecting a continuation token to resume a cross-partition ORDER BY or aggregate query in Python.

4 questions test this
max_item_count bounds page size and each page reports its cost in x-ms-request-charge

max_item_count on query_items is an upper bound on the items returned per page: the engine returns that number of items or fewer, never more. A page can therefore come back short, or even empty, when throttling, response size, execution time, or the engine's own efficiency choices split the results further, so correct code drains every page instead of trusting one round trip. The RU cost of each page is reported in the x-ms-request-charge response header (read in Python from container.client_connection.last_response_headers) so query cost can be measured and tuned.

3 questions test this
Cosmos SQL JOINs are intra-document self-joins that unwind arrays within a single item

A JOIN in Cosmos DB SQL unwinds arrays inside one document (intra-document), not rows across documents, and queries can project shaped results and call built-in functions such as STARTSWITH, ARRAY_CONTAINS, and VectorDistance.

Optimize Cosmos DB RUs with indexing policies and consistency levels

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Request Units (RUs) are the normalized currency billed for every read, write, and query

A Request Unit abstracts the CPU, memory, and IOPS of an operation, so all reads, writes, and queries are charged in RUs against the container or database throughput. A point read of a 1-KB item is about 1 RU; writes and queries cost more depending on item size, indexed paths, and query complexity.

4 questions test this
Read x-ms-request-charge to measure the exact RU cost of any operation

Every Cosmos response carries the RUs consumed in the x-ms-request-charge header, exposed through the SDK's response headers. Reading it is the authoritative way to profile and optimize a specific read, write, or query rather than estimating cost.

Trap Estimating an operation's RU cost from item size instead of reading x-ms-request-charge.

2 questions test this
Throughput is provisioned as manual RU/s, autoscale, or serverless, each with different scaling behavior

You allocate throughput at the database or container level as manual (fixed RU/s), autoscale (scales automatically between 10% and a configured maximum), or serverless (pay per consumed RU with no provisioning). Autoscale fits spiky or unpredictable traffic; serverless fits low, intermittent workloads.

3 questions test this
Time to Live (TTL) auto-expires items using background RUs; -1 enables TTL with no default expiry

A container's DefaultTimeToLive governs automatic expiry: a positive value is the default item lifetime in seconds, -1 enables TTL so only items carrying their own ttl expire, and null/absent disables it. Expired items disappear from queries immediately and are purged by a background task: on a provisioned throughput account that purge uses leftover RUs that user requests did not consume, while on a serverless account it is charged in RUs at the same rate as delete operations.

Cosmos DB integrated cache via dedicated gateway

The integrated cache serves repeated point reads and identical queries from an in-memory cache on a provisioned dedicated gateway at effectively 0 RU — the lever for cutting RU on read-heavy repeat traffic. It requires connecting through the dedicated-gateway endpoint (gateway connection mode) with session or eventual consistency, and a MaxIntegratedCacheStaleness window bounds how stale a cached response may be.

Exceeding provisioned throughput returns HTTP 429 with an x-ms-retry-after-ms hint

When consumption exceeds the provisioned RU/s, Cosmos rejects the request with HTTP 429 (Request rate too large) and includes an x-ms-retry-after-ms header stating how long to wait before retrying. Sustained 429s indicate under-provisioned throughput or a hot partition.

8 questions test this
The SDK automatically retries throttled requests up to a configurable maximum, honoring retry-after

By default the SDK transparently retries 429 responses, waiting the x-ms-retry-after-ms interval each time, up to a bounded number of attempts (nine by default, changed with the Python SDK's retry_total setting) and a maximum cumulative wait time (30 seconds by default, after which a CosmosHttpResponseError with status 429 reaches the application even if attempts remain). Raising these limits absorbs larger bursts at the cost of latency but does not add capacity.

Trap Increasing max retry attempts masks a hot partition or too-low RU/s; it does not provision more throughput.

5 questions test this
A hot logical partition can throttle even when total RU/s appears sufficient

Because throughput is divided across physical partitions, a partition key that concentrates traffic on one logical partition can trigger 429s while overall utilization looks low. The remedy is a higher-cardinality, evenly distributed partition key, not simply more RU/s.

Partition-key cardinality design rule

The design rule for even throughput is to pick a partition key with high cardinality whose access pattern spreads work uniformly — a per-user or per-device id distributes load, whereas a low-cardinality field (a status flag) or a monotonically increasing timestamp concentrates writes and creates a hot partition. Because provisioned throughput divides evenly across a container's physical partitions and every logical partition maps to exactly one of them, a skewed key throttles one physical partition even when total account RUs are ample.

Cosmos indexes every property automatically by default; you tune write cost by excluding paths

A container's indexing policy defaults to automatic, consistent indexing of all paths (/*). Write RU cost scales with the number of indexed paths, so excluding properties you never filter or sort on reduces write and storage cost without affecting the queries you actually run.

Trap Assuming properties you never filter or sort on are free because no query touches them.

7 questions test this
includedPaths and excludedPaths use JSON path expressions such as /category/? and /*

Indexing paths use JSON path syntax: /* matches everything recursively, /category/? indexes the scalar at that path, and /metadata/* indexes a subtree. The most specific matching rule wins, so you can include /* while excluding a large subtree like /rawText/*.

Trap Assuming a broad /* include outranks a more specific excludedPaths entry.

5 questions test this
indexingMode consistent keeps the index in sync with writes; none disables indexing entirely

indexingMode consistent (the default) updates the index synchronously as you create, update, or delete items, so read queries see the consistency configured for the account rather than a lagging index; none removes the index — suitable for a pure key/value point-read store where any query would otherwise scan. A third mode, lazy, can return inconsistent or incomplete query results and can no longer be selected for new containers.

Trap Setting indexingMode to none on a container that still has to answer queries.

2 questions test this
Excluding a vector or large-text path from the standard index avoids paying to index data you search specially

Large properties such as embedding arrays or raw document text add write RU and storage when covered by the default index. Adding their path to excludedPaths while defining a dedicated vector index keeps writes cheap without losing the specialized search path.

A composite index is required to ORDER BY two or more properties

A single-property range index handles ORDER BY on one field, but ordering by multiple properties (for example ORDER BY c.lastName ASC, c.firstName ASC) requires a compositeIndexes entry listing those paths with their sort orders, or the query fails.

Trap Expecting two single-property range indexes to satisfy an ORDER BY over both.

6 questions test this
Composite index property order and direction must match the query, including its exact reverse

A composite index defined as (name ASC, age ASC) serves ORDER BY name ASC, age ASC and its exact reverse (name DESC, age DESC), but not (name ASC, age DESC). Define the composite index to mirror the query's property sequence and directions.

Trap Assuming one composite index serves every combination of sort directions on its properties.

6 questions test this
Composite indexes can also lower RU for queries that filter on one property and sort or range on another

Beyond multi-property ORDER BY, a composite index can reduce the RU charge of queries that filter on one property and range-filter or sort on another, because the engine resolves them from the composite index instead of a broader index scan.

Cosmos offers five consistency levels from Strong to Eventual, with Session as the default

The five levels — Strong, Bounded Staleness, Session, Consistent Prefix, and Eventual — trade read consistency against latency, availability, and RU cost. Session, the default, guarantees read-your-own-writes and monotonic reads within a client session and satisfies most applications.

6 questions test this
Strong and Bounded Staleness reads consume roughly double the RUs of weaker levels

Strong guarantees a linearizable, always-latest read but adds latency and is unavailable with multi-region writes; Bounded Staleness bounds lag by versions or time. Reads at Strong or Bounded Staleness cost about twice the RUs of Session, Consistent Prefix, or Eventual reads.

Trap Strong consistency is not compatible with multi-region (multi-master) write accounts.

5 questions test this
Session consistency is carried by a session token emitted on the write response

Under Session consistency each write response returns a session token; to preserve read-your-own-writes across processes or nodes you capture that token and supply it on later requests' options. The token is produced by the operation response, not configured on the client.

Trap Hunting for the session token as a client setting instead of on the write response.

2 questions test this
A request can relax to a weaker consistency than the account default; the ConsistencyLevel override cannot strengthen it

The account's default consistency applies to all requests, but an individual read may request a weaker level than the default (for example Eventual on a Strong account) to save RUs and latency. With the per-request ConsistencyLevel option that override can only relax consistency; moving to a level stronger than the account default means changing the account's own default.

Conflict-resolution policy for multi-region write accounts

When a multi-region write account takes concurrent writes to the same item in different regions, the container's conflict-resolution policy reconciles them: Last-Writer-Wins (the default, on a numeric/timestamp conflict path such as _ts) or a Custom policy backed by a merge stored procedure. The policy decides WHICH version wins; it does not route writes to the nearest region (that is the preferred-regions list).

Store embeddings and run vector similarity search in Cosmos DB

Read full chapter

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
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
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
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
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
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
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
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

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
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
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.

Implement a Cosmos DB change feed processor

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

The change feed is a persistent, per-partition ordered record of creates and updates

The change feed exposes items in the order they were modified within each logical partition, so downstream consumers can react to new or changed data. In its default mode it shows only the latest version of each changed item and does not surface deletes.

Trap Expecting the default change feed to replay every intermediate version of an item.

8 questions test this
Latest-version mode omits deletes; all-versions-and-deletes mode captures inserts, updates, and deletes

Latest-version (formerly incremental) mode returns the most recent state of changed items and no deletes. All-versions-and-deletes (full-fidelity) mode also emits deletes and intermediate versions, but it requires continuous backup / retention to be enabled on the account.

Trap Switching to all-versions-and-deletes mode on an account with no continuous backup enabled.

9 questions test this
A soft-delete-plus-TTL pattern lets latest-version consumers observe logical deletions

Because the default change feed does not emit hard deletes, a common pattern marks an item deleted with a flag (optionally with a TTL) so latest-version consumers see the update as a change. Use all-versions-and-deletes mode when true delete events must be captured.

The change feed processor has four components: monitored container, lease container, compute host, and delegate

The processor reads from the monitored (source) container, records progress in a separate lease container, runs on one or more compute instances (hosts), and invokes your delegate/handler with each batch of changes. All four pieces are required to build a processor.

Trap Expecting the processor to checkpoint into the monitored container without a separate lease container.

8 questions test this
The lease container stores per-partition leases and checkpoints so work is distributed and resumable

Each physical partition range gets a lease document in the lease container recording its continuation (checkpoint). Multiple host instances sharing the same lease container automatically balance partition ranges among themselves and resume from the last checkpoint after a restart.

11 questions test this
Instances share work only when they share a lease container AND a processor name, and leases cap the count

Instances cooperate only as one deployment unit, which takes three things at once: the same lease container configuration, the same processor name, and a different instance name for each. Meet all three and the processor distributes every lease across the running instances using an equal-distribution algorithm and rebalances as instances come and go. A lease is owned by one instance at any time, so the number of instances shouldn't be greater than the number of leases, and a differing processor name builds a second deployment unit that reads the whole feed again instead of sharing the work.

Trap Expecting instances with different processor names to share the work rather than each read the whole feed.

5 questions test this
A partitioned lease container is required to have an /id partition key, and it consumes its own RUs

The lease container is a separate container that acts as state storage and coordinates processing across workers; it can sit in the same account as the monitored container or in another account, and partitioned lease containers are required to have a /id partition key definition. It consumes its own request units for lease reads, writes and checkpoints, and throttling it delays change feed events or can end processing altogether. You normally provision it yourself, but the Azure Functions trigger can create it for you when CreateLeaseContainerIfNotExists is set to true (the default is false).

Checkpointing after a batch succeeds yields at-least-once delivery, so handlers must be idempotent

The processor advances the lease continuation (checkpoints) only after your delegate finishes a batch, so semantics are at-least-once: a host crash mid-batch causes the next owner to reprocess from the last checkpoint. Delegates must therefore be idempotent.

Trap Change feed processing is at-least-once, not exactly-once; make the handler idempotent to tolerate re-delivery.

5 questions test this
The start setting controls where a new lease begins; an existing checkpoint always takes precedence

When a lease is first created you can start reading from now (default — only future changes), from the container's beginning, or from a specific start time. Once a checkpoint exists the processor resumes from it and ignores the start setting.

Trap Setting start-from-beginning to re-read the feed when a lease checkpoint already exists.

5 questions test this
Changes are delivered in modification order within a partition key, batched by page, not ordered across ranges

Within a single logical partition the change feed preserves modification order, and the processor hands the delegate batches bounded by a max-items-per-page setting. Ordering is not guaranteed across different partition key ranges.

Trap Assuming the change feed delivers changes in one global order across every partition.

4 questions test this
The change feed estimator reports processing lag so you can scale consumers

The change feed estimator compares each lease's checkpoint against the latest change to report the remaining backlog (estimated pending items). A growing estimate signals that consumers are falling behind and that more processor instances or throughput are needed.

4 questions test this
The push (processor) model auto-manages leases; the pull model queries the change feed manually

The change feed processor is the push model: it polls, distributes leases, and invokes your delegate automatically. The pull model (query_items_change_feed with a continuation) gives manual control over which partition range and how much to read, but you must manage checkpoints yourself.

Trap Assuming the pull model manages leases and checkpoints the way the processor does.

5 questions test this
The Azure Functions Cosmos DB trigger is a hosted change feed processor

The Azure Functions Cosmos DB trigger wraps the change feed processor: you supply the monitored container and a lease container, and the platform runs the processor and scales instances for you, making a Function the serverless way to consume the change feed.

Implement Azure Managed Redis caching, expiration, and invalidation

Read full chapter
  • The redis-py client connects to Azure Managed Redis over TLS, then issues SET and GET
  • SET can atomically apply an expiry and conditional flags (EX/PX, NX/XX) in one round trip
  • MSET/MGET and pipelining batch multiple operations to cut round trips
  • EXPIRE sets a key's time-to-live in seconds; Redis deletes the key automatically when it lapses
  • TTL returns the remaining life: a positive value, -1 for no expiry, and -2 if the key does not exist
  • PERSIST removes a key's expiry, and a plain SET on an existing key clears its TTL
  • Redis mixes lazy and active expiration, so an expired key is never served
  • Cache-aside checks Redis first and loads from the backing store only on a miss
  • A TTL on each cached entry bounds staleness and lets the cache self-heal after source changes
  • Cache-aside risks a stampede when a hot key expires; mitigate with a lock or early refresh
  • Invalidate a cached item on write by deleting or updating its key (DEL/UNLINK)
  • maxmemory-policy selects which keys are evicted when the cache reaches its memory limit
  • noeviction returns errors on writes once memory is full instead of dropping keys
  • Keyspace notifications can publish key-change and expiry events to drive external invalidation

Unlock with Premium — includes all practice exams and the complete study guide.

Connect and query Azure Database for PostgreSQL with SDKs

Read full chapter
  • Flexible server requires TLS; sslmode decides how much the client verifies
  • psycopg2 and psycopg (v3) are the mainline drivers; v3 adds native async and pooling
  • On flexible server the login is the plain role name, not user@servername
  • Entra authentication passes an access token as the connection password
  • Entra tokens are short-lived, so the app must fetch a fresh token for new connections
  • An Entra admin and mapped database roles must exist before token auth works
  • Pass parameters with %s placeholders so the driver binds values and blocks SQL injection
  • Read rows with fetchone/fetchmany/fetchall and batch writes with executemany
  • A named (server-side) cursor streams a large result set in batches
  • asyncpg is a high-performance async driver that uses numbered $1 placeholders
  • SQLAlchemy selects the driver through the dialect in its connection URL

Unlock with Premium — includes all practice exams and the complete study guide.

Model PostgreSQL schemas, data types, and indexes

Read full chapter
  • Prefer jsonb over json for stored, queryable documents
  • timestamptz stores a timezone-aware instant normalized to UTC
  • Use uuid for distributed keys and numeric for exact decimals, not float
  • A surrogate key can be a sequence-backed IDENTITY column or a uuid, with different locality
  • PRIMARY KEY and UNIQUE constraints automatically create a supporting B-tree index
  • Normalize to remove redundancy, denormalizing hot retrieval metadata selectively
  • B-tree is the default index for equality, range, and ORDER BY on scalar columns
  • GIN indexes jsonb, arrays, and full-text tsvector for containment and membership
  • GiST is the extensible framework for ranges, geometry, and nearest-neighbor access
  • A composite index is most efficient when the query constrains its leading columns
  • Partial indexes shrink the index; covering (INCLUDE) indexes enable index-only scans
  • Every index must be maintained on writes, so index only for real query patterns

Unlock with Premium — includes all practice exams and the complete study guide.

Optimize query latency and reduce pgvector compute

Read full chapter
  • HNSW gives high recall and stable low latency but is slower to build and memory-heavy
  • IVFFlat builds fast and is memory-light but must be built on representative data
  • Both indexes are approximate; without one, a similarity query does an exact sequential scan
  • pg_diskann as an Azure-specific ANN index
  • HNSW build parameters m and ef_construction cost build time and memory, and only a rebuild changes them
  • hnsw.ef_search is a runtime setting that trades recall against latency without a rebuild
  • IVFFlat lists is set at build; ivfflat.probes is tuned per query
  • On Azure Database for PostgreSQL flexible server a server parameter is read-only, dynamic, or static, and a static one needs a restart
  • Indexing embeddings as halfvec roughly halves the bytes per vector without changing the stored column
  • Binary quantization cuts memory furthest and is normally paired with a re-rank
  • HNSW and IVFFlat index at most 2000 dimensions for vector; a different representation raises the ceiling
  • EXPLAIN ANALYZE reveals whether the query uses the ANN index or falls back to a Seq Scan
  • An ANN index accelerates ORDER BY distance ... LIMIT k, not a bare distance predicate
  • Iterative index scans keep scanning the ANN index until enough filtered rows are found, up to a documented bound

Unlock with Premium — includes all practice exams and the complete study guide.

Configure compute, memory, and storage for vector workloads

Read full chapter
  • Burstable, General Purpose, and Memory Optimized tiers differ in RAM-per-vCore
  • Size RAM to the working set: the ANN index plus the rows queries touch
  • maintenance_work_mem governs index-build memory and avoids spilling to disk
  • shared_buffers caches index and data pages that keep vector queries fast
  • work_mem sizes per-operation sorts; effective_cache_size hints the planner
  • IOPS scale with disk size, and the compute SKU caps what you can use
  • The index shares the table's disk, and writes stop at 95 percent used
  • pgvector must be added to the azure.extensions server parameter before CREATE EXTENSION
  • Raising max_parallel_maintenance_workers parallelizes and shortens HNSW builds

Unlock with Premium — includes all practice exams and the complete study guide.

Run vector similarity search and RAG on PostgreSQL

Read full chapter
  • CREATE EXTENSION vector adds the vector type; the column dimension must match the model
  • Insert embeddings by binding the vector as a parameter
  • Stored and query embeddings must come from the same model to be comparable
  • Generate embeddings in-database via the azure_ai extension
  • pgvector exposes <-> (L2), <=> (cosine), and <#> (negative inner product) operators
  • Semantic retrieval is ORDER BY embedding <=> $query LIMIT k returning payload columns
  • The index opclass must match the query's distance operator
  • Add a WHERE predicate on metadata columns to restrict semantic retrieval
  • A very selective filter can under-return from an ANN index, so raise search effort
  • The RAG pattern retrieves the top-k nearest chunks with their citation metadata to ground the LLM
  • Hybrid search fuses PostgreSQL full-text with vector similarity for better recall
  • Retrieved candidates can be re-ranked before grounding to sharpen the top-k

Unlock with Premium — includes all practice exams and the complete study guide.

Optimize PostgreSQL connections for throughput and latency

Read full chapter
  • Flexible server has built-in PgBouncer enabled by a server parameter and reached on port 6432
  • A pooler reuses a small set of server connections and absorbs connection storms
  • Transaction pooling returns the connection after each transaction; session pooling holds it for the session
  • Transaction pooling breaks session-scoped features like SET, advisory locks, and LISTEN/NOTIFY
  • Each connection is a backend process, so max_connections is bounded by SKU memory
  • An in-process connection pool reuses warm connections rather than one per request
  • Co-locate the app and the flexible server in the same region to cut round-trip latency
  • Batch writes and bulk loads to collapse many round-trips into few
  • TCP keepalives prevent idle pooled connections from being silently dropped

Unlock with Premium — includes all practice exams and the complete study guide.

Connect to and consume Azure services

Queue and process back-end operations with Azure Service Bus

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

A Service Bus queue delivers each message to exactly one competing consumer (point-to-point)

A Service Bus queue is a point-to-point channel: many consumers can compete for messages, but each message is delivered to and processed by only one receiver. Choose a queue (not a topic) when a back-end operation must be handled exactly once by a single worker.

Trap A topic with multiple subscriptions is fan-out — each subscription gets its own copy — so it violates single-consumer delivery.

5 questions test this
A topic with subscriptions is publish/subscribe fan-out — each subscription receives its own copy

A Service Bus topic delivers a published message to every matching subscription, and each subscription is itself an independent queue read by its own consumer(s). Use topics + subscriptions when several independent consumers must each process the same event.

13 questions test this
Subscription rules (SQL and correlation filters) select which topic messages a subscription receives

Each subscription can carry rules that filter the topic stream: a correlation filter matches system/application properties (fast, exact match), while a SQL filter evaluates a SQL-like expression over message properties. A subscription with no filter receives every message via the default TrueFilter.

Trap Assuming a subscription with no rule receives nothing until a filter is added.

7 questions test this
PeekLock is a two-stage receive: the message is locked, then explicitly Completed after processing succeeds

In PeekLock mode the broker hands the message to one receiver and locks it for the lock duration; the receiver must call complete after successful work to remove it. This makes processing at-least-once and safe: a crash before Complete releases the lock so the message is redelivered.

Trap Treating a PeekLock receive as having already removed the message from the queue.

14 questions test this
ReceiveAndDelete settles the message at delivery, so a mid-processing failure loses it

ReceiveAndDelete removes the message from the queue the instant it is delivered, before processing begins. It is faster and simpler but offers no retry: if the consumer crashes mid-work the message is gone. Use it only for high-throughput, loss-tolerant data.

Trap Reliable single-consumer processing needs PeekLock + Complete, never ReceiveAndDelete.

7 questions test this
A locked message can be Completed, Abandoned, Dead-lettered, or Deferred

Beyond complete, the SDK exposes abandon (release the lock for immediate redelivery, incrementing the delivery count), dead_letter (move to the DLQ with a reason), and defer (set aside for later retrieval by sequence number). Each is an explicit settlement action only valid on a PeekLock message.

Trap Calling abandon or dead_letter on a message received in ReceiveAndDelete mode.

12 questions test this
Locks expire after the lock duration unless renewed; the max delivery count governs redelivery

A PeekLock lock is held only for the entity's lock duration; long-running work must renew the lock (for example with an auto lock renewer) or the message unlocks and is redelivered. Repeated redeliveries eventually exceed the max delivery count.

The dead-letter queue is a secondary sub-queue of its parent entity, not an entity you provision

Dead-lettered messages land in a dead-letter queue (DLQ), a secondary sub-queue belonging to the queue or topic subscription itself rather than a separate entity. It can't be deleted or managed independently of the main entity, messages can only be submitted to it via the dead-letter operation of the parent, time-to-live isn't observed there, and there's no automatic cleanup: messages stay until you receive and complete them. What you configure is the entity's dead-lettering settings, never the sub-queue itself.

Trap Expecting dead-lettered messages to age out of the DLQ on their own.

12 questions test this
Messages dead-letter when the max delivery count is exceeded, TTL expires, or the app calls dead_letter

Service Bus moves a message to the DLQ automatically when it exceeds the max delivery count (repeated abandon/lock loss) or when its time-to-live expires with dead-lettering on expiration enabled. The application can also dead-letter a message explicitly (for example, a poison/unparseable payload).

Trap Expecting an expired message to reach the DLQ with dead-lettering on expiration switched off.

10 questions test this
Read the DLQ by opening a receiver on the entity's /$deadletterqueue sub-path

To inspect or reprocess dead-lettered messages you open a receiver against the sub-queue formatted as /$DeadLetterQueue (or /subscriptions//$DeadLetterQueue). In the Python SDK this is done via the sub_queue=ServiceBusSubQueue.DEAD_LETTER option when creating the receiver.

8 questions test this
Dead-lettered messages carry DeadLetterReason and DeadLetterErrorDescription properties

When a message is dead-lettered the broker (or app) records DeadLetterReason and DeadLetterErrorDescription in the message's application properties, letting an operator triage why delivery failed before reprocessing.

Sessions provide guaranteed FIFO ordering for all messages sharing a session id

Enabling sessions on a queue/subscription groups messages by SessionId and locks an entire session to one receiver, guaranteeing first-in-first-out processing within that session. This is how you achieve ordered, related-message processing that a plain competing-consumer queue cannot.

Trap A session must be enabled at entity creation; you cannot get per-key ordering from a non-session queue just by setting SessionId.

10 questions test this
A session receiver accepts a specific or the next available session and holds a session lock

To read a session-enabled entity you create a session receiver, which locks one session and delivers its messages in order. In Python there is no separate accept call: the session is chosen through the same receiver factory, either get_queue_receiver(queue_name=..., session_id="") for a named session or session_id=NEXT_AVAILABLE_SESSION to take whichever session is free. Session state can be persisted on the broker through the receiver's session object to checkpoint per-session progress.

Trap Hunting for a separate accept-session call in the Python SDK.

10 questions test this
Message time-to-live expires undelivered messages, optionally routing them to the DLQ

Each message has a time-to-live (defaulting to the entity's default TTL, capped by it); once it expires the message is removed, and if dead-lettering on message expiration is enabled it is moved to the DLQ instead of being silently dropped.

Trap Setting a per-message TTL longer than the entity's default and expecting it to hold.

6 questions test this
ServiceBusClient is the connection factory that creates senders and receivers

A single ServiceBusClient (built from a namespace + DefaultAzureCredential or a connection string) is the entry point; you call get_queue_sender / get_queue_receiver (or the topic/subscription variants) to obtain a ServiceBusSender for publishing and a ServiceBusReceiver for consuming. Messages are ServiceBusMessage objects.

8 questions test this
The processor model registers message/error handler callbacks and can auto-complete on success

The event-driven ServiceBusProcessor (.NET) registers a message handler and an error handler and continuously pumps messages, auto-completing them on success unless auto-complete is disabled; the Python SDK achieves the same by iterating a ServiceBusReceiver and settling each message explicitly.

Trap Expecting the Python receiver to auto-complete messages the way the .NET processor does.

6 questions test this
Duplicate detection discards messages with a repeated MessageId within a configured time window

When duplicate detection is enabled on a queue/topic, the broker ignores any incoming message whose MessageId matches one seen within the configured detection history window (default 10 minutes, minimum 20 seconds, maximum 7 days). A suppressed send still reports success to the sender, and no part of the message other than the MessageId is considered, so the sender must set a stable, reconstructible MessageId for this to work.

Trap Expecting a send suppressed by duplicate detection to surface as an error.

6 questions test this
Messages can be scheduled for future enqueue via a scheduled enqueue time

A sender can schedule a message to become available at a future instant by setting its scheduled enqueue time (or calling schedule_messages), which returns a sequence number that can be used to cancel the scheduled delivery before it fires.

Implement event-driven workflows with Azure Event Grid

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Applications publish custom events to a custom topic's endpoint URI, authenticated by access key or identity

A custom (application) topic exposes an HTTPS endpoint to which your app POSTs events; the publisher authenticates with the topic's access key (or SAS token, or a managed identity with the EventGrid Data Sender role). This is how first-party app events enter Event Grid.

14 questions test this
An Event Grid schema event requires id, subject, eventType, eventTime, and data; dataVersion, topic, and metadataVersion are optional

A custom event in the native Event Grid schema must supply id, subject, eventType, eventTime, and data (the payload). dataVersion is optional and is stamped with an empty value when omitted, while topic and metadataVersion are stamped by Event Grid. The subject and eventType are the fields most subscriptions filter on, so publishers set them deliberately to enable routing.

Trap Treating topic as a field the publisher has to populate on a custom event.

8 questions test this
Event Grid supports the CNCF CloudEvents 1.0 JSON schema in addition to its native schema

A topic can be configured to use the CloudEvents 1.0 schema (fields include specversion, type, source, id, time, subject, and data) for interoperability with other CloudEvents systems. The schema is set with two separate knobs, not one: the input schema is fixed when the topic is created (--input-schema), while the output (delivery) schema is chosen per event subscription (--event-delivery-schema). Event Grid input can be delivered as CloudEvents, but CloudEvents input cannot be delivered in the Event Grid schema, because CloudEvents extension attributes have no place in it.

Trap Assuming a single schema setting on the topic governs both input and delivery.

6 questions test this
Subject filtering routes events with subjectBeginsWith and subjectEndsWith prefix/suffix matches

An event subscription can filter on the event's subject using subjectBeginsWith (for example a folder path prefix) and subjectEndsWith (for example a file extension), plus a case-sensitivity flag. This is the lightweight first-line filter for narrowing which events a handler receives.

11 questions test this
Advanced filters test individual event fields with operators such as StringContains and NumberGreaterThan

Advanced filters evaluate a specific key inside the event (including data payload fields) with operators like StringIn, StringContains, NumberGreaterThan, and BoolEquals, allowing precise content-based routing beyond subject prefixes. Multiple advanced filters combine with AND semantics.

Trap Expecting multiple advanced filters to match when only one of them is satisfied.

19 questions test this
includedEventTypes limits a subscription to specific event types

A subscription can restrict delivery to a named list of event types via includedEventTypes; omitting it delivers all event types published to the topic. This is the coarsest, most common filter for custom-event workflows.

Event Grid retries failed deliveries with exponential back-off, bounded by max attempts and event TTL

If a handler does not return success, Event Grid retries with an exponential back-off schedule until either the configured maximum delivery attempts or the event time-to-live is reached. Tuning these two retry-policy values controls how long a transient handler outage is tolerated.

Trap Raising max delivery attempts when the event time-to-live is what expires first.

14 questions test this
Undelivered events dead-letter to an Azure Storage blob container, which must exist first

When retries are exhausted, Event Grid writes the event to a dead-letter destination that is an Azure Storage blob container; the storage account and container must already exist before the subscription is created, and Event Grid names each blob after the subscription in upper case. Enabling a system- or user-assigned managed identity for dead-lettering is OPTIONAL, and only when one is enabled must that identity hold an RBAC role permitting writes to the storage. Storage queues are not a valid Event Grid dead-letter target.

Trap Expecting Event Grid to create the dead-letter storage container for you.

15 questions test this
Some handler responses are non-retriable and dead-letter immediately

Certain HTTP responses from a webhook handler (for example 400 Bad Request or 413 Payload Too Large) are treated as non-retriable, so Event Grid stops retrying and, if dead-lettering is configured on the subscription, dead-letters the event right away; dead-lettering is off by default, and with no dead-letter destination configured the event is dropped instead. 5xx responses and timeouts are retried under the back-off policy.

A custom webhook endpoint must complete the subscription validation handshake before it receives events

When you create a subscription to a webhook that Azure does not validate automatically (which includes an HTTP-triggered Azure Function, not only endpoints outside Azure), Event Grid sends a SubscriptionValidationEvent containing a validationCode; the endpoint must echo that code back in a validationResponse (synchronous) or use the manual validationUrl handshake, proving ownership before delivery begins.

Trap Assuming an HTTP-triggered Azure Function is validated automatically because it lives in Azure.

14 questions test this
Event Grid delivers to first-party handlers (Functions, Logic Apps, Service Bus, Storage Queues) and generic webhooks

A subscription's endpoint can be an Azure Function, Logic App, Service Bus queue/topic, Storage Queue, Event Hub, or an arbitrary HTTPS webhook. Azure-native handlers (like Functions with the Event Grid trigger) auto-complete the validation handshake, unlike a raw webhook.

13 questions test this
CloudEvents-schema webhooks validate via the HTTP OPTIONS abuse-protection handshake instead of the validation event

When a subscription uses the CloudEvents 1.0 schema, endpoint validation follows the CloudEvents abuse-protection flow — an HTTP OPTIONS request carrying WebHook-Request-Origin that the endpoint answers with WebHook-Allowed-Origin — rather than echoing a validationCode.

Build serverless APIs with Azure Functions triggers and bindings

Read full chapter
  • The HTTP trigger's authLevel (anonymous, function, admin) controls key requirements for a serverless API
  • HTTP triggers define a route template and allowed HTTP methods for the request
  • A function has exactly one trigger but may declare many input and output bindings
  • The Timer trigger runs on a fixed NCRONTAB schedule
  • Blob triggers can poll or use an Event Grid source; the Event Grid source is the low-latency option
  • The Service Bus and Event Grid triggers bind a function directly to a queue/subscription or event stream
  • The Cosmos DB trigger consumes the change feed and requires a lease container
  • Storage Queue trigger poison-message handling
  • Input bindings read data into the function; output bindings write data out — declaratively, no client SDK code
  • Bindings are declared with decorators (Python v2 model) or function.json, referencing a connection app setting
  • An output binding can be fed by the function's return value
  • Binding expressions inject trigger metadata ({queueTrigger}, {name}) and app settings (%setting%)
  • A Cosmos DB input binding fetches items by id/partition key or a SQL query
  • A blob binding path uses a container/{name} pattern to bind the specific blob

Unlock with Premium — includes all practice exams and the complete study guide.

Configure and deploy Azure function apps

Read full chapter
  • The Consumption plan scales to zero and bills per execution, at the cost of cold starts
  • The Premium plan pairs always ready instances with a prewarmed buffer, and adds VNet integration
  • Dedicated (App Service) and Flex Consumption plans trade off predictable capacity vs fast elastic scale
  • The Always On setting exists only on Dedicated plans, not Consumption
  • WEBSITE_RUN_FROM_PACKAGE runs the app from a read-only mounted package, on the plans that allow it
  • func azure functionapp publish deploys the app, using a remote build for Python on Linux
  • Deployment slots let you stage and swap a new build with warm-up and easy rollback
  • Application settings surface as environment variables; AzureWebJobsStorage is required by the runtime
  • Key Vault references let an app setting resolve a secret from Key Vault at runtime without code changes
  • Identity-based (managed identity) connections replace secret connection strings for triggers and bindings
  • Python functions run in a language worker out-of-process, pinned to a supported Functions runtime version
  • The Python v2 programming model defines functions with decorators in function_app.py
  • Python dependencies are declared in requirements.txt and restored during deployment build

Unlock with Premium — includes all practice exams and the complete study guide.

Secure, monitor, and troubleshoot Azure solutions

Secure secrets with Azure Key Vault

Read full chapter

Cheat sheet

Sharp facts the exam loves — scan these before test day.

SecretClient authenticated with DefaultAzureCredential retrieves a secret by name from a vault

Instantiate SecretClient(vault_url="https://.vault.azure.net", credential=DefaultAzureCredential()) and call get_secret(name) to read a secret at runtime; DefaultAzureCredential uses the app's managed identity in Azure and developer credentials locally, so no secret or connection string is embedded in code.

Trap Passing a raw API key or hard-coded credential to SecretClient defeats the purpose — the client is meant to be reached with a managed identity via DefaultAzureCredential.

11 questions test this
A versionless secret identifier returns the current version; a versioned identifier pins one exact version

A secret identifier without a version segment (.../secrets/), which Key Vault calls a base identifier, resolves to the latest version of the object, while appending a version (.../secrets//) pins that immutable version. get_secret with no version argument returns the latest version.

Trap Pinning a versioned URI means a rotated secret is NOT picked up; use the versionless identifier when you want rotation to flow through automatically.

6 questions test this
Keys, secrets, and certificates each have a dedicated Key Vault client

The SDK exposes SecretClient for secrets, KeyClient for cryptographic keys, and CertificateClient for certificates; they are separate clients against the same vault endpoint because the three object types have distinct operations and permissions.

Expiry and not-before are informational for a secret get; only enabled=false blocks retrieval

The exp and nbf attributes on a Key Vault secret are informational for a get - the docs carry a dedicated Date-time controlled operations section stating that a get works for not-yet-valid and expired secrets, so they can be used for test and recovery scenarios. Only enabled=false blocks a get. A get against a disabled version fails and the value cannot be read until the version is re-enabled with update_secret_properties(name, enabled=True).

Trap Setting an expiration date does not stop an application from reading the secret - code that must hard-stop access to a compromised credential has to DISABLE the secret version, not merely expire it.

3 questions test this
A Key Vault SDK client's first call returns 401 by design - the challenge that discovers the tenant

Key Vault SDK clients for secrets, keys and certificates send their first request without an access token on purpose: Key Vault answers HTTP 401 with a WWW-Authenticate header naming the authorization endpoint and the resource, and the client then retries with a valid token. A 401 on a process's first Key Vault call is the expected handshake, not a misconfiguration; only a 401 that persists after the retry indicates a real credential or access problem.

Trap A 401 in traces or logs for the first Key Vault call does NOT mean DefaultAzureCredential failed - the handshake is how the client learns which tenant to authenticate against, so chasing it as a credential bug wastes the investigation.

1 question tests this
A SecretClient binds to one vault endpoint, and Managed HSM has no secrets surface at all

A SecretClient is constructed against exactly one vault's data-plane endpoint, and the DNS suffix is cloud-specific (.vault.azure.net in the public cloud, .vault.azure.cn and .vault.usgovcloudapi.net in the sovereign clouds), so the vault URL must be configuration rather than a literal in code that runs across clouds. Managed HSM is a keys-only container reached at .managedhsm.azure.net: it supports HSM-protected keys and nothing else, so secret retrieval has no Managed HSM equivalent.

Trap Managed HSM is not a higher-security drop-in for a vault that stores secrets - it exposes only /keys, so a workload that must RETRIEVE secrets still needs a key vault no matter how strong its HSM requirement is.

5 questions test this
Key Vault throttles per vault per region, and the subscription ceiling is only five times one vault

Key Vault's transaction budget is enforced per vault per region and answers HTTP 429 once a client exceeds it, so a single high-traffic vault is the bottleneck rather than the subscription. Retrieval scales by caching secrets in memory and re-reading only when the cached copy stops working, and by splitting traffic across multiple vaults - but the subscription-wide ceiling is only five times a single vault's limit, so adding vaults inside one subscription stops helping.

Trap Retrying a 429 immediately does not help; and because the throttle scope is the vault resource, 'use a bigger vault' is not an available move - the levers are caching, more vaults, and eventually more subscriptions.

Key Vault emits Event Grid events such as SecretNearExpiry and SecretNewVersionCreated to drive rotation

Key Vault publishes lifecycle events (Microsoft.KeyVault.SecretNearExpiry, SecretExpired, SecretNewVersionCreated) to Event Grid; subscribing an Azure Function to SecretNearExpiry lets you generate a new credential in the backing service and add it as a new secret version before the old one expires.

Trap Polling the vault on a timer to check expiry is the anti-pattern the event model replaces — rotation should be event-driven off SecretNearExpiry, not scheduled scanning.

14 questions test this
Rotating a secret creates a new version, and versionless consumers pick it up automatically

Rotation does not overwrite in place; set_secret adds a new version and the prior version stays recoverable. Consumers that reference the secret by its versionless identifier begin resolving the new version automatically, which is what allows rotation without a redeploy.

Trap Thinking rotation overwrites the secret in place, so the previous value is gone.

6 questions test this
Cryptographic keys support a built-in automatic rotation policy

For keys (not secrets), Key Vault offers a rotation policy that regenerates the key on a defined interval and can fire a near-expiry Event Grid notification; secret rotation of external credentials still relies on a custom rotation handler.

An app setting of the form @Microsoft.KeyVault(...) resolves a secret at runtime without code

Set an App Service or Functions application setting to @Microsoft.KeyVault(SecretUri=) (or @Microsoft.KeyVault(VaultName=...;SecretName=...)); the platform resolves it from Key Vault using the app's managed identity and injects the plain value as an environment variable, so the secret never appears in source control or configuration files.

Trap The app's managed identity still needs Get permission on the vault (Key Vault Secrets User under RBAC); without it the reference FAILS TO RESOLVE and the platform injects the literal '@Microsoft.KeyVault(...)' reference string as the setting value — it is never blank.

9 questions test this
A versionless Key Vault reference automatically picks up a rotated secret; a versioned one pins it

When the reference omits the version, App Service periodically refreshes the resolved value (within about a day, or immediately on an application-settings change or restart) so a rotated secret flows in with no redeploy and no downtime; a versioned reference stays fixed to that version.

Trap Expecting a version-pinned Key Vault reference to follow a rotated secret.

2 questions test this
Grant the workload's managed identity the Key Vault Secrets User role for read access

Assign the app's system- or user-assigned managed identity the data-plane role Key Vault Secrets User (get/list secrets) scoped to the vault; the app then authenticates with that identity via DefaultAzureCredential and reads secrets with no stored credential.

Trap Key Vault Secrets User grants only read (get/list); creating or rotating secrets requires Key Vault Secrets Officer — don't over- or under-grant the role.

11 questions test this
A vault uses either Azure RBAC or vault access policies, not both at once

Each vault's permission model is set by enableRbacAuthorization: Azure RBAC uses role assignments that inherit from subscription/resource-group scope, while the legacy vault-access-policy model assigns per-principal permissions on the vault itself. Microsoft recommends RBAC for consistent, scopeable management.

Trap Expecting a leftover vault access policy to still grant access once the vault moves to Azure RBAC.

10 questions test this
DefaultAzureCredential chain and user-assigned identity client-id

DefaultAzureCredential tries an ordered chain of credentials - environment variables, then workload/managed identity, then developer credentials (Azure CLI / VS Code) - so the same SDK code authenticates locally and in Azure with no code change. Configuration is what differs: when the workload must authenticate as a USER-ASSIGNED managed identity, name it by client id (the AZURE_CLIENT_ID environment variable, or ManagedIdentityCredential(client_id=...)), because IMDS resolves an unnamed request to the system-assigned identity when one is enabled and rejects it outright when several user-assigned identities exist.

Trap Supplying no client id does NOT reliably fail: with a system-assigned identity enabled, IMDS defaults to it, so a role granted only to a user-assigned identity produces a 403 authorization error rather than an authentication error. The request fails outright only when no system-assigned identity is enabled and two or more user-assigned identities exist.

6 questions test this
Soft-delete retains deleted vaults and secrets for a retention period so they can be recovered

Soft-delete (enabled by default and not disableable) keeps a deleted vault or secret in a recoverable state for its configured retention period; you recover the object during that window instead of losing it permanently.

Trap Assuming soft-delete can be switched off to make a delete immediate.

12 questions test this
Purge protection blocks permanent deletion until the retention period elapses

With purge protection enabled, a soft-deleted vault or secret cannot be purged (permanently deleted) before its retention period ends, defeating an attacker or accident that tries to erase secrets immediately. Purge protection cannot be turned off once enabled.

Trap Soft-delete alone still allows an immediate purge; only purge protection prevents early permanent deletion — the two settings are distinct.

10 questions test this

Store and retrieve settings with Azure App Configuration

Read full chapter
  • Labels let one key hold a distinct value per environment
  • A key-value is uniquely identified by the key plus its label
  • A Key Vault reference stores the secret's URI, marked by a special content type; the secret stays in Key Vault
  • The application/json content type lets the provider parse a value as structured data
  • Feature flags are special key-values that toggle features without a redeploy
  • Feature filters conditionally enable a flag
  • Python resolves a flag through FeatureManager.is_enabled() over an opt-in load
  • Flags carry their own refresh switch and need no watch key
  • A sentinel key lets the provider reload all settings only when that one key changes
  • The provider caches configuration and refreshes on a cache-expiration interval
  • A snapshot is an immutable, named set of key-values for consistent deployment and rollback
  • Point-in-time queries recover an earlier key-value state from revision history
  • A Python app pins a release by naming the snapshot in the provider's selects argument
  • Archiving starts an expiration countdown that recovery has to beat

Unlock with Premium — includes all practice exams and the complete study guide.

Trace distributed systems with OpenTelemetry

Read full chapter
  • configure_azure_monitor() wires OpenTelemetry export to Application Insights in one call
  • The exporter can be attached to a manually built TracerProvider
  • Individual bundled instrumentations are switched off by name
  • Ingestion volume is throttled by the Distro's sampler arguments
  • Live Metrics streams unsampled, unstored, unbilled telemetry over a two-way channel
  • Telemetry volume is cut at the SDK or at ingestion, and the two act at different points
  • App Service autoinstrumentation and the in-code Distro have different ceilings
  • A trace is a tree of spans sharing a trace ID, propagated across services by the traceparent header
  • Manual spans add custom operations and attributes inside the current trace
  • The Distro auto-instruments common libraries so calls are traced without code changes
  • OpenTelemetry is a vendor-neutral standard; the Azure Monitor Distro packages it with an exporter
  • Never call instrument() for a library the Distro already covers
  • An exception you catch yourself is invisible unless you record it on the span
  • Exported spans become requests and dependencies correlated by a shared operation ID
  • Sampling reduces telemetry volume while keeping whole traces intact

Unlock with Premium — includes all practice exams and the complete study guide.

Analyze logs and metrics with KQL

Read full chapter
  • KQL chains tabular operators with the pipe, each transforming the previous result
  • summarize with a by clause groups rows and computes aggregates per group
  • A TimeGenerated filter in the query sets the Log Analytics time range - unless the source is a classic app(), where both windows apply
  • On a Basic or Auxiliary table the query is limited to one table - join, find, search and externaldata are unavailable
  • A log query is capped at 500,000 records, ~100 MB and 10 minutes, and a multi-region scope is warned then blocked
  • Kusto's datetime and term indexes dictate the order of where predicates and the choice of has over contains
  • Application Insights exposes one table per telemetry type, and which of them fill depends on how the app is instrumented
  • join and union correlate rows across telemetry tables
  • Application Insights tables keep ninety days for free while the rest of the workspace keeps thirty
  • A custom metric is stored twice, and the two copies do not carry the same dimensions
  • bin() buckets timestamps into intervals so summarize can build a time series
  • ago() and datetime comparisons scope a query to a time range
  • make-series returns gap-free arrays because empty intervals take the declared default
  • render timechart demands a leading datetime column and splits lines on a string column
  • Failed-request triage filters requests by success and groups by result code
  • Slow-dependency triage aggregates dependency duration, including tail latency

Unlock with Premium — includes all practice exams and the complete study guide.