AZ-204 Cheatsheet — Code Snippets, Tables, and High-Yield Azure Developer Patterns

Comprehensive AZ-204 quick reference: App Service, Functions, containers, Cosmos DB, Blob Storage, Entra ID auth, Key Vault/App Configuration, API Management policies, Event Grid/Hubs, Service Bus/Queues, and Application Insights. Includes code, tables, charts, and diagrams.

On this page

Use this for last‑mile review. Pair it with the Syllabus for coverage, the Study Plan for structure, and Practice for speed.


AZ-204 at a glance (what Microsoft tests)

AZ-204 is less about memorizing product lists and more about choosing the right service + configuration for a scenario.

Domain weighting chart (official ranges)

Domain Weight Visual (relative)
Develop Azure compute solutions 25–30% ██████████
Develop for Azure storage 15–20% ██████
Implement Azure security 15–20% ██████
Monitor and troubleshoot Azure solutions 5–10% ███
Connect/consume Azure + third-party services 20–25% ████████

Always look for the hidden requirement: private vs public, ordering, idempotency, throughput, RTO/RPO, least privilege, cost controls.


1) Compute service picker (most-tested table)

Need Best fit Why
Managed web app/API with easy deployment App Service Built-in scaling, TLS/custom domains, slots
Event-driven code, bursty traffic Functions Triggers/bindings, scale-to-zero (Consumption)
Containerized microservices with revisions + KEDA Container Apps Managed env, ingress, traffic splitting
“Run a container now” without orchestration Container Instances Simple container group execution
    flowchart TD
	  Q{"Do you need triggers\nand bindings?"} -->|Yes| F["Azure Functions"]
	  Q -->|No| C{"Do you need\na container image?"}
	  C -->|No| AS["App Service"]
	  C -->|Yes| O{"Need revisions\n+ autoscaling rules?"}
	  O -->|Yes| CA["Container Apps"]
	  O -->|No| ACI["Container Instances"]

2) Containers (ACR → ACI / Container Apps)

ACR quick CLI

1# Create ACR
2az acr create -g RG -n myregistry --sku Basic
3
4# Login and push
5az acr login -n myregistry
6docker build -t myregistry.azurecr.io/myapi:1.0.0 .
7docker push myregistry.azurecr.io/myapi:1.0.0

ACR authentication options (pick least-privilege)

Option Best when Notes
Entra ID (AAD) humans/devs Role assignments; best default
Managed identity Azure-hosted workloads Great for pull access (no secrets)
Scoped tokens limited automation Narrow scope + expiry
Admin user last resort Shared credential; avoid for prod

Dockerfile (multi-stage, small runtime)

 1FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
 2WORKDIR /src
 3COPY . .
 4RUN dotnet publish -c Release -o /out
 5
 6FROM mcr.microsoft.com/dotnet/aspnet:8.0
 7WORKDIR /app
 8COPY --from=build /out .
 9ENV ASPNETCORE_URLS=http://+:8080
10EXPOSE 8080
11ENTRYPOINT ["dotnet","MyApi.dll"]

ACR Tasks / CI: automate builds

1# Example: build on source context (conceptual)
2az acr build -r myregistry -t myapi:<build-id> .

Container Apps: why it’s different

Feature Container Apps ACI
Revision-based deploys
Traffic splitting
Event-based scaling (KEDA)
“Just run a container” simplicity ⚠ (more setup)

Container Apps: key knobs to remember

  • Ingress (external vs internal), custom domains
  • Revisions (single vs multiple) + traffic weights
  • Secrets and environment variables (avoid baking secrets into images)
  • Scaling rules (HTTP concurrency, queue length, event-based via KEDA)
1# Minimal Container Apps flow (conceptual)
2az containerapp env create -g RG -n ca-env --location eastus
3az containerapp create -g RG -n myapi --environment ca-env \\
4  --image myregistry.azurecr.io/myapi:1.0.0 --ingress external --target-port 8080
    flowchart LR
	  DEV["Dev pushes image"] --> ACR["ACR"]
	  ACR --> CA["Container Apps"]
	  CA --> REV{"Revisions"}
	  REV -->|blue| R1["rev-1"]
	  REV -->|green| R2["rev-2"]
	  R1 --> TR["Traffic split"]
	  R2 --> TR

Common gotcha: container apps and private registries require correct auth (managed identity or registry credentials) and correct image reference.


3) App Service (Web Apps) — deploy, diagnose, scale, slots

