๐Ÿ”—
Module 7 of 9 20โ€“25% 3 sub-modules ยท 25 units Domain 3: Connect to and Consume Azure Services

Integrate Backend Services for AI Solutions

Queue and process back-end operations with Azure Service Bus including dead-letter queue handling. Implement event-driven workflows with Event Grid. Build serverless APIs with Azure Functions triggers and bindings.

Azure Service BusAzure Event GridAzure Functions

Last updated: ยท Aligned with Course AI-200T00-A

Module

Integrate Services with Azure Service Bus

units
๐ŸŽฌ Unit 1

Introduction

3 min

Azure Service Bus is an enterprise-grade messaging broker that decouples AI pipeline stages. A document ingestion API sends to a queue; an embedding service processes independently; a vector indexing service receives results โ€” all without any service knowing about the others. The broker handles ordering, retries, dead-lettering, and guaranteed delivery.

๐Ÿ’ก Exam Tip
Exam pillars: 1) Queues vs Topics vs Subscriptions 2) Peek-lock vs Receive-and-Delete modes 3) Dead-letter queue (DLQ) purpose 4) Claim-check pattern for large messages 5) Sessions for FIFO ordering.
๐Ÿ“˜ Unit 2

Service Bus Concepts

8 min

Service Bus: Producer โ†’ Queue/Topic โ†’ Multiple Consumers (fan-out for Topics)

ProducerAI PipelineService BusQueueTopicDead-letter โ†’ Sessions โ†’ FIFOConsumer AConsumer BConsumer C

1. Queues vs Topics/Subscriptions

#FeatureQueueTopic + Subscriptions
1ConsumersOne receiver per messageEach subscription gets a copy โ†’ multiple receivers
2PatternPoint-to-pointPub/Sub (fan-out)
3Use forTask queue, work distributionEvents that multiple services must react to
4AI exampleDocument โ†’ embedding worker (1 worker processes)New AI result โ†’ logging + analytics + webhook (3 subscribers)
โš ๏ธ Common Gotcha
Queue = ONE consumer gets the message. Topic = ALL subscriptions get a copy. "Fan-out to multiple services" always means Topic, not Queue.

2. Message Properties

  1. MessageId โ€” unique identifier. Used for duplicate detection (idempotent receive).
  2. SessionId โ€” groups related messages. Required for session-based FIFO ordering. All messages with same SessionId go to same consumer.
  3. ScheduledEnqueueTimeUtc โ€” delay message delivery to a future time.
  4. TimeToLive (TTL) โ€” auto-move to DLQ if not consumed before TTL expires.
  5. ApplicationProperties โ€” custom key-value metadata for filtering subscriptions.

3. Receive Modes โ€” The Exam Trap

  1. Peek-lock (default, recommended) โ€” message is locked for a timeout (default 60 seconds). Process succeeds โ†’ call complete(). Process fails โ†’ lock expires, message returns to queue for retry. Guarantees at-least-once delivery.
  2. Receive-and-Delete โ€” message deleted immediately on receive. Fast but if processing fails, message is lost forever. Only for non-critical, idempotent operations.
โš ๏ธ Common Gotcha
Always default to Peek-lock. If the question asks "ensure no messages are lost even if consumer crashes" โ†’ Peek-lock. If "maximum throughput, message loss acceptable" โ†’ Receive-and-Delete.
๐Ÿ“˜ Unit 3

Send and Receive Messages with the SDK

10 min

1. Send Messages

from azure.servicebus import ServiceBusClient, ServiceBusMessage
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
client = ServiceBusClient("mynamespace.servicebus.windows.net", credential)

with client.get_queue_sender("document-processing") as sender:
    msg = ServiceBusMessage(
        body='{"document_id": "doc-456", "url": "https://..."}',
        message_id="doc-456",                # For duplicate detection
        application_properties={"model": "gpt-4o", "priority": "high"}
    )
    sender.send_messages(msg)

2. Receive Messages (Peek-Lock)

with client.get_queue_receiver("document-processing", max_wait_time=5) as receiver:
    for msg in receiver:
        try:
            process_document(str(msg))       # Your business logic
            receiver.complete_message(msg)   # Removes from queue
        except Exception as e:
            receiver.abandon_message(msg)    # Returns to queue for retry
            # Or: receiver.dead_letter_message(msg, reason=str(e))  # Send to DLQ

3. Send Large Payloads โ€” Claim-Check Pattern

Service Bus max message size = 256 KB (Standard) or 100 MB (Premium with large message support). AI models, embeddings, and documents often exceed this.

  1. Upload large content to Azure Blob Storage
  2. Send only the blob URI in the Service Bus message body
  3. Receiver reads URI, fetches blob, processes large content
