Connect to and Consume Azure Services
Wire AI back-end services together with Service Bus and Event Grid for messaging, and Azure Functions for serverless APIs.
Azure Service Bus: queues, topics, and dead-letter handling
Service Bus is the durable, ordered message broker of choice for back-end operations that must not be dropped — a classic fit for queuing an AI inference request, a document-processing job, or any workload where "eventually, exactly once effectively" beats "immediately, best effort."
Queues vs. topics
- A *queue* is point-to-point: each message is received and processed by exactly one consumer, ideal for distributing work across a pool of identical workers.
- A *topic* is publish/subscribe: a message sent to the topic is delivered to every *subscription* on it, each of which behaves like its own independent queue. This is the right shape when the same event (say, "document uploaded") needs to trigger several independent downstream processes (indexing, embedding generation, notification) without the publisher knowing about any of them.
- A subscription can have a SQL or correlation *filter*, so only messages matching a condition are delivered to it — letting one topic serve several different consumer types without every consumer having to filter messages itself.
Dead-letter queues
- Every queue and subscription has an associated dead-letter sub-queue (`$deadletterqueue`) where messages land automatically after exceeding `MaxDeliveryCount` failed delivery attempts, expiring (TTL), or being explicitly dead-lettered by application code.
- Dead-lettering exists specifically so a single poison message (one that reliably crashes its consumer) doesn't block the queue forever by being redelivered in an infinite retry loop — it's set aside for separate inspection while healthy messages keep flowing.
- Consumers should use `PeekLock` receive mode (lock a message, process it, then explicitly complete or abandon it) rather than `ReceiveAndDelete` for anything where losing a message on a crash mid-processing is unacceptable — `ReceiveAndDelete` removes the message the instant it's received, before you know processing succeeded.
Common confusion
- A message that keeps failing and is redelivered isn't lost — it's still in the queue being retried — until it's either dead-lettered after too many attempts or its TTL expires. Monitoring dead-letter queue depth is a standard health signal precisely because a growing DLQ means something downstream is systematically broken, not just occasionally slow.
Azure Event Grid: event-driven workflows
Event Grid is built for a different shape of problem than Service Bus: reacting to discrete events from Azure services or your own application, at very high scale and low latency, rather than reliably queuing units of work for guaranteed processing.
Core model
- An event source publishes events to a *topic* (a system topic for built-in Azure resource events, like a new blob landing in storage, or a custom topic for application-defined events).
- An *event subscription* routes matching events from a topic to a handler — a Function, a webhook, Service Bus, Event Hubs, and more.
- A *filter* on a subscription narrows delivery by event type or subject prefix/suffix, so a single topic covering "everything happening in this storage account" can still let a subscriber receive only, say, blob-created events under a specific folder prefix.
Custom events and reliability
- Applications publish custom events in the CloudEvents or Event Grid schema, which is how an AI pipeline stage signals "I finished my part" to whichever downstream stages care, without those stages being hardwired to know about each other.
- Event Grid retries failed deliveries with exponential backoff up to a configurable retry policy, and can be configured with a dead-letter destination (typically a storage container) for events that exhaust their retries — conceptually similar to Service Bus's DLQ, but for events rather than queued work items.
Common confusion
- Event Grid notifies you that something happened; it doesn't guarantee a consumer will process it exactly once, and it isn't a work queue you pull batches from — Service Bus (or Event Grid delivering *into* Service Bus) is the better fit when you need ordered, exactly-once-processed units of work rather than fan-out notifications.
Azure Functions: serverless APIs, triggers, and bindings
Functions is the serverless compute layer that ties the rest of an AI back end together — often the glue code that runs when a queue message arrives, an event fires, or an HTTP request comes in, without you provisioning or managing a server.
Triggers and bindings
- A *trigger* is what causes a function to run — exactly one per function: HTTP request, a new Service Bus message, a new Event Grid event, a Cosmos DB change feed entry, a timer, and others.
- *Bindings* are declarative input/output connections to other services, configured (not hand-coded) so a function can, for example, read a Cosmos DB document and write a Service Bus message without writing SDK connection boilerplate for either — the runtime supplies the connected object or return-value wiring based on configuration.
- Building a serverless API means using the HTTP trigger, with the route, allowed methods, and auth level defined per function; each function effectively becomes one API endpoint without you standing up a web server.
Configuring and deploying function apps
- A function app is the deployment and scaling unit — one or more functions packaged and hosted together, sharing a runtime version, app settings, and (on Consumption or Premium plans) the same automatic, event-driven scaling behavior.
- The hosting plan matters for AI workloads specifically: Consumption scales to zero and is billed per execution but has cold starts and execution time limits; Premium keeps instances warm and supports VNet integration; Functions can also run on Container Apps for full control over the container image, GPU-backed hosting, and scaling that shares KEDA rules with the rest of your Container Apps environment.
- App settings (including Key Vault references, exactly as with App Service) configure connection strings and secrets for a function app's triggers and bindings without embedding them in code.
Common confusion
- A trigger and an input binding sound similar but are different: a trigger starts the function's execution and a function has exactly one; input/output bindings are optional, can be multiple, and only supply or receive data during a run that's already been triggered by something else.