Deployment options (know the trade-offs)

Method When it’s best Notes
Zip deploy / run-from-package Fast + simple Great for CI/CD artifacts
GitHub Actions / Azure DevOps Repeatable Build → test → deploy pipelines
Container from ACR Containerized web apps Control image tag/version

Quick CLI: create + deploy + slots (conceptual)

 1# Plan + web app
 2az appservice plan create -g RG -n plan-az204 --sku P1v3 --is-linux
 3az webapp create -g RG -p plan-az204 -n mywebapp --runtime \"DOTNETCORE:8.0\"
 4
 5# App settings (configuration) + connection strings
 6az webapp config appsettings set -g RG -n mywebapp --settings ASPNETCORE_ENVIRONMENT=prod
 7az webapp config connection-string set -g RG -n mywebapp -t SQLAzure --settings Db=\"<conn-string>\"
 8
 9# Zip deploy (one option)
10az webapp deploy -g RG -n mywebapp --src-path ./artifact.zip --type zip
11
12# Slots (safe releases)
13az webapp deployment slot create -g RG -n mywebapp --slot staging
14az webapp deployment slot swap -g RG -n mywebapp --slot staging --target-slot production

GitHub Actions (minimal pattern)

 1name: build-and-deploy
 2on: [push]
 3jobs:
 4  deploy:
 5    runs-on: ubuntu-latest
 6    steps:
 7      - uses: actions/checkout@v4
 8      - uses: azure/login@v2
 9        with:
10          creds: ${{ secrets.AZURE_CREDENTIALS }}
11      - uses: azure/webapps-deploy@v3
12        with:
13          app-name: mywebapp
14          package: ./artifact.zip

Configuration: where to put what

Item Best home Why
Feature flags / non-secret settings App Configuration Centralized, environment-aware
Secrets (API keys, passwords) Key Vault Rotation + auditing
App runtime env vars App settings Standard platform config
Database connection strings Connection strings Separate slot settings + tooling support

Slots: safe deployment pattern

    flowchart LR
	  U["Users"] --> P["Prod slot"]
	  S["Staging slot"] --> SW["Swap"]
	  SW --> P

Slot rules of thumb

  • Put env-specific config in slot settings so it doesn’t swap.
  • Use staging for warm-up, then swap for near-zero downtime.
  • Always validate connection strings and auth settings post-swap.

Diagnostics checklist (fast)

  • App Service logs: application logs + web server logs
  • Log stream for “what’s happening now”
  • Application Insights for traces/dependencies/exceptions

4) Azure Functions — triggers, bindings, retries

Trigger/binding cheat table (high yield)

Pattern Typical trigger Typical output
HTTP API HTTP trigger Storage/Cosmos/Service Bus
Background processing Queue/Service Bus trigger Blob/Cosmos/Service Bus
Event routing Event Grid trigger Service Bus / storage
Scheduled job Timer trigger Blob/Cosmos

Hosting plan picker (cold start vs scale vs networking)

Plan Best when Notes
Consumption bursty workloads scale-to-zero; watch cold start
Premium low-latency + scale reduced cold start; more features
Dedicated (App Service plan) steady load predictable capacity; you manage scaling

Retry / resilience knobs (conceptual)

1{
2  "version": "2.0",
3  "retry": {
4    "strategy": "fixedDelay",
5    "maxRetryCount": 5,
6    "delayInterval": "00:00:10"
7  }
8}

Key exam idea: many triggers are at-least-once. Design processing to be idempotent.

C# example: Service Bus trigger (peek-lock) + output

 1using Azure.Messaging.ServiceBus;
 2using Microsoft.Azure.Functions.Worker;
 3using Microsoft.Extensions.Logging;
 4
 5public class ProcessOrders
 6{
 7    private readonly ILogger _logger;
 8    public ProcessOrders(ILoggerFactory loggerFactory) => _logger = loggerFactory.CreateLogger<ProcessOrders>();
 9
10    [Function("ProcessOrders")]
11    public async Task Run(
12        [ServiceBusTrigger("orders", Connection = "ServiceBusConnection")]
13        ServiceBusReceivedMessage message,
14        ServiceBusMessageActions messageActions)
15    {
16        try
17        {
18            var body = message.Body.ToString();
19            _logger.LogInformation("Order received: {Body}", body);
20
21            // Do work...
22
23            await messageActions.CompleteMessageAsync(message);
24        }
25        catch (Exception ex)
26        {
27            _logger.LogError(ex, "Failed processing message");
28            await messageActions.AbandonMessageAsync(message);
29        }
30    }
31}