# Producer (send only the reference)
blob_uri = upload_to_blob(large_document_bytes)
sender.send_messages(ServiceBusMessage(
    body='{"blob_uri": "' + blob_uri + '", "document_id": "doc-123"}'
))

# Consumer (fetch the actual content)
msg_data = json.loads(str(msg))
content = download_from_blob(msg_data["blob_uri"])
๐Ÿ’ก Exam Tip
Claim-check pattern = message carries a pointer (blob URI), not the payload. Exam scenario: "messages exceed 256 KB limit" โ†’ answer is always claim-check pattern.
๐Ÿ“˜ Unit 4

Dead-Letter Queue, Sessions, and Filters

8 min

1. Dead-Letter Queue (DLQ)

Sub-queue automatically created for every queue/subscription. Messages land in DLQ when:

  1. Delivery count exceeds maximum (default 10 retries)
  2. Consumer explicitly calls dead_letter_message()
  3. Message TTL expires without being consumed
  4. Filter evaluation fails on a topic subscription

Access the DLQ path: queuename/$deadletterqueue. Re-process or investigate failed messages there.

โš ๏ธ Common Gotcha
DLQ is NOT the primary queue. It's a holding area for poison messages. Monitor DLQ message count as an alert โ€” growing DLQ = something is wrong with your consumer logic.

2. Sessions โ€” FIFO Ordering Per Key

Standard Service Bus is not ordered. Sessions guarantee FIFO ordering for messages with the same session_id. Essential for conversation chains in AI chatbots where messages from the same user must be processed in order.

msg = ServiceBusMessage(body="step-2", session_id="user-001")
sender.send_messages(msg)

# Receiver acquires exclusive lock on a session
with receiver.get_session_receiver("my-queue", session_id="user-001") as session_receiver:
    for msg in session_receiver:
        process_in_order(msg)

3. Topic Filters โ€” Route Messages to Subscriptions

  1. Boolean filter โ€” TrueRuleFilter(): all messages. FalseRuleFilter(): no messages.
  2. SQL filter โ€” SQL-like expression on ApplicationProperties: priority = 'high' AND model = 'gpt-4o'
  3. Correlation filter โ€” match specific property values exactly. More efficient than SQL filters.

โšก Service Bus Master Cheatsheet

One consumerQueue
Fan-out to N servicesTopic + Subscriptions
No message lossPeek-lock mode + complete()/abandon()
Fast, loss acceptableReceive-and-Delete
Large payload (>256 KB)Claim-check (blob URI in message)
FIFO per keySessions (session_id field)
Failed after 10 retriesDead-letter queue (DLQ)
Filter topic messagesSQL filter on ApplicationProperties
Duplicate detectionSet message_id, enable on namespace
DLQ pathqueuename/$deadletterqueue
๐Ÿงช Unit 5

Exercise โ€” Async Document Processing Pipeline

30 min
  1. Create a Service Bus namespace and queue
  2. Send document processing messages with application_properties for model type
  3. Implement a consumer with peek-lock: complete on success, abandon on failure
  4. Observe DLQ after 10 failed retries
  5. Implement claim-check: upload a large JSON payload to Blob, send URI in message
  6. Create a topic with two subscriptions + SQL filter to route by model type
โœ… Unit 6

Knowledge Check

5 min
  1. Q: New AI result must notify 3 different services. Queue or Topic? A: Topic with 3 subscriptions (fan-out)
  2. Q: Consumer crashes mid-processing. Which receive mode re-queues message? A: Peek-lock (lock expires โ†’ message returns to queue)
  3. Q: Message payload is 5 MB embedding vector. Service Bus max is 256 KB. Solution? A: Claim-check pattern (store blob in Azure Storage, send URI)
  4. Q: Chat messages per user must be processed in order. Feature needed? A: Sessions (session_id = userId)
  5. Q: Where do messages go after 10 failed delivery attempts? A: Dead-letter queue (DLQ)
๐Ÿ Unit 7

Summary

2 min

Service Bus decouples AI pipeline stages. Use Queues for point-to-point, Topics for pub/sub fan-out. Always use Peek-lock for reliability โ€” complete on success, abandon or dead-letter on failure. Use claim-check for large payloads. Use sessions for per-key FIFO. Monitor DLQ for stuck messages. Authenticate with managed identity + Azure Service Bus Data Sender/Receiver roles.

๐Ÿง  Memory Tricks

Queue vs Topic: Queue = one consumer wins. Topic = everyone wins (pub/sub).

