Acedify
AZ-204, certifications
Back to all posts

Exam page

Practice AZ-204

Azure Developer Associate (AZ-204)

az-204azurecertificationsguides

Microsoft Azure Developer Associate (AZ-204): 5 Must-Know Concepts

Acedify

Acedify Team

17 Jan 202612 min read

The Azure Developer Associate exam (AZ-204) validates the ability to design, build, test, and maintain cloud applications on Microsoft Azure. It is code-heavy and expects real development experience — these five concepts recur in scenarios.

1. Azure Compute Solutions#

Compute solutions make up 25-30% of the exam — you need to know when to use each service and how to implement them.

Tip

Think of Azure compute as a spectrum: VMs give you full control, App Service handles the platform, Functions go serverless, and containers offer portability. Choose based on your control vs. management trade-off.

Azure App Service#

App Service is your go-to for hosting web applications, REST APIs, and mobile backends:

// Configure App Service settings programmatically
var webApp = azure.WebApps.Define("myapp")
    .WithRegion(Region.USEast)
    .WithExistingResourceGroup("myResourceGroup")
    .WithNewAppServicePlan(PricingTier.StandardS1)
    .WithRuntimeStack(WebAppRuntimeStack.NETCore("6.0"))
    .WithAppSetting("ConnectionString", "@Microsoft.KeyVault(SecretUri=...)")
    .Create();

Key concepts to know:

  • Deployment slots — Deploy to staging, test, then swap to production with zero downtime
  • Autoscale rules — Scale based on metrics like CPU, memory, or HTTP queue length
  • App Settings & Connection Strings — Configure without code changes, use Key Vault references

Azure Functions#

Serverless compute for event-driven scenarios:

// Blob-triggered function example
[FunctionName("ProcessImage")]
public static async Task Run(
    [BlobTrigger("images/{name}", Connection = "StorageConnection")] Stream imageBlob,
    string name,
    [Blob("thumbnails/{name}", FileAccess.Write)] Stream thumbnailBlob,
    ILogger log)
{
    log.LogInformation($"Processing blob: {name}");
    // Generate thumbnail and write to output blob
    await GenerateThumbnailAsync(imageBlob, thumbnailBlob);
}
Trigger TypeUse Case
HTTPREST APIs, webhooks
TimerScheduled tasks, cleanup jobs
BlobProcess uploaded files
QueueBackground processing, decoupling
Event GridReact to Azure events
Service BusEnterprise messaging scenarios

Azure Container Solutions#

ServiceDescriptionUse When
Container Instances (ACI)Simple, fast container hostingQuick deployments, burst workloads
Container AppsServerless containers with autoscaleMicroservices, event-driven apps
Kubernetes Service (AKS)Full Kubernetes orchestrationComplex multi-container workloads
Compute Solutions Check

You need to run a containerized app that scales to zero when idle and scales up based on HTTP traffic. Which service is best?

2. Azure Storage Solutions#

Understanding storage options and access patterns is critical for the exam.

Blob Storage Operations#

// Upload a blob with metadata
BlobClient blobClient = containerClient.GetBlobClient("document.pdf");

var options = new BlobUploadOptions
{
    HttpHeaders = new BlobHttpHeaders { ContentType = "application/pdf" },
    Metadata = new Dictionary<string, string>
    {
        { "uploadedBy", "user123" },
        { "department", "engineering" }
    }
};

await blobClient.UploadAsync(fileStream, options);

Blob Access Tiers#

TierAccess FrequencyMin Storage DurationCost
HotFrequently accessedNoneHigher storage, lower access
CoolInfrequently accessed30 daysLower storage, higher access
ColdRarely accessed90 daysEven lower storage
ArchiveRarely accessed, offline180 daysLowest storage, highest access

Warning

Archive tier blobs must be rehydrated before access — this can take hours! Use blob lifecycle management policies to automatically transition blobs between tiers.

Shared Access Signatures (SAS)#

SAS tokens provide secure, delegated access to your storage resources:

// Generate a SAS token for blob read access
BlobSasBuilder sasBuilder = new BlobSasBuilder
{
    BlobContainerName = containerName,
    BlobName = blobName,
    Resource = "b", // b for blob
    ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};
sasBuilder.SetPermissions(BlobSasPermissions.Read);

Uri sasUri = blobClient.GenerateSasUri(sasBuilder);