Function gotchas

  • Consumption plan cold starts: reduce heavy startup and reuse clients.
  • Queue-based triggers: design for idempotency and retries.
  • Poison messages: plan a dead-letter or poison queue strategy (Service Bus DLQ, storage queue patterns).

Durable Functions (high-level mental model)

    flowchart LR
	  START["Starter (HTTP/Timer)"] --> ORCH["Orchestrator"]
	  ORCH --> A1["Activity: step 1"]
	  ORCH --> A2["Activity: step 2"]
	  A1 --> ORCH
	  A2 --> ORCH
	  ORCH --> DONE["Complete"]

5) Cosmos DB — partitioning, consistency, change feed

Partition key rules of thumb

  • Choose a key that spreads writes/reads (avoid “all to one partition”).
  • Prefer keys you already filter on (queries become cheaper).

Consistency level quick table

Level Strength Typical use
Strong Highest Single region, strict correctness
Bounded staleness High Controlled lag
Session Medium Most apps (user session correctness)
Consistent prefix Lower Ordered but potentially stale
Eventual Lowest Highest availability/lowest latency

RU & throttling: what questions are really asking

  • 429 (Too Many Requests) → you exceeded provisioned throughput (RU/s).
  • Fix levers: increase RU (manual/autoscale), improve partitioning, reduce query cost, cache results, avoid cross-partition scans.

Optimistic concurrency (ETag) pattern

1var read = await container.ReadItemAsync<MyItem>(id, new PartitionKey(pk));
2var etag = read.ETag;
3
4item.Version = item.Version + 1;
5await container.ReplaceItemAsync(item, id, new PartitionKey(pk), new ItemRequestOptions
6{
7    IfMatchEtag = etag
8});

C# example: query with pagination

 1var client = new CosmosClient(endpoint, credential);
 2var container = client.GetContainer("db", "items");
 3
 4var query = new QueryDefinition("SELECT * FROM c WHERE c.type = @t")
 5    .WithParameter("@t", "invoice");
 6
 7using var iterator = container.GetItemQueryIterator<dynamic>(query);
 8while (iterator.HasMoreResults)
 9{
10    foreach (var item in await iterator.ReadNextAsync())
11    {
12        Console.WriteLine(item);
13    }
14}

Change feed (concept)

    flowchart LR
	  CDB["Cosmos DB container"] --> CF["Change Feed"]
	  CF --> FN["Function / Worker"]
	  FN --> OUT["Downstream system"]

Change feed gotcha: you need leases/checkpointing so processors can scale safely.

Change feed processor (conceptual C# skeleton)

 1var processor = container
 2    .GetChangeFeedProcessorBuilder<MyItem>(
 3        processorName: "proc",
 4        onChangesDelegate: async (changes, cancellationToken) =>
 5        {
 6            foreach (var doc in changes)
 7            {
 8                // react to changes
 9            }
10        })
11    .WithInstanceName("worker-1")
12    .WithLeaseContainer(leaseContainer)
13    .Build();
14
15await processor.StartAsync();

6) Blob Storage — metadata, lifecycle, SAS

Blob SDK: upload + properties + metadata (C#)

 1using Azure.Storage.Blobs;
 2using Azure.Storage.Blobs.Models;
 3
 4var container = new BlobContainerClient(connectionString, "docs");
 5await container.CreateIfNotExistsAsync();
 6
 7var blob = container.GetBlobClient("reports/2025-q4.pdf");
 8await blob.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = "application/pdf" });
 9
10await blob.SetMetadataAsync(new Dictionary<string, string>
11{
12    ["owner"] = "finance",
13    ["classification"] = "internal"
14});

Blob features that show up in scenarios

Feature Why it matters Typical scenario
Soft delete recover from deletes “accidental deletion”
Versioning recover previous versions “rollback changes” / ransomware
Immutability WORM retention compliance retention
Access tiers cost optimization logs/archives

Blob lifecycle policy (example)

 1{
 2  "rules": [
 3    {
 4      "name": "tier-old-logs",
 5      "enabled": true,
 6      "type": "Lifecycle",
 7      "definition": {
 8        "filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["logs/"] },
 9        "actions": {
10          "baseBlob": {
11            "tierToCool": { "daysAfterModificationGreaterThan": 30 },
12            "tierToArchive": { "daysAfterModificationGreaterThan": 180 },
13            "delete": { "daysAfterModificationGreaterThan": 365 }
14          }
15        }
16      }
17    }
18  ]
19}

