Azure Integration Services Pipeline
Build an event-driven order system with API Management, Service Bus, and Event Grid.
Introduction
30 Second Summary
When you order something online, dozens of systems coordinate behind the scenes. The payment processor, inventory tracker, and shipping service all need to communicate reliably without stepping on each other.
In this project, you will build an event-driven order notification system using five Azure Integration Services that work together to process orders securely and reliably.
What You'll Build
You'll create a complete order processing pipeline where an API Management gateway receives requests, a Service Bus message broker ensures reliable delivery, and an Event Grid event system broadcasts notifications to multiple subscribers.
By the end of this project, you'll have:
- A fully connected integration pipeline using API Management, Service Bus, Event Grid, Logic Apps, and Azure Functions.
- Hands-on experience with enterprise patterns like API gateways, message queuing, and event-driven pub/sub.
- An architectural decision framework for choosing the right integration service for any scenario.
- Secret Mission: Build a dead-letter queue handler that catches failed messages and sends alert notifications.
Are there any prerequisites?
You'll need an active Azure free subscription. You should also have basic familiarity with Logic Apps and Azure Functions. This project focuses on the integration services that connect them together.
Explore Azure Integration Services Concepts
Before you create any resources, you need a mental map of the services you'll wire together. Each of the five Azure Integration Services solves a specific problem in distributed systems.
In this step, you'll build the conceptual foundation for API Management, Service Bus, and Event Grid. You'll learn when to reach for each one and why your order processing pipeline uses all three.
In this step, get ready to:
- Understand API Management as a secure front door for your APIs.
- Understand Service Bus for reliable, decoupled messaging between services.
- Understand Event Grid for broadcasting events to multiple subscribers.
Understand what API Management solves
Imagine you have 15 backend microservices. Without a central gateway, every client (mobile app, partner, web app) needs to know the exact URL of each service.
Each client handles authentication differently, and you have no central way to monitor, rate-limit, or version your APIs. API Management is your "front door" that provides a single entry point for all consumers.
What are the core API Management concepts?
API Management has five building blocks you'll work with throughout this project.
- API Gateway: the runtime component that sits between callers and your backends, proxying every request.
- Products: bundles of APIs offered to developers. For example, a "Starter" product with rate limits and an "Unlimited" product for premium partners.
- Subscriptions: keys that grant access to products. Every API call requires a subscription key in the header.
- Policies: XML-based rules applied at inbound, backend, outbound, or on-error phases. Examples include rate limiting, JWT validation, and response caching.
- Developer Portal: an auto-generated website where API consumers discover and test your APIs.
When should I NOT use API Management?
If you have a single internal API with no external consumers, no need for rate limiting, and no versioning requirements, calling your Azure Function or App Service directly is simpler.
Use API Management when you need: external partners consuming your APIs, rate limiting per consumer, API versioning and deprecation, or governing AI/LLM API access.
API Management has multiple pricing tiers: Developer, Basic, Standard, Premium, and Consumption.
Why the Consumption tier for this project?
The Consumption tier is serverless, scales automatically, and bills per execution. It costs $0 for the first 1 million calls per month.
It also provisions in seconds. Other tiers can take 30 to 40 minutes or more to create and activate. For a learning project with limited time, Consumption is the correct choice.
One trade-off: the Consumption tier does not include a developer portal. If you wanted to explore that feature, you'd need the Developer tier.
Understand how Service Bus enables reliable messaging
Consider this scenario: your order API calls the inventory service directly. What happens when the inventory service is down for maintenance at 2 AM?
Orders fail. Customers get errors. Revenue is lost. Service Bus breaks this temporal coupling by introducing a message broker between services.
The sender puts a message in a queue and moves on. The receiver processes it when ready. If the receiver is down, messages wait safely in the queue.
What are the core Service Bus concepts?
- Namespace: a container for all messaging entities, like a database server hosts databases.
- Queues: point-to-point messaging. One message, one consumer. Think "order processing pipeline."
- Topics and Subscriptions: publish/subscribe messaging. One message, many consumers. Each subscription receives a copy of each topic message.
- Peek-Lock: a two-stage receive mode. The message is locked while you process it. If processing fails, the message reappears for retry. The alternative, Receive-and-Delete, removes the message immediately.
- Dead-Letter Queue (DLQ): where messages go when they cannot be processed after max retry attempts. Your safety net for messages that would otherwise be lost.
- Sessions: enable FIFO guarantee even with multiple consumers. Messages with the same session ID go to the same consumer in order.
Why the Standard tier for Service Bus?
The Basic pricing tier does not support topics and subscriptions. Since this project demonstrates pub/sub messaging, you need the Standard tier.
Standard tier costs $0.0135/hour with the first 13 million operations per month included. For a learning project, this will cost cents at most.
When should I use Service Bus vs. simpler alternatives?
Use Service Bus when you need guaranteed delivery (cannot lose messages), message ordering (FIFO with sessions), messages over 64KB (up to 256KB on Standard), pub/sub with filtering (topics), or transaction support.
Use Azure Queue Storage instead if cost is your primary concern and your needs are basic. Queue Storage costs roughly $0.0004 per 10,000 operations but lacks dead-letter queues and ordering.
Understand Event Grid and the full architecture pattern
Traditional polling wastes resources: "Has anything changed? No. Has anything changed? No. Has anything changed? Yes!"
Event Grid flips this model. When something changes, it tells subscribers immediately. It is a fully managed event routing service that connects event sources to event handlers.
What are the core Event Grid concepts?
- Topics: endpoints where events are published. System topics are built-in events from Azure services (e.g., "blob uploaded to Storage"). Custom topics are your application's own events (e.g., "order completed").
- Event Subscriptions: rules that route events from a topic to a handler. Can include filters for event type, subject prefix, or data fields.
- Event Handlers: destinations for events. These include Azure Functions, Logic Apps, webhooks, Service Bus queues, Event Hubs, and Storage queues.
- Retry and Dead-letter: failed deliveries retry with exponential backoff. After max retries, events go to a dead-letter container.
What is the key difference between Event Grid and Service Bus?
Service Bus is for commands ("process this order"). Event Grid is for events ("something happened").
Commands require guaranteed delivery. Events are notifications that the world changed.
Think of it this way: Event Grid is like a news broadcast ("breaking news: earthquake happened"). Service Bus is like a postal service ("deliver this package to exactly one recipient, get a signature").
Event Grid Basic tier includes 100,000 free operations per month. For this learning project, you will stay well within that free allowance.
How do all five services connect in this project?
Your order processing pipeline follows a common enterprise pattern: API Gateway, then Reliable Queue, then Process, then Broadcast Event.
- API Management: the external-facing gateway. Validates requests, applies rate limits, logs analytics.
- Logic Apps: orchestrates the workflow. Receives the validated request and routes it onward.
- Service Bus: ensures the order message is reliably processed even if the processor is temporarily down.
- Azure Functions: custom code that picks up and processes the message from the queue.
- Event Grid: after processing succeeds, broadcasts "order processed" to multiple interested parties (notifications, analytics, inventory).
Your architectural decision framework
- Need a secure API front door? Use API Management.
- Need reliable, ordered message delivery between services? Use Service Bus.
- Need to broadcast "something happened" to many consumers? Use Event Grid.
- Need to orchestrate a multi-step workflow visually? Use Logic Apps.
- Need custom code execution triggered by events? Use Azure Functions.
You now have the conceptual foundation for all three services. Next up, you'll create the Azure resources and start wiring them together into a working pipeline.
Set Up the Foundation
You now have a solid mental model of what API Management, Service Bus, and Event Grid each do. Time to turn that knowledge into real, running infrastructure.
In this step, you will create the core Azure resources that form the backbone of your order processing pipeline. Think of it as laying the plumbing before connecting the pipes.
In this step, get ready to:
- Create a resource group to hold all your integration resources.
- Create a Service Bus namespace with a queue and a topic.
- Create an Event Grid custom topic for event routing.
Create a resource group
A resource group is a logical container that holds related Azure resources together. Placing everything in one group makes it easy to manage and delete all resources at the end of the project.
- Switch to your Azure Cloud Shell (PowerShell) session in the Azure Portal.
- Create your resource group by running this command:
New-AzResourceGroup -Name rg-integration-lab -Location eastus
What does this command do?
- `New-AzResourceGroup` is the PowerShell cmdlet for creating a new resource group.
- `-Name rg-integration-lab` sets the name of the group. All resources you create in this project will go here.
- `-Location eastus` places the group in the East US region. You will use the same region for all resources to keep things simple and reduce latency.
- Confirm the output shows ProvisioningState: Succeeded along with the resource group name rg-integration-lab.
Seeing an error?
- Make sure your Cloud Shell is set to PowerShell mode, not Bash. You can toggle this from the dropdown at the top-left of the Cloud Shell pane.
- If you see a subscription-related error, confirm your Azure free subscription is still active. It expires on June 18, 2026.
Help me troubleshoot my resource group creation error.
Create the Service Bus namespace and queue
Your Service Bus namespace is the container that will hold the queue and topic for your order processing pipeline. You need the Standard tier because the Basic tier does not support topics and subscriptions.
- In the Azure Portal, click All services in the left sidebar.
- Select Integration, then click Service Bus.
- Click + Create on the toolbar.
Fill in the creation form with these values:
- In the Resource group dropdown, select rg-integration-lab.
- In the Namespace name field, enter a unique name such as sb-orders- followed by your name (e.g., sb-orders-jordan). This name must be globally unique across Azure.
- Set the Location to East US.
- Set the Pricing tier to Standard.
- Click Review + create, then click Create.
Why Standard tier?
The Basic pricing tier does not support topics and subscriptions. Since your pipeline uses a topic to fan out order events to multiple subscribers, you need at least the Standard tier.
Standard costs $0.0135/hour as a base charge, with the first 13 million operations per month included. For this learning project, the total cost will be just a few cents.
Wait for the deployment to complete, then navigate to your new Service Bus namespace resource.
Now create the queue that will buffer order messages:
- On your Service Bus Namespace page, expand Entities in the left navigation menu.
- Select Queues.
- On the toolbar, click + Queue.
- In the Name field, enter orders.
- Leave all other values at their defaults.
- Click Create.
Next, create the topic and subscription for pub/sub messaging:
- In the left navigation under Entities, select Topics.
- On the toolbar, click + Topic.
- In the Name field, enter order-events.
- Leave all other values at their defaults.
- Click Create.
Now add a subscription to the topic:
- Click the order-events topic you just created to open it.
- On the toolbar, click + Subscription.
- In the Name field, enter notification-sub.
- Leave all other values at their defaults.
- Click Create.
Queues vs. topics: what's the difference?
A queue delivers each message to exactly one consumer. This is perfect for the orders queue because you want each order processed once.
A topic with subscriptions delivers a copy of each message to every subscriber. The order-events topic will let multiple downstream systems (notifications, analytics) each get their own copy of the event.
- Confirm your setup by checking the Entities section in the left navigation. You should see Queues (1) and Topics (1) listed.
Don't see your queue or topic?
- Make sure the deployment of your Service Bus namespace completed before you tried to create entities. Look for a "Deployment succeeded" notification.
- If the namespace name was rejected, ensure it is 6-50 characters, contains only letters, numbers, and hyphens, starts with a letter, and ends with a letter or number.
Help me fix my Service Bus setup.
Create the Event Grid custom topic
The Event Grid custom topic gives your pipeline a place to publish "order processed" events. Multiple subscribers can then react to those events independently.
- In the Azure Portal search bar at the top, type Event Grid Topics and select Event Grid Topics from the results.
- Click + Create on the toolbar.
Fill in the creation form:
- Select your Subscription from the dropdown.
- In the Resource group dropdown, select rg-integration-lab.
- In the Name field, enter a unique name such as eg-orders- followed by your name (e.g., eg-orders-jordan). The name must be 3-50 characters, using only letters, numbers, and hyphens.
- Set the Region to East US.
- Click Review + create, then click Create.
- Wait for the deployment notification to show success. Then click Go to resource to confirm your Event Grid topic is live.
What is a custom topic?
Azure Event Grid has two types of topics. System topics fire automatically when Azure services change (e.g., a blob is uploaded). Custom topics are endpoints that your own code publishes events to.
In this project, your Azure Function will publish an "order processed" event to this custom topic after it finishes processing a message from Service Bus.
Topic creation failed?
- Check that your topic name is between 3 and 50 characters, uses only letters, numbers, and hyphens, and is DNS-unique.
- Confirm you selected the rg-integration-lab resource group and East US region.
Help me troubleshoot my Event Grid topic creation.
Your foundation is set. You have a resource group, a Service Bus namespace with a queue and topic, and an Event Grid custom topic ready to go. Next up, you will build the API layer with API Management to create the secure front door for your order processing system.
Build the API Layer with API Management
Your integration infrastructure is in place. You have a Service Bus queue ready to buffer messages and an Event Grid topic ready to broadcast events.
Now you need a secure front door for your order system. API Management acts as a gateway that sits between external callers and your backend services. It validates requests, applies rate limits, and logs analytics before anything reaches your Logic App or Function.
In this step, get ready to:
- Create an API Management instance on the Consumption tier.
- Define a blank API with a POST operation for placing orders.
- Apply a rate limit policy to protect your backend from overuse.
Create the API Management instance (Consumption tier)
The Consumption tier is serverless and provisions in seconds. Other tiers can take 30 to 40 minutes to create. For a learning project, Consumption is the right choice because it costs nothing for the first 1 million calls per month and scales automatically.
- In the Azure Portal, select Create a resource from the home page.
- Select Integration, then select API Management.
- On the Basics tab, configure the following settings:
- Resource group: select rg-integration-lab.
- Region: select East US.
- Resource name: enter a unique name (for example, apim-orders-yourname). This name forms your gateway URL as yourname.azure-api.net and cannot be changed later.
- Organization name: enter your name or a company name.
- Administrator email: enter your email address.
- Pricing tier: select Consumption from the dropdown.
- Select Review + create, then select Create.
- Wait for the deployment to complete. The Consumption tier typically provisions in under a minute.
- Once deployed, select Go to resource to open your API Management instance.
Why Consumption tier instead of exposing the Logic App directly?
API Management gives you subscription key authentication so no one can call your API without a key. It also provides rate limiting to protect against abuse, request and response logging, and a clean API surface that is independent of your backend implementation.
If you swap the Logic App for a Function later, consumers do not notice. The gateway URL stays the same.
Deployment taking longer than expected?
Make sure you selected the Consumption pricing tier. Other tiers (Developer, Basic, Standard, Premium) take 30 to 40 minutes to provision. If you accidentally chose a different tier, cancel the deployment and start again with Consumption selected.
Also confirm your resource name is unique across Azure. If the name is already taken, you will see a validation error.
help me troubleshoot my API Management deployment
Import a blank API and apply a rate limit policy
With your instance ready, you will create an API definition and add an operation that accepts order requests. Then you will apply a policy to limit how many calls a single consumer can make per minute.
- In your API Management instance, select APIs in the left menu.
- Select + Add API, then select HTTP (Manually define an HTTP API) to create a blank API.
- Fill in the following fields:
- Display name: Order API.
- Name: order-api.
- Web service URL: leave this as a placeholder for now (for example, https://placeholder). You will update it after creating the Logic App in the next step.
- API URL suffix: orders.
- Select Create.
Now add an operation to the API that accepts order placement requests.
- With your Order API selected, select + Add operation.
- Set Display name to Place Order.
- Set the HTTP verb to POST.
- Set the URL to /place.
- Select Save.
Next, apply a rate limit policy so no single consumer can overwhelm your order system.
- Select your Place Order operation in the operations list.
- In the Inbound processing section, select + Add policy.
- Select Limit call rate per subscription (the rate-limit policy).
- Set the number of calls to 10.
- Set the renewal period (in seconds) to 60.
- Select Save to apply the policy.
What does this rate limit policy do?
The rate-limit policy limits calls on a per-subscription basis. Each consumer (identified by their subscription key) can make at most 10 requests within any 60-second window. If they exceed the limit, API Management returns a 429 Too Many Requests response.
This protects your backend from being overwhelmed during traffic spikes. In production, you would also add JWT validation, request transformation, CORS policies, and caching.
What is a policy in API Management?
Policies are XML-based rules applied at different phases of a request lifecycle: inbound, backend, outbound, or on-error. Each phase lets you transform, validate, or control traffic at a specific point in the request flow.
The rate limit you just added runs during the inbound phase. This means it blocks excess requests before they ever reach your backend service.
Don't see the rate limit policy option?
Make sure you have your Place Order operation selected (not All operations) before clicking + Add policy. If you still do not see the option, select the Other policies tile to open the XML code editor and add the rate-limit element manually in the inbound section.
help me add a rate limit policy in API Management
Test the API and understand the request flow
Before wiring up a real backend, explore how API Management handles requests. The Test console lets you see exactly what the gateway does with each call.
- In your API Management instance, select APIs in the left menu.
- Select Order API, then select the Place Order operation.
- Select the Test tab at the top of the operation panel.
Notice three things in the test console:
- The subscription key (Ocp-Apim-Subscription-Key header) is automatically included. Every API call requires this key for authentication.
- The request URL follows the pattern https://your-apim-name.azure-api.net/orders/place. This is your gateway URL with the API suffix and operation path appended.
- The gateway validates the subscription key and applies your rate limit policy before forwarding the request to the backend URL.
Why is the gateway pattern powerful?
Your backend never handles authentication, rate limiting, or request transformation. It receives only clean, validated requests. If you later swap the Logic App backend for an Azure Function, the consumer's URL and subscription key stay the same.
This separation of concerns is what makes API Management essential for enterprise architectures. The gateway absorbs cross-cutting concerns so each backend can focus purely on its business logic.
The test will return an error right now
If you select Send in the Test tab, you will get an error because the backend URL is a placeholder. This is expected. You will update it to point to your Logic App in the next step.
Your API gateway is configured and protected with a rate limit. Next up, you will build the Logic App workflow and wire it to Service Bus so that orders flow reliably through the entire pipeline.
Connect Service Bus for Reliable Messaging
Your API Management gateway is configured and ready to validate incoming requests. The next challenge is making sure those requests survive failures downstream.
In this step, you will connect the pieces between API Management and Service Bus by building the middle layer. You will create an Azure Function that automatically processes messages from the queue, a Logic App that orchestrates the workflow, and then wire everything together so the full flow works end to end.
In this step, get ready to:
- Create an Azure Function triggered by Service Bus queue messages.
- Build a Logic App workflow with an HTTP trigger and Service Bus action.
- Wire API Management's backend URL to the Logic App.
Create an Azure Function triggered by Service Bus
When a message lands in a Service Bus queue, something needs to pick it up and process it. An Azure Function with a queue trigger does exactly that. It fires automatically whenever a new message arrives.
- In the Azure Portal, select Create a resource from the top menu.
- In the New page, select Function App.
- Under Select a hosting option, select Consumption, then click Select.
Why Consumption plan?
The Consumption plan is serverless. You only pay when your Function runs, and it scales automatically. For our learning project, this keeps costs at zero for the first million executions per month.
- On the Basics page, fill in the following settings:
- Set Resource Group to rg-integration-lab.
- Set Function App name to a globally unique name like func-order-processor-yourname (replace yourname with your own name).
- Set Runtime stack to Node.js (or .NET if you prefer). Choose a runtime that supports in-portal editing so you can create functions directly in the Portal.
- Set Region to East US.
- Accept the default Windows operating system.
- Accept defaults on the remaining tabs (Storage, Monitoring).
- Click Review + create, review your settings, then click Create.
- Wait for the Deployment succeeded notification, then click Go to resource.
Now create the Function itself inside your new Function App.
- On the Function App Overview page, select + Create under Functions.
- Under Select a template, scroll down and choose the Azure Service Bus Queue trigger template.
- In Template details, set the New Function name to ProcessOrder.
- For Service Bus connection, click New and select your Service Bus namespace from the list.
- Set Queue name to orders.
- Click Create.
What does this accomplish?
Your ProcessOrder Function now has a live connection to the orders queue. Whenever a message lands in that queue, Azure automatically fires this Function to process it. This is the competing consumers pattern. If you scale to multiple Function instances, each message is still processed by exactly one instance.
Why Service Bus instead of calling the Function directly?
Three reasons make Service Bus the better choice here. First, resilience. If the Function is down during deployment or scaling, messages wait safely in the queue. Second, load leveling. During a flash sale, thousands of orders can queue up while the Function processes them at its own pace.
Third, retry semantics. Service Bus has built-in retry with dead-letter support. A direct HTTP call simply fails.
Don't see the + Create button?
In-portal function creation is only supported for certain runtime stacks (JavaScript, Python, PowerShell, TypeScript) on the Consumption plan with Windows. If you chose .NET, you may need to use VS Code or Visual Studio to deploy the function code.
help me troubleshoot creating a Function in the Azure Portal
Build the Logic App workflow
The Logic App serves as the orchestrator. It receives HTTP requests, sends the order to Service Bus, and returns a response to the caller. This keeps the workflow visible and editable without writing code.
- In the Azure Portal, select Create a resource.
- Search for Logic App and select it.
- On the Create Logic App pane, set the following:
- Set Logic App name to la-order-orchestrator.
- Set Resource Group to rg-integration-lab.
- Set Region to East US.
- Under Plan, set Plan type to Consumption.
- Click Review + create, then click Create.
- After deployment completes, click Go to resource.
Now open the Logic App designer and build the workflow.
- On the Logic App resource page, scroll down to Start with a common trigger and select When a HTTP request is received.
- In the trigger's Request Body JSON Schema field, paste the following schema:
{"type":"object","properties":{"orderId":{"type":"string"},"customerName":{"type":"string"},"amount":{"type":"number"}}}
What does this schema do?
This JSON schema tells the Logic App what shape of data to expect in the HTTP request body. It defines three fields: orderId (string), customerName (string), and amount (number). The Logic App uses this schema to parse the incoming data and make it available as dynamic content for later steps.
Next, add the Service Bus action.
- Click + New step below the trigger.
- Search for Service Bus and select the Send message action.
- In the connection pane, select Access Key as the authentication type.
- Provide a Connection Name (any descriptive name, like sb-orders-connection).
- Paste the connection string from your Service Bus namespace (find it under Shared access policies in your namespace's settings).
- Click Create to save the connection.
- Set Queue/Topic name to orders.
- In the Content field, select the HTTP request body from the dynamic content list (this passes the full incoming order JSON to the queue).
Finally, add a Response action so callers get a confirmation.
- Click + New step again.
- Search for Response and select the Response action.
- Set Status Code to 202.
- In the Body field, enter a JSON response confirming the order was received. Include the orderId from the trigger's dynamic content.
- Click Save in the designer toolbar.
Why HTTP 202 and not 200?
HTTP 202 means "Accepted". It tells the caller that the request was received and will be processed asynchronously. This is the correct response when the actual processing happens later (via the Service Bus queue), not immediately within this workflow.
- After saving, the designer shows the HTTP POST URL at the top of the trigger. Copy this URL and save it somewhere temporarily. You will need it in the next substep.
Don't see the HTTP POST URL?
The URL only appears after you save the workflow. Click Save in the designer toolbar, then expand the trigger to see the generated URL.
help me find my Logic App HTTP trigger URL
Wire API Management to the Logic App
The last piece of the puzzle is connecting API Management's backend to your Logic App. This closes the loop so requests flow from the client all the way through to the Service Bus queue.
- Navigate back to your API Management instance in the Azure Portal.
- In the left menu, select APIs, then select Order API.
- Select the Place Order operation.
- Click the Design tab, then select the pencil icon in the Backend section.
- Update the Web service URL to the Logic App HTTP trigger URL you copied in the previous substep.
- Click Save.
What is the full request flow now?
The complete pipeline is now connected. A client sends a POST request to your API Management endpoint. API Management validates the subscription key, applies the rate limit policy, then forwards the request to the Logic App.
The Logic App receives it, sends the order message to the Service Bus orders queue, and returns HTTP 202 to the caller. The ProcessOrder Function picks up the message from the queue and processes it.
Getting a 404 or 500 when testing?
Make sure the Logic App URL in the backend field includes the full path with the query parameters (the SAS token). The URL should start with https:// and contain sig= near the end.
Also confirm you saved your changes in API Management after pasting the URL.
help me troubleshoot my API Management backend connection to the Logic App
Your integration pipeline is now fully wired. Next up, you will add Event Grid to broadcast events after an order is processed, enabling multiple downstream systems to react independently.
Add Event-Driven Notifications with Event Grid
Your order processing pipeline reliably moves messages from the API gateway through the queue and into your Function for processing. But right now, after processing completes, nothing else in your system knows about it.
In a real e-commerce system, a successfully processed order needs to trigger multiple downstream actions simultaneously: send a customer confirmation email, update inventory counts, log analytics. Event Grid solves this by broadcasting a "something happened" notification to all interested subscribers at once.
In this step, get ready to:
- Configure your Function to publish events to Event Grid after processing an order.
- Create event subscriptions that route events to multiple consumers with filtering.
- Test the complete end-to-end flow from API Management through to Event Grid subscribers.
Publish events from the Function to Event Grid
After your ProcessOrder Function successfully processes a message from the Service Bus queue, it should announce "order processed" to the rest of the system. You will publish this announcement as an event to your Event Grid custom topic.
First, you need the Event Grid topic's endpoint URL and access key so your Function knows where to send events.
- In the Azure Portal, search for Event Grid Topics in the top search bar and select it.
- Select your Event Grid custom topic (the one you created earlier, e.g., eg-orders-yourname).
- On the Overview tab, find the Topic Endpoint value. Copy it and save it somewhere temporarily.
- Select the Access keys tab on the same page. Copy Key 1 and save it temporarily alongside the endpoint.
What are these values for?
The topic endpoint is the URL your Function sends events to. The access key authenticates the request using the aeg-sas-key header. Together, they let your Function securely publish events to Event Grid.
Now you need to understand the event payload structure your Function will send. Every event published to Event Grid follows a specific schema.
- Review the following Event Grid event schema that your Function will publish after processing an order:
[{
"id": "unique-id",
"eventType": "Order.Processed",
"subject": "orders/order123",
"eventTime": "2026-06-10T12:00:00Z",
"data": {
"orderId": "order123",
"customerName": "John Doe",
"amount": 99.99,
"status": "processed"
},
"dataVersion": "1.0"
}]
What does each field do?
- id is a unique identifier for the event (typically a GUID).
- eventType categorises the event. Subscribers use this to filter which events they care about.
- subject provides context about the event source (here, the specific order).
- data contains the actual payload. Any well-formed JSON is valid here.
- dataVersion lets consumers know which schema version the data uses.
Next, update your ProcessOrder Function to publish this event after it processes a message.
- Navigate to your Function App in the Azure Portal.
- Select Functions in the left menu, then select your ProcessOrder Function.
- Select Code + Test in the left menu to open the code editor.
- Add logic that makes an HTTP POST request to your Event Grid topic endpoint URL. Include the aeg-sas-key header set to your topic access key.
- The request body should follow the event schema above, with dynamic values from the Service Bus message (orderId, customerName, amount) and status set to processed.
- Select Save at the top of the code editor.
Why Event Grid here instead of another Service Bus message?
Multiple subscribers need this notification (analytics, email, inventory). You don't need guaranteed ordering or persistence for notifications. Event Grid provides push-based, near-instant delivery to all subscribers simultaneously.
This event is a notification ("this happened"), not a command ("do this"). Event Grid handles notifications. Service Bus handles commands.
Function not saving?
Make sure you selected the correct Function (ProcessOrder) and that you're in the Code + Test view. If you see a read-only notice, check that your Function App is running and not in a stopped state.
help me troubleshoot why my Azure Function code won't save in the portal Code + Test editor
Create event subscriptions for multiple consumers
Your Function can now publish events. The next step is telling Event Grid where to deliver them. Event subscriptions define the routing rules.
You will create two subscriptions on your Event Grid topic to demonstrate the fan-out pattern: one event triggers multiple independent handlers, each with its own filtering logic.
- Navigate back to your Event Grid custom topic in the Azure Portal.
- Select + Event Subscription on the toolbar.
Configure the first subscription (notification handler):
- Enter order-notification as the Name.
- For Endpoint Type, select Azure Function (or Web Hook if you prefer).
- Select Configure an endpoint and choose a target Function or provide a webhook URL.
- Select the Filters tab.
- Under Event Types, add Order.Processed to filter only for processed order events.
- Select Create.
Now create the second subscription (analytics queue) with an advanced filter:
- Return to your Event Grid topic page and select + Event Subscription again.
- Enter order-analytics as the Name.
- For Endpoint Type, select Storage Queue.
- Select Configure an endpoint and choose a Storage Account queue as the destination.
- Select the Filters tab.
- Under Event Types, add Order.Processed.
- In the ADVANCED FILTERS section, select Add new filter.
- Set the Key to data.amount, the Operator to Number Greater Than, and the Value to 50.
- Select Create.
What is the fan-out pattern?
Fan-out means one event gets delivered to multiple independent handlers. The order-notification subscription receives all processed orders. The order-analytics subscription only receives high-value orders (amount > 50) using the advanced filter on the data.amount field.
Each subscriber is independent. If one fails, the other still receives its events. This is the power of event-driven architecture.
Verify that both subscriptions appear on your Event Grid topic page. You should see order-notification and order-analytics listed under Event Subscriptions.
Event subscription creation failing?
Make sure your endpoint is accessible and can respond to the Event Grid validation handshake. For webhook endpoints, they must return a 200 response to the validation request. For Azure Function endpoints, ensure the Function App is running.
help me fix my Event Grid event subscription that's failing to create
Test the end-to-end flow
Every piece of the integration pipeline is now connected. It is time to send a test order through the entire system and verify each service handles it correctly.
- Open Azure Cloud Shell (PowerShell) from the top menu bar of the Azure Portal.
- Send a test POST request to your API Management endpoint using the following command (replace the placeholders with your actual values):
# Get your API Management subscription key from the APIM portal
# Replace the URL with your actual APIM endpoint
$headers = @{
"Ocp-Apim-Subscription-Key" = [[APIM_KEY="your APIM subscription key"]]
"Content-Type" = "application/json"
}
$body = @{
orderId = "order-001"
customerName = "Jane Smith"
amount = 75.00
} | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "https://[[APIM_NAME="your-apim-name"]].azure-api.net/orders/place" -Headers $headers -Body $body
What does this command do?
- The Ocp-Apim-Subscription-Key header authenticates the request with API Management.
- The JSON body contains order data that flows through the entire pipeline.
- The amount of 75.00 is deliberately above 50 so both event subscriptions (notification AND analytics) will receive the event.
Now trace the event through each service to verify the complete path:
- Navigate to your Logic App (la-order-orchestrator). Select Overview and check the Run history section. You should see a successful run triggered by your test request.
- Navigate to your Service Bus namespace. Select Queues and then the orders queue. Check the metrics to confirm a message was received and processed.
- Navigate to your Function App. Select the ProcessOrder Function and check Monitor to see the invocation log.
- Navigate to your Event Grid custom topic. Select Metrics and look for Published Events and Matched Events to confirm the event was published and delivered to subscribers.
What is the complete request path?
API Management (validates subscription key, applies rate limit) then forwards to Logic App (orchestrates the workflow) which sends to Service Bus queue (buffers reliably) which triggers the Function (processes the order) which publishes to Event Grid (broadcasts to subscribers).
Each service solves a distinct problem in the chain. Remove any one of them and you lose a specific capability: security, orchestration, reliability, processing, or broadcast notification.
Not seeing events in Event Grid metrics?
Check that your ProcessOrder Function ran successfully by examining its Monitor tab. If the Function ran but no event appeared, verify that the topic endpoint URL and access key are correct in your Function code. Also confirm the event payload matches the expected JSON schema (array of event objects).
help me debug why my Azure Function is not publishing events to Event Grid after processing a Service Bus message
Your integration pipeline is fully operational. You have a working example of the enterprise pattern: API Gateway, Reliable Queue, Process, and Broadcast Event. Next up, you will tackle a real production concern in the Secret Mission.
Secret mission
Dead-Letter Queue Handler
In production, messages that fail processing end up in the dead-letter queue. Without monitoring, you'll silently lose orders. Build a DLQ handler Function and an alerting Logic App that catches failed messages before customers notice.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. The main cost driver is the Service Bus Standard tier at approximately $0.0135/hour. Your Azure free subscription expires on June 18, 2026, so full cleanup is recommended if you are done experimenting.
Cost warning
The Service Bus Standard tier incurs a base charge of approximately $0.0135/hour (roughly $10/month) even when idle. If you leave your resources running beyond the free subscription period, this charge applies. The other Consumption-tier resources (API Management, Logic Apps, Functions, Event Grid) have generous free allowances and are unlikely to cost anything for a learning project.
Resources you used:
- API Management instance (Consumption tier) in rg-integration-lab.
- Service Bus namespace (Standard tier) with the orders queue, order-events topic, and notification-sub subscription.
- Event Grid custom topic with order-notification and order-analytics event subscriptions.
- Function App (func-order-processor-yourname) with ProcessOrder and ProcessDeadLetter functions.
- Logic App la-order-orchestrator (order workflow).
- Logic App la-dlq-monitor (dead-letter queue monitor).
- Resource group rg-integration-lab.
Keep everything running
No action needed. Choose this if you are still actively building or want to experiment further with the integration pipeline.
- Your Service Bus Standard tier will continue to charge approximately $0.0135/hour.
- The la-dlq-monitor Logic App runs every 5 minutes. This accumulates actions over time, but stays within free-tier limits for short experiments.
- All other resources (API Management Consumption, Function App Consumption, Event Grid) have free allowances that cover light usage.
Pause - I'll come back to this later
Remove the biggest cost driver (Service Bus) while keeping the rest of your resources intact for when you return.
- Open Azure Cloud Shell (PowerShell).
- Delete your Service Bus namespace by running the following command (replace the namespace name with yours):
Remove-AzServiceBusNamespace -ResourceGroupName rg-integration-lab -NamespaceName [[SB_NAMESPACE="your Service Bus namespace name"]]
- This removes the namespace along with the orders queue, order-events topic, and all subscriptions inside it.
- Disable the la-dlq-monitor Logic App to stop its scheduled runs. Navigate to the Logic App in the portal and click Disable on the overview page.
- Your remaining resources (API Management, Event Grid, Function App, and the la-order-orchestrator Logic App) stay within free-tier limits when idle.
Delete - I don't want to use this again
Remove all project resources and start fresh. Since all resources live in a single resource group, one command handles everything.
- Open Azure Cloud Shell (PowerShell).
- Delete the entire resource group by running this command:
Remove-AzResourceGroup -Name rg-integration-lab -Force
- This deletes the resource group and every resource inside it: API Management, Service Bus, Event Grid, Function App, and both Logic Apps.
- Confirm the deletion is complete by running:
Get-AzResourceGroup -Name rg-integration-lab
- You should see an error stating the resource group was not found. This confirms all resources have been removed.
Nice Work!
Nice Work!
Nice work! You've just built an enterprise-grade event-driven order notification system using Azure Integration Services.
You've learned how to:
- Configure API Management as a secure gateway with policies, subscription keys, and rate limiting to protect your backend services.
- Connect Service Bus queues and topics for reliable, decoupled messaging between services using the temporal decoupling pattern.
- Broadcast events through Event Grid custom topics with filtered event subscriptions to fan out notifications to multiple consumers.
- Built a dead-letter queue monitoring system that catches failed messages and sends proactive alerts for production resilience.
Ready to quiz yourself?