SAS Types:

  • User Delegation SAS — Secured with Entra ID credentials (most secure)
  • Service SAS — Scoped to a single storage service
  • Account SAS — Access to multiple services in a storage account

Azure Cosmos DB#

Know the consistency levels — this is heavily tested:

LevelGuaranteeLatencyUse Case
StrongLinearizabilityHighestFinancial transactions
Bounded StalenessConsistent prefix, bounded lagHighLeaderboards, inventory
SessionRead your writes within sessionMediumShopping carts, user profiles
Consistent PrefixOrdered readsLowSocial feeds
EventualNo ordering guaranteeLowestAnalytics, non-critical reads
// Query with the SDK
var container = cosmosClient.GetContainer("database", "products");

var query = new QueryDefinition(
    "SELECT * FROM c WHERE c.category = @category")
    .WithParameter("@category", "electronics");

using FeedIterator<Product> iterator = container.GetItemQueryIterator<Product>(query);

while (iterator.HasMoreResults)
{
    FeedResponse<Product> response = await iterator.ReadNextAsync();
    foreach (Product product in response)
    {
        Console.WriteLine(product.Name);
    }
}
Storage Solutions Quiz

You need to give a partner temporary read access to a specific blob without sharing your account key. What should you use?

3. Implementing Azure Security#

Security is 20-25% of the exam. Focus on managed identities, Key Vault, and authentication patterns.

Note

The exam loves questions about managed identities — they eliminate the need to manage credentials in code. System-assigned identities are tied to a resource's lifecycle; user-assigned identities can be shared across resources.

Managed Identity with Key Vault#

// Access Key Vault using managed identity (no credentials in code!)
var credential = new DefaultAzureCredential();
var client = new SecretClient(
    new Uri("https://myvault.vault.azure.net/"),
    credential);

KeyVaultSecret secret = await client.GetSecretAsync("DatabasePassword");
string connectionString = secret.Value;

App Service Authentication (Easy Auth)#

Configure identity providers without writing authentication code:

// authentication settings in Azure portal or ARM template
{
  "platform": {
    "enabled": true
  },
  "identityProviders": {
    "azureActiveDirectory": {
      "enabled": true,
      "registration": {
        "clientId": "<app-registration-client-id>",
        "openIdIssuer": "https://login.microsoftonline.com/<tenant-id>/v2.0"
      }
    }
  },
  "login": {
    "tokenStore": {
      "enabled": true
    }
  }
}

Microsoft Identity Platform#

For custom authentication, use MSAL (Microsoft Authentication Library):

// Acquire token for calling an API
var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithClientSecret(clientSecret)
    .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
    .Build();

var result = await app
    .AcquireTokenForClient(new[] { "api://target-api/.default" })
    .ExecuteAsync();

string accessToken = result.AccessToken;

Security Best Practices#

PracticeImplementation
Never store secrets in codeUse Key Vault with managed identity
Use managed identitiesEnable system or user-assigned identity
Apply least privilegeGrant minimum required permissions
Rotate secretsUse Key Vault secret rotation
Validate tokensVerify issuer, audience, and signature
Security Implementation Quiz

Your Azure Function needs to read secrets from Key Vault. What's the most secure approach?

4. Monitoring and Optimization#

Understand how to instrument applications and optimize performance.

Application Insights#

// Custom telemetry tracking
private readonly TelemetryClient _telemetryClient;

public async Task ProcessOrderAsync(Order order)
{
    var stopwatch = Stopwatch.StartNew();
    
    try
    {
        // Track custom event
        _telemetryClient.TrackEvent("OrderProcessed", new Dictionary<string, string>
        {
            { "OrderId", order.Id },
            { "CustomerId", order.CustomerId }
        });
        
        await ProcessAsync(order);
        
        // Track custom metric
        _telemetryClient.TrackMetric("OrderProcessingTime", stopwatch.ElapsedMilliseconds);
    }
    catch (Exception ex)
    {
        // Track exception with context
        _telemetryClient.TrackException(ex, new Dictionary<string, string>
        {
            { "OrderId", order.Id }
        });
        throw;
    }
}

Key Application Insights Features#

FeaturePurpose
Distributed TracingCorrelate requests across services
Live MetricsReal-time performance monitoring
Application MapVisualize service dependencies
Smart DetectionAutomatic anomaly detection
Availability TestsMonitor endpoint health globally