SAS quick table

SAS type Best when Notes
Service SAS Scoped to a resource Most common “least privilege” SAS
Account SAS Broad Easy to over-permission
User delegation SAS Best security Signed by Entra ID; no account key exposure

Common gotcha: SAS failures are often clock skew, expired token, or missing permissions on the exact resource path.

SAS generation (C# quick patterns)

 1using Azure.Storage.Sas;
 2
 3var builder = new BlobSasBuilder
 4{
 5    BlobContainerName = "docs",
 6    BlobName = "reports/2025-q4.pdf",
 7    Resource = "b",
 8    ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(15)
 9};
10builder.SetPermissions(BlobSasPermissions.Read);
11
12var sasUri = blob.GenerateSasUri(builder);
13Console.WriteLine(sasUri);

7) Security — Identity platform, Entra ID, Graph, Key Vault

OAuth flow picker

Scenario Flow Why
Web app signing in a user Authorization code Standard OIDC pattern
Service-to-service (daemon) Client credentials No user context
CLI/device sign-in Device code Works without browser redirect

MSAL (C#) — client credentials token

 1using Microsoft.Identity.Client;
 2
 3var app = ConfidentialClientApplicationBuilder
 4  .Create(clientId)
 5  .WithClientSecret(clientSecret)
 6  .WithAuthority($"https://login.microsoftonline.com/{tenantId}")
 7  .Build();
 8
 9var result = await app.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" })
10  .ExecuteAsync();
11
12Console.WriteLine(result.AccessToken);

Microsoft Graph permissions (common confusion)

Permission type Used when Example
Delegated user is signed in User.Read to call /me
Application daemon/no user .default for app-only permissions

Call Microsoft Graph (HTTP example)

1using System.Net.Http.Headers;
2
3using var http = new HttpClient();
4http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
5
6var json = await http.GetStringAsync("https://graph.microsoft.com/v1.0/me");
7Console.WriteLine(json);

Managed identity + Key Vault (C#)

1using Azure.Identity;
2using Azure.Security.KeyVault.Secrets;
3
4var vaultUri = new Uri("https://myvault.vault.azure.net/");
5var client = new SecretClient(vaultUri, new DefaultAzureCredential());
6KeyVaultSecret secret = await client.GetSecretAsync("DbPassword");
    sequenceDiagram
	  participant App as "App Service / Function"
	  participant MSI as "Managed Identity"
	  participant AAD as "Entra ID"
	  participant KV as "Key Vault"
	  App->>MSI: Request token for Key Vault
	  MSI->>AAD: Get access token
	  AAD-->>MSI: Access token
	  MSI-->>App: Access token
	  App->>KV: GetSecret (Bearer token)
	  KV-->>App: Secret value

Key Vault vs App Configuration (fast picker)

Store Best for Why
Key Vault secrets/keys/certs rotation + auditing + access controls
App Configuration app settings + feature flags centralized config + refresh

8) API Management — the “policy exam”

High-yield policy snippets

Rate limiting

1<rate-limit-by-key calls="10" renewal-period="60" counter-key="@(context.Subscription.Key)" />

Validate JWT

1<validate-jwt header-name="Authorization" failed-validation-httpcode="401">
2  <openid-config url="https://login.microsoftonline.com/{tenantId}/v2.0/.well-known/openid-configuration" />
3  <required-claims>
4    <claim name="aud">
5      <value>{api-app-id-uri}</value>
6    </claim>
7  </required-claims>
8</validate-jwt>

CORS

1<cors allow-credentials="false">
2  <allowed-origins>
3    <origin>https://example.com</origin>
4  </allowed-origins>
5  <allowed-methods>
6    <method>GET</method>
7    <method>POST</method>
8  </allowed-methods>
9</cors>

Rewrite URL (common “legacy backend” fix)

1<rewrite-uri template="/v2/{uri}" />

Set backend (multi-backend routing)

1<set-backend-service base-url="https://mybackend.azurewebsites.net" />

Response caching

1<cache-lookup vary-by-developer="false" vary-by-developer-groups="false" />
2<cache-store duration="60" />

Policy scopes: global → product → API → operation (more specific overrides earlier scopes).

    flowchart LR
	  C["Client"] --> APIM["API Management"]
	  APIM --> POL["Policies (auth, throttling, transform)"]
	  POL --> BE["Backend API"]

Policy order matters: inbound runs before backend; outbound after backend response.


9) Eventing and messaging — choose the right service