Peek-lock flow: Peek (lock) โ†’ Process โ†’ Complete (or Abandon/DLQ). Think: "Look before you delete."

Claim-check: "Check your coat at the door" โ€” store the big thing (blob), carry the ticket (URI).

๐Ÿ Unit 8

Exam Summary Card

2 min
ScenarioAnswer
1 service processes each messageQueue
Multiple services need each messageTopic + subscriptions
No data loss on consumer crashPeek-lock + complete()/abandon()
Message > 256 KB (Standard)Claim-check pattern (blob + URI)
Messages per user in orderSessions (session_id=userId)
Messages that keep failingDead-letter queue (after max delivery count)
Route to subscription based on attributeSQL filter on ApplicationProperties
๐Ÿ“˜ Unit 9

Azure Functions + Service Bus Trigger

3 min

Service Bus integrates natively with Azure Functions for serverless processing. A function triggers on every new message โ€” scales to zero when queue is empty, scales up automatically under load. Perfect for AI background processing without managing infrastructure.

import azure.functions as func

@app.service_bus_queue_trigger(
    arg_name="msg",
    queue_name="document-processing",
    connection="ServiceBusConnection"
)
def process_document(msg: func.ServiceBusMessage):
    doc_data = msg.get_body().decode('utf-8')
    # process document, generate embedding, store in vector DB
    return
๐Ÿ“จ
Module Cheatsheet

Azure Service Bus

25โ€“30% PDF

๐Ÿ”‘ Key Facts

  • Queue โ€” Point-to-point โ€” ONE consumer processes each message
  • Topic + Subscriptions โ€” Pub/Sub โ€” ALL subscriptions get a copy (fan-out)
  • Peek-lock โ€” Lock โ†’ Process โ†’ complete() or abandon() โ€” no message loss
  • Receive-and-Delete โ€” Deleted on receive โ€” fast but message lost on crash
  • DLQ path โ€” queuename/$deadletterqueue โ€” after max delivery count (default 10)
  • Claim-check pattern โ€” Large payload (>256 KB) โ†’ Blob Storage, send URI in message
  • Sessions โ€” FIFO per session_id โ€” use for per-user conversation ordering
  • SQL filter โ€” Route topic messages by ApplicationProperties key/value

๐Ÿ’ป Commands & Patterns

from azure.servicebus import ServiceBusClient, ServiceBusMessage
from azure.identity import DefaultAzureCredential
client = ServiceBusClient(
  "mynamespace.servicebus.windows.net",
  DefaultAzureCredential())
# Send
with client.get_queue_sender("doc-queue") as s:
  s.send_messages(ServiceBusMessage(
    body='{"doc_id":"123"}', message_id="doc-123",
    application_properties={"priority":"high"}))
# Receive (peek-lock)
with client.get_queue_receiver("doc-queue",max_wait_time=5) as r:
  for msg in r:
    try:
      process(str(msg)); r.complete_message(msg)
    except: r.abandon_message(msg)  # retry
# Claim-check
blob_uri = upload_to_blob(large_content)
s.send_messages(ServiceBusMessage(f'{{"uri":"{blob_uri}"}}'))
Module

Build and Deploy Serverless APIs with Azure Functions

units
๐ŸŽฌ Unit 1

Introduction to Azure Functions

3 min

Azure Functions is serverless compute โ€” code runs in response to events (HTTP, queue messages, timers, blob uploads) without managing servers. For AI apps: trigger on Service Bus, call Azure OpenAI, write results to Cosmos DB โ€” zero infrastructure.

๐Ÿ’ก Exam Tip
Functions exam pillars: 1) HTTP / Timer / Service Bus / Blob / Event Grid triggers 2) Input/output bindings eliminate SDK boilerplate 3) Consumption (cold start, 10-min limit) vs Premium (no cold start, VNet) vs Dedicated 4) Durable Functions fan-out/fan-in 5) Orchestrator must be deterministic.
๐Ÿ“˜ Unit 2

Triggers and Output Bindings

10 min

1. HTTP Trigger

import azure.functions as func
import json

app = func.FunctionApp()

@app.route(route="embed", methods=["POST"])
def embed_text(req: func.HttpRequest) -> func.HttpResponse:
    body = req.get_json()
    embedding = generate_embedding(body.get("text", ""))
    return func.HttpResponse(
        json.dumps({"embedding": embedding}),
        mimetype="application/json"
    )

2. Service Bus Trigger