Caching with Azure Cache for Redis#

// Connection with proper configuration
var connection = ConnectionMultiplexer.Connect(new ConfigurationOptions
{
    EndPoints = { "mycache.redis.cache.windows.net:6380" },
    Password = "<access-key>",
    Ssl = true,
    AbortOnConnectFail = false
});

IDatabase cache = connection.GetDatabase();

// Cache-aside pattern
public async Task<Product> GetProductAsync(string productId)
{
    string cacheKey = $"product:{productId}";
    
    // Try cache first
    string cached = await cache.StringGetAsync(cacheKey);
    if (!string.IsNullOrEmpty(cached))
        return JsonSerializer.Deserialize<Product>(cached);
    
    // Load from database
    Product product = await _database.GetProductAsync(productId);
    
    // Cache for 1 hour
    await cache.StringSetAsync(
        cacheKey, 
        JsonSerializer.Serialize(product),
        TimeSpan.FromHours(1));
    
    return product;
}

Tip

Use the cache-aside pattern: check the cache first, load from the source on cache miss, then populate the cache. This works well for read-heavy workloads with data that changes infrequently.

Azure CDN#

CDN improves performance by caching static content at edge locations:

  • Cache rules — Control what gets cached and for how long
  • Query string caching — Ignore, cache unique, or bypass cache
  • Compression — Automatic gzip/brotli compression
  • Custom domains — Use your own domain with HTTPS
Monitoring & Optimization Quiz

You need to track how long specific operations take in your application. What Application Insights method should you use?

5. Connect to Azure Services#

The final domain covers API Management, messaging, and event-driven patterns.

Azure API Management#

API Management provides a facade for your backend services:

<!-- Inbound policy example: validate JWT and rate limit -->
<inbound>
    <validate-jwt header-name="Authorization" 
                  failed-validation-httpcode="401"
                  require-signed-tokens="true">
        <openid-config url="https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration"/>
        <required-claims>
            <claim name="aud" match="any">
                <value>{client-id}</value>
            </claim>
        </required-claims>
    </validate-jwt>
    <rate-limit calls="100" renewal-period="60"/>
</inbound>

Event Grid vs Service Bus vs Queue Storage#

ServicePatternMessage SizeUse Case
Event GridPub/Sub events1 MBReact to Azure/custom events
Service BusEnterprise messaging256 KB – 100 MBOrdered, transactional messaging
Queue StorageSimple queue64 KBLightweight async processing

Event Grid Integration#

// Publish custom events
var client = new EventGridPublisherClient(
    new Uri("https://mytopic.eastus-1.eventgrid.azure.net/api/events"),
    new AzureKeyCredential("<topic-key>"));

var events = new List<EventGridEvent>
{
    new EventGridEvent(
        subject: "orders/new",
        eventType: "Order.Created",
        dataVersion: "1.0",
        data: new { OrderId = "12345", CustomerId = "C001" })
};

await client.SendEventsAsync(events);

Service Bus Patterns#

// Send message with session for ordered processing
var client = new ServiceBusClient(connectionString);
var sender = client.CreateSender("orders-queue");

var message = new ServiceBusMessage(JsonSerializer.SerializeToUtf8Bytes(order))
{
    SessionId = order.CustomerId,  // Group by customer
    MessageId = Guid.NewGuid().ToString(),
    ContentType = "application/json"
};

await sender.SendMessageAsync(message);

Note

Sessions in Service Bus enable FIFO (first-in, first-out) processing. All messages with the same SessionId are processed in order by a single consumer. This is essential for scenarios like order processing where sequence matters.

Service Integration Quiz

Multiple services need to react when a new customer signs up. Which service best supports this pub/sub pattern?


Know your range before test day#

AZ-204 is code-and-scenario heavy. A short diagnostic shows which compute, security, or messaging topics still break under pressure.

  • Timed diagnostic with domain-level breakdown
  • Clear signal on what to drill next
  • Practice free; timed sittings and readiness range on Pro

Take the free AZ-204 assessment →


Next step: Start practicing free on the AZ-204 hub, or sit a short diagnostic first.

Ready to practice AZ-204?

Go to the Azure Developer page for the diagnostic, study plan, and practice.

Practice AZ-204