The must-know chooser table

Service Best for Key traits
Event Grid event routing push, fan-out, filtering
Event Hubs streaming ingestion partitions, high throughput
Service Bus enterprise messaging DLQ, sessions, transactions
Storage Queues simple queues basic, cheap, fewer features

Feature matrix (what the question is usually testing)

Feature Event Grid Event Hubs Service Bus Storage Queues
Primary job route events ingest streams reliable messaging simple queue
Push vs pull push pull pull pull
Ordering within partition sessions/FIFO patterns best-effort
Dead-letter queue dead-lettering consumer design built-in DLQ custom pattern
Transactions
Typical workload app/resource events telemetry/logs commands/work items lightweight jobs
    flowchart LR
	  SRC["Source system"] --> EG["Event Grid"]
	  EG --> FN["Function handler"]
	  FN --> SB["Service Bus queue"]
	  SB --> WK["Worker"]

Event Grid: filter + dead-letter (conceptual)

  • Use filters to avoid “every event triggers everything.”
  • Use dead-lettering for undeliverable events (e.g., endpoint down long enough).

Event Hubs: producer (C# skeleton)

1using Azure.Messaging.EventHubs;
2using Azure.Messaging.EventHubs.Producer;
3
4await using var producer = new EventHubProducerClient(connectionString, "telemetry");
5using EventDataBatch batch = await producer.CreateBatchAsync();
6batch.TryAdd(new EventData(System.Text.Encoding.UTF8.GetBytes("{\"ok\":true}")));
7await producer.SendAsync(batch);

Service Bus: send (C# skeleton)

1using Azure.Messaging.ServiceBus;
2
3await using var client = new ServiceBusClient(connectionString);
4ServiceBusSender sender = client.CreateSender("orders");
5await sender.SendMessageAsync(new ServiceBusMessage("hello") { CorrelationId = "c-123" });

Service Bus: receive mode

Mode Behavior When to use
Peek-lock process then settle Most reliable (handles failures)
Receive-and-delete delete immediately Only when loss is acceptable

Storage Queues: visibility timeout pattern (conceptual)

 1using Azure.Storage.Queues;
 2
 3var queue = new QueueClient(connectionString, "jobs");
 4await queue.CreateIfNotExistsAsync();
 5
 6await queue.SendMessageAsync("do-work");
 7var msg = await queue.ReceiveMessageAsync(visibilityTimeout: TimeSpan.FromMinutes(2));
 8
 9// Do work...
10await queue.DeleteMessageAsync(msg.Value.MessageId, msg.Value.PopReceipt);

Poison message rule: if the same message fails repeatedly, move it to a poison/dead-letter queue and alert.


10) Application Insights — what to do on failures

KQL quick wins

requests
| where success == false
| summarize count() by resultCode, operation_Name
| order by count_ desc
dependencies
| where duration > 2s
| summarize avg(duration), count() by target
| order by avg_duration desc
exceptions
| summarize count() by type, outerMessage
| order by count_ desc

Correlation tip: join on operation_Id to stitch requests → dependencies → exceptions for a single transaction.

Alerting defaults

  • Availability test fails (web test)
  • Error rate spike (failed requests)
  • Latency regression (p95 duration)

Fast troubleshooting checklist

  • Is it auth? 401/403 spikes, token failures, Key Vault denies
  • Is it dependency? DB/HTTP dependency duration spikes
  • Is it scale? throttling, queue backlog, timeouts
  • Is it deployment? slot swap/config drift, missing app settings

11) Common exam failure patterns (quick fixes)

Symptom Likely cause First fix to try
401 from API wrong audience/issuer verify Entra app IDs + aud claim
403 from Key Vault missing RBAC/access policy grant least-privilege + verify identity
SAS “authentication failed” expired token / clock skew regenerate SAS; ensure UTC + expiry
Cosmos 429 RU throttling increase RU/autoscale; optimize partition/query
Service Bus “lock lost” processing too slow renew lock / shorten processing / increase concurrency
Event Grid delivery failures endpoint down / auth mismatch fix handler auth; configure dead-letter
App Service works in staging but not prod slot settings swapped mark correct settings as slot settings

Keep going