@app.service_bus_queue_trigger(
    arg_name="msg",
    queue_name="embed-queue",
    connection="ServiceBusConnection"
)
def process_embedding(msg: func.ServiceBusMessage) -> None:
    body = json.loads(msg.get_body().decode())
    embedding = generate_embedding(body["text"])
    store_in_cosmos(body["doc_id"], embedding)
    # Auto-completed on success; dead-lettered on repeated failure
๐Ÿ’ก Exam Tip
Connection string stored in App Settings by name โ€” never hardcoded. Auto-complete on success = no complete() call needed.

3. Timer Trigger (NCRONTAB)

@app.timer_trigger(
    arg_name="timer",
    schedule="0 0 2 * * *"
)
def daily_cleanup(timer: func.TimerRequest) -> None:
    cleanup_old_embeddings()
    # NCRONTAB: {second} {minute} {hour} {day} {month} {dow}

4. Output Binding โ€” No SDK Boilerplate

@app.route(route="process", methods=["POST"])
@app.cosmos_db_output(
    arg_name="doc",
    database_name="ai-db",
    container_name="results",
    connection="CosmosConnection"
)
def process_and_store(
    req: func.HttpRequest,
    doc: func.Out[func.Document]
) -> func.HttpResponse:
    result = process(req.get_json())
    doc.set(func.Document.from_dict(result))
    return func.HttpResponse("Stored", status_code=202)
๐Ÿ’ก Exam Tip
Output bindings = no SDK client, no connection boilerplate. Just doc.set(value). Exam-preferred pattern for "write to Cosmos/Queue from Functions".
๐Ÿ“˜ Unit 3

Hosting Plans

5 min
PlanCold StartVNetMax Duration
ConsumptionYesNo10 min
PremiumNo (pre-warmed)YesUnlimited
DedicatedNoYesUnlimited
โš ๏ธ Common Gotcha
VNet integration (private endpoints to Cosmos/Redis/KV) requires Premium or Dedicated. Consumption = no VNet, 10-minute timeout. Long AI jobs need Premium.
๐Ÿ“˜ Unit 4

Durable Functions โ€” Fan-Out / Fan-In

7 min
import azure.durable_functions as df

@app.orchestration_trigger(context_name="context")
def embedding_orchestrator(context: df.DurableOrchestrationContext):
    docs = context.get_input()
    # Fan-out: embed all docs in parallel
    tasks = [context.call_activity("EmbedDoc", d) for d in docs]
    # Fan-in: wait for all
    embeddings = yield context.task_all(tasks)
    yield context.call_activity("StoreAll", embeddings)
    return f"Done: {len(embeddings)} docs"

@app.activity_trigger(input_name="doc")
def embed_doc(doc: dict) -> list:
    return generate_embedding(doc["content"])
โš ๏ธ Common Gotcha
Orchestrator must be deterministic โ€” no datetime.now(), no random, no direct external calls. All side effects go through call_activity().
๐Ÿงช Unit 5

Exercise

20 min
  1. Create a Function App (Python 3.11, Consumption plan)
  2. Add an HTTP trigger that returns embeddings for POSTed text
  3. Add a Service Bus trigger consuming from embed-queue
  4. Use a Cosmos DB output binding โ€” no SDK code needed
  5. Deploy with func azure functionapp publish my-app
๐Ÿ Unit 6

Summary

2 min

Azure Functions: HTTP triggers for REST APIs, Service Bus triggers for reliable queue processing, Timer triggers for scheduled jobs. Output bindings eliminate SDK boilerplate. Durable Functions: orchestrator + activities for fan-out/fan-in parallel AI workloads. Orchestrator must be deterministic. Premium plan = no cold starts + VNet for private endpoints.

๐Ÿง 

Quick Quiz

5 questions โ€” test your understanding before moving on

Finished reading this module? Mark it complete to track your progress.

Frequently Asked Questions

What percentage of the AI-200 exam covers Connect to and Consume Azure Services? +

Domain 3 (Connect to and Consume Azure Services) accounts for 20โ€“25% of the AI-200 exam. Integrate Backend Services for AI Solutions topics like Azure Service Bus and Azure Event Grid are actively tested. Study all official skill objectives listed in the module header above.

Is Service Bus, Event Grid & Functions on the AI-200 exam? +

Yes. Integrate Backend Services for AI Solutions is part of Domain 3 in the official AI-200 skill outline, weighted at 20โ€“25%. The key services tested are Azure Service Bus, Azure Event Grid, Azure Functions. Review the code examples and exam tips in this module for targeted prep.

How do I practice Service Bus, Event Grid & Functions hands-on? +

The best approach is to create a free Azure account and follow the code examples in this module step-by-step. The official Microsoft Learn sandbox for Course AI-200T00-A also provides free lab environments for Azure Service Bus and related services.