
Azure Event GridAuthorCloudBrum editorial teamLast reviewedReading time~12 minLevelBeginner to advanced
Microsoft Azure · App modernization · Event routing, MQTT and pull delivery
Event Grid is how Azure tells your code that something changed. A blob arrives, a resource is deleted, your own app announces an order, and Event Grid hands the event to the handlers that subscribed. It has grown into two shapes: the original topics that push events over HTTP, and namespaces that add an MQTT broker and pull delivery for queue-style reading. Picking the right shape up front matters, because the tiers, limits and prices differ, and the retry and dead-letter settings decide whether a failed delivery is recovered or quietly dropped.
On this page (17 sections)
Mind map: Azure Event Grid at a glance
Free to share. The downloaded image includes the CloudBrum link.
Key features (summary)
- Events from Azure itselfBlob Storage, resource groups and subscriptions, Key Vault, Container Registry, IoT Hub, Service Bus and many more publish to system topics. You subscribe and write no publisher code.
- Your own events on custom topicsPublish with an HTTP call or an SDK, in the CloudEvents 1.0 format or the older Event Grid schema. Domains manage thousands of topics at once, which suits software that serves many customers.
- Filtering before deliveryA subscription picks event types and a subject prefix or suffix, and advanced filters look inside the data. Handlers get what they asked for, nothing else.
- Plenty of handlersAzure Functions, Logic Apps, Event Hubs, Service Bus queues and topics, Storage queues, Hybrid Connections and any webhook can receive pushed events.
- Pull delivery in namespacesA consumer connects, receives a batch, and acknowledges, releases or rejects each event, like a queue. It chooses the pace, so a slow consumer isn’t flooded.
- An MQTT brokerNamespaces speak MQTT 3.1.1 and 5.0, so devices and apps publish and subscribe to topic spaces, and the messages can be routed on to Azure services.
- Retries and dead-letteringFailed deliveries are retried with exponential backoff until the attempt count or the time to live runs out. Events that never arrive can be written to a Blob Storage container.
- Identity-based accessPublishers and consumers can use Microsoft Entra roles, deliveries can use a managed identity, and topics can be limited to private endpoints and chosen IP ranges.
Basic concepts
- Event
- A small record that something happened. It says what happened and where, not the full state; handlers fetch more if they need it.
- Topic
- The endpoint events are sent to. System topics belong to an Azure service, custom topics belong to you, and partner topics link to a SaaS provider.
- Event subscription
- A rule on a topic: which events, filtered how, delivered where, with which retry and dead-letter settings.
- Event handler
- The destination of a subscription, such as a function, a queue, an Event Hubs hub or a webhook.
- Domain
- A management container for many custom topics under one endpoint, with permissions per topic.
- Namespace
- The container for the Standard tier. It holds namespace topics for HTTP and topic spaces for MQTT, and has its own capacity in throughput units.
- Namespace topic
- A topic inside a namespace. It takes CloudEvents over HTTP and serves them to subscriptions by pull (or push to Event Hubs).
- Topic space
- A set of MQTT topic templates in a namespace. Permission bindings decide which client groups can publish or subscribe to them.
- CloudEvents
- A vendor-neutral event format from the CNCF. Event Grid accepts it everywhere and requires it for namespace topics.
- Throughput unit (TU)
- A pre-bought slice of capacity in a namespace, billed by the hour. More units allow more ingress and egress.
- Push and pull delivery
- In push, Event Grid calls the handler. In pull, the consumer calls Event Grid, locks events, and then acknowledges, releases or rejects them.
- Dead-lettering
- Writing an event to a storage container after delivery failed for good, so it can be inspected and reprocessed.
- Advanced filter
- A condition on a field in the event data, such as data.total greater than 1000. It is evaluated per subscription and counts as an operation.
How to create & configure it
Route storage events and your own events with the Azure CLI
- Choose the shapeBasic topics suit pushing Azure service events and your own events to handlers. Namespaces suit MQTT devices and consumers that want to pull. You can use both in one subscription.
- Create a place for the events to landA storage queue is the simplest handler. Create a second container for events that cannot be delivered.
- Create a system topic for the service you care aboutFor Blob Storage, point a system topic at the storage account. Azure publishes to it without any code from you.
- Subscribe with a filterChoose the event type, a subject prefix such as the container, and a suffix such as the file type, so the handler isn’t woken for every upload.
- Set retries and a dead-letter locationPick the maximum attempts and the time to live that suit the handler, and name the container for failures. Without it, an event that runs out of retries is dropped.
- Create a custom topic for your own eventsUse the CloudEvents schema, subscribe a handler to one event type, and keep the access key out of source control, or turn on Entra access instead.
- Publish and look for the resultA successful publish means Event Grid accepted the event, not that a handler finished. Peek at the queue to see the delivery.
- Read the topic’s metricsFailed delivery attempts, dropped events and dead-lettered events tell you what the portal hides.
- Add a namespace when you need MQTT or pullCreate it with Terraform or the eventgrid extension, grant the sender and receiver roles, and move the consumer to pull.
Tip: before you create the first system topic in a subscription, check that the Microsoft.EventGrid resource provider is registered. A missing registration is a frequent reason the first subscription fails. See the code references for the same setup as Terraform.
Common issues after configuration
| Symptom | Likely cause | What to check / fix |
|---|---|---|
| Creating a webhook subscription fails | The endpoint didn’t answer the validation handshake within the time allowed, or it isn’t reachable from Event Grid | Use a handler that answers the handshake (an Event Grid-trigger function does), or complete the manual validation with the URL in the validation event. |
| The subscription exists, but nothing reaches the handler | The event type or the subject filter doesn’t match (subject paths are case-insensitive by default but must start exactly as the event does), or the subscription has expired | Remove the filters and test, then add them back one at a time. Check the expiration date and the topic metrics for matched events. |
| Events vanish after a failure | No dead-letter location is set, and the retries or the time to live ran out | Set a dead-letter container and alarm on the dead-lettered and dropped counts. |
| The dead-letter container stays empty | The identity or key used for dead-lettering can’t write to it, or the delivery hasn’t exhausted its attempts yet | Give Event Grid’s identity the Storage Blob Data Contributor role on the container, and wait for the time to live to pass. |
| Publishing returns 401 or 403 | A wrong key, a missing EventGrid Data Sender role, or local authentication switched off on the topic | Use the topic’s own endpoint, use Entra roles where local keys are off, and check the key hasn’t been regenerated. |
| Publishing returns 400 | The event’s schema doesn’t match the topic’s input schema, or a required field such as id or type is missing | Send CloudEvents to a CloudEvents topic. Check the content type header, and that the batch stays under the size limit. |
| The first system topic can’t be created | The Microsoft.EventGrid resource provider isn’t registered in the subscription | Register the provider, wait a minute, and create the topic again. |
| A consumer sees events twice or in a different order | Delivery is at least once and the service doesn’t promise order | Make handlers idempotent, keep an event ID or a version, and don’t rely on arrival order. |
| A pull consumer receives the same event again | The lock expired before the consumer acknowledged it | Acknowledge sooner, renew the lock for long jobs, or raise the lock duration on the subscription. |
| An MQTT client cannot connect or publish | The client isn’t registered in a client group, authentication names or certificates don’t match, or no permission binding covers the topic | Check the client’s authentication name, the client group, and a binding from that group to the topic space. |
| The bill is higher than expected | Advanced filters, retries and delivery attempts count as operations, and a namespace bills its throughput units every hour | Filter early with event types and subject filters, fix failing handlers, and right-size or remove unused namespace capacity. |
Use cases: when and where to use it
Good fit
- Reacting to Azure resource events, such as a new blob, without writing a poller
- Applications that announce their own events to several independent handlers
- Serverless designs that wake a function only when something happened
- IoT and device scenarios that need an MQTT broker next to Azure services
- Consumers that want to pull events at their own pace from a managed broker
- SaaS products that give each customer their own topic through a domain
Consider something else
- Ordered, transactional messages between systems → Azure Service Bus queues and topics
- A very high-volume stream that many consumers read and replay → Azure Event Hubs
- A visual workflow that calls many services → Azure Logic Apps, which can also be a handler
- Scheduled jobs → timer triggers in Azure Functions or a Logic Apps recurrence, because Event Grid itself doesn’t run timers
- The same job on other clouds → compare Amazon EventBridge and Eventarc
Pros: why consider it?
Why teams choose it
- Native events from dozens of Azure services, with no publisher code
- Filtering by type, subject and data before delivery
- Push and pull, plus an MQTT broker in the same service
- Retries with backoff and dead-lettering built in
- Works with Entra identities, managed identity delivery and private endpoints
- Pay per operation, with a free monthly allowance on the Basic tier
Trade-offs to weigh
- No ordering, and at-least-once delivery means handlers must cope with duplicates
- Two shapes (topics and namespaces) with different features, limits and prices
- Push delivery from namespaces is narrower than from topics, so check the current list of handlers
- No built-in replay of past events, unlike an event log
- Webhook handlers must handle the validation handshake
- Regional resources, so cross-Region designs need planning
Common threats, vulnerabilities & risks
| Risk | Severity | Why it matters | Mitigation |
|---|---|---|---|
| No dead-letter location | High | When retries run out the event is dropped, and an order or an alert is lost without a trace. | Set a dead-letter container on every subscription and alarm on dropped and dead-lettered counts. |
| Access keys in code or pipelines | High | A leaked topic key lets anyone publish events that your handlers trust. | Switch off local authentication, use Entra roles, and rotate keys if you must keep them. |
| Open public endpoints | High | A public topic or an unprotected webhook accepts traffic from anywhere. | Use private endpoints and IP rules where possible, and protect webhooks with Entra authentication. |
| Handlers that aren’t idempotent | Medium | A retried or duplicate delivery repeats the side effect, such as a second email or a double charge. | Store the event ID or a business key and skip what you have seen. |
| Sensitive data inside events | Medium | Events pass through queues, storage and logs, each with its own access rules. | Send identifiers, not personal data, and let the handler read the record. |
| Subscriptions that expire or drift | Medium | A subscription with an expiration date stops quietly, and manual edits differ between environments. | Avoid expiry dates for production, and manage subscriptions as code. |
| Broad subscriptions at subscription or resource group level | Medium | A resource-group topic receives every change under it, which is noisy and costly. | Filter on event types and subjects, or scope the source more narrowly. |
| Unmonitored namespace capacity | Low–Med | Throughput units are billed whether used or not, and too few cause throttling. | Watch the namespace metrics, and use autoscale where it is available. |
| Relying on order | Low–Med | A later change can arrive before an earlier one. | Carry a version or timestamp in the event and ignore stale ones. |
Performance optimisation
- Send events in batches on one request, and keep each request below the 1 MB limit.
- Keep events small: send an ID and a URL, not the whole document.
- Use subject and type filters so handlers receive only what they need.
- Choose batched delivery for handlers that can process several events at once, such as Functions or Event Hubs.
- For slow or bursty consumers, use pull delivery or put a Storage queue or Service Bus queue between Event Grid and the code.
- Keep handlers fast and idempotent: return a success quickly and do the long work afterwards.
- Place the topic in the same region as the publisher and the main handler to cut latency.
- For devices, use MQTT with sensible topic hierarchies and shared subscriptions so load spreads over consumers.
Reduce monthly cost
FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for Azure Event Grid.
- Start on the Basic tier for push-only designs, since the first 100,000 operations a month are free.
- Remember that delivery attempts, advanced filters and management calls all count as operations.
- Filter with event types and subjects first; they are cheaper than advanced filters.
- Fix failing handlers, because every retry is another operation.
- Delete unused subscriptions and topics, and turn off subscriptions for retired systems.
- Size namespace throughput units to the real load, and remove idle namespaces, since units are billed per hour.
- Use batched delivery where the handler supports it, to cut the number of calls.
- Keep dead-letter storage small by processing and deleting failed events.
- Don’t publish chatty events that nobody consumes. Sample progress events at the source.
- Tag topics with the owning team, and put a budget alert on Event Grid spend.
Rates and allowances here come from Microsoft's pricing page and third-party summaries, read in October 2026. The Microsoft page renders prices by region and currency, so confirm there (see Pricing).
Security optimisation
- Use Azure RBAC: EventGrid Data Sender for publishers, EventGrid Data Receiver for consumers, and narrow contributor roles for management.
- Switch off local authentication on topics and namespaces, and use Microsoft Entra tokens from your apps.
- Deliver with a managed identity to Azure handlers, so no keys or SAS tokens sit in the subscription.
- Use private endpoints and turn off public network access, or set IP firewall rules.
- Protect webhook handlers with Entra authentication, and answer the validation handshake only on that route.
- Use a minimum TLS version of 1.2, and require MQTT clients to authenticate with certificates or Entra identities.
- Keep personal data and secrets out of events and out of subjects, because subjects appear in logs.
- Send diagnostic logs to Azure Monitor and alert on failed deliveries and publish errors.
- Review who can create subscriptions, since a new subscription can send events to another destination.
- Use Azure Policy to require private access and disabled local authentication on topics and domains.
Governance & compliance
Guardrails
- A Bicep or Terraform module for topics and subscriptions that always sets a dead-letter location, retry settings and tags
- Azure Policy that denies topics with public access or local authentication, assigned at the management group
- A naming and versioning rule for event types, such as com.example.order.placed, with schemas kept in the producer’s repository
- An owner tag on every subscription, and a review of subscriptions that haven’t matched an event in 90 days
Continuous checks (Azure Policy and your own scripts)
- Built-in policies that require private link and disabled public access on Event Grid topics and domains
- A policy or script that finds subscriptions without a dead-letter destination (the C# tab does this)
- An alert rule on the dead-lettered, dropped and failed-attempt metrics
- A policy audit for topics and domains that still allow local authentication
- Defender for Cloud recommendations on the resource group that holds the topics
The activity log records who changed topics and subscriptions, Azure Policy evaluates the rules above, Defender for Cloud raises recommendations, and the Microsoft Service Trust Portal holds audit reports. Microsoft runs the service and keeps events safe in transit and at rest. Event design, who may publish and subscribe, retry and dead-letter settings, and the handlers' own security are yours.
Reduce carbon footprint
- Send fewer, leaner events, and sample the producers that talk too much.
- Filter at the subscription so handlers aren’t invoked for events they ignore.
- Fix failing handlers, since each retry repeats work and traffic.
- Remove unused topics, subscriptions and namespaces.
- Where residency rules and latency allow, use a region on a cleaner grid.
- Microsoft’s Emissions Impact Dashboard reports emissions per subscription, with no separate figure for Event Grid, so this page gives none.
Pricing
Purchase options
Basic tier First 100,000 operations a month free
After that, roughly $0.60 per million operations as third-party pages list it. An operation is an event published, a delivery attempt, an advanced filter match or a management call.
Standard tier (namespaces) Throughput units plus operations
Throughput units are billed by the hour, and event and MQTT operations are billed per million after a monthly allowance. Check the page for the current numbers.
MQTT Per message operation
Messages published to and delivered from the broker count as operations. Client connections are not billed on their own.
Things around it Storage, handlers and logs
Dead-letter blobs, Storage queues, Functions executions and Azure Monitor logs are billed by their own services.
What you actually pay for
- Events published, delivery attempts and advanced filter matches (Basic tier operations)
- Throughput units, by the hour, in a Standard namespace
- MQTT and namespace event operations above the monthly allowance
- Storage for dead-lettered events and the queues you use as handlers
- Handler compute and the diagnostic logs you send to Azure Monitor
Rates differ by region and currency, and the allowances on the Standard tier have changed over time. See the official Azure Event Grid pricing page and the Azure pricing calculator.
Important code references
Blob uploads and order events: a storage account with a queue and a dead-letter container, a system topic that sends new .jpg uploads to the queue, and a custom topic for your own CloudEvents with a subscription, retries and dead-lettering. The CLI tab builds it and publishes a test event; Terraform describes the same resources and adds a namespace. The Python tab publishes to a namespace topic and reads with pull delivery, and the C# tab audits a subscription for event subscriptions without a dead-letter location. Replace the names and the region with your own, and use a test subscription for the first run.
# Placeholders: replace the names and the region with your own. Storage account names must be unique worldwide.
RG=rg-events-demo
LOC=centralindia
SA=stevents$RANDOM
APP=orders
az group create --name $RG --location $LOC
# 1. A storage account with a queue for the events and a container for the ones that cannot be delivered.
az storage account create --name $SA --resource-group $RG --location $LOC --sku Standard_LRS \
--min-tls-version TLS1_2 --allow-blob-public-access false
az storage queue create --account-name $SA --name blob-created --auth-mode login
az storage container create --account-name $SA --name dead-letters --auth-mode login
SA_ID=$(az storage account show --name $SA --resource-group $RG --query id --output tsv)
# 2. A system topic: Azure itself publishes the storage account's events to it. There is no publisher code to write.
az eventgrid system-topic create --name $SA-events --resource-group $RG --location $LOC \
--source $SA_ID --topic-type microsoft.storage.storageaccounts
# 3. Only new .jpg files in the uploads container go to the queue. Ten attempts or two hours, then the dead-letter container.
az eventgrid system-topic event-subscription create --name uploads-to-queue --resource-group $RG --system-topic-name $SA-events \
--included-event-types Microsoft.Storage.BlobCreated \
--subject-begins-with /blobServices/default/containers/uploads/ --subject-ends-with .jpg \
--endpoint-type storagequeue --endpoint $SA_ID/queueServices/default/queues/blob-created \
--max-delivery-attempts 10 --event-ttl 120 \
--deadletter-endpoint $SA_ID/blobServices/default/containers/dead-letters
# 4. A custom topic for your own events, in the CloudEvents format, with a subscription for one event type.
az eventgrid topic create --name $APP-topic --resource-group $RG --location $LOC --input-schema cloudeventschemav1_0
TOPIC_ID=$(az eventgrid topic show --name $APP-topic --resource-group $RG --query id --output tsv)
az storage queue create --account-name $SA --name orders-placed --auth-mode login
az eventgrid event-subscription create --name orders-to-queue --source-resource-id $TOPIC_ID \
--event-delivery-schema cloudeventschemav1_0 --included-event-types com.example.order.placed \
--endpoint-type storagequeue --endpoint $SA_ID/queueServices/default/queues/orders-placed \
--max-delivery-attempts 10 --event-ttl 120 --deadletter-endpoint $SA_ID/blobServices/default/containers/dead-letters
# 5. Publish one event. Event Grid answers 200 when it has accepted the event, not when a handler has finished with it.
ENDPOINT=$(az eventgrid topic show --name $APP-topic --resource-group $RG --query endpoint --output tsv)
KEY=$(az eventgrid topic key list --name $APP-topic --resource-group $RG --query key1 --output tsv)
curl -s -X POST "$ENDPOINT" -H "aeg-sas-key: $KEY" -H "Content-Type: application/cloudevents+json; charset=utf-8" \
-d '{"specversion": "1.0", "id": "1001", "source": "/shop/orders", "type": "com.example.order.placed",
"subject": "orders/A-1001", "datacontenttype": "application/json", "data": {"orderId": "A-1001", "total": 2500}}'
az storage message peek --account-name $SA --queue-name orders-placed --auth-mode login
# 6. Did anything fail to arrive? The topic's metrics tell you: failed attempts, dropped events and dead-lettered events.
az monitor metrics list --resource $TOPIC_ID --metric DeliveryAttemptFailCount DroppedEventCount DeadLetteredCount \
--interval PT5M --aggregation Total
# MQTT and pull delivery live in Event Grid namespaces. Create one with the Terraform tab or with the eventgrid CLI extension.
# Placeholders: pass in your own names and region. Storage account names must be unique worldwide.
variable "location" {
type = string
default = "centralindia"
}
variable "storage_account_name" {
type = string
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "events" {
name = "rg-events-demo"
location = var.location
}
resource "azurerm_storage_account" "events" {
name = var.storage_account_name
resource_group_name = azurerm_resource_group.events.name
location = azurerm_resource_group.events.location
account_tier = "Standard"
account_replication_type = "LRS"
min_tls_version = "TLS1_2"
allow_nested_items_to_be_public = false
}
resource "azurerm_storage_queue" "blob_created" {
name = "blob-created"
storage_account_name = azurerm_storage_account.events.name
}
resource "azurerm_storage_queue" "orders_placed" {
name = "orders-placed"
storage_account_name = azurerm_storage_account.events.name
}
resource "azurerm_storage_container" "dead_letters" {
name = "dead-letters"
storage_account_name = azurerm_storage_account.events.name
container_access_type = "private"
}
# Azure publishes the storage account's events to this system topic by itself.
resource "azurerm_eventgrid_system_topic" "storage" {
name = "${var.storage_account_name}-events"
resource_group_name = azurerm_resource_group.events.name
location = azurerm_resource_group.events.location
source_arm_resource_id = azurerm_storage_account.events.id
topic_type = "Microsoft.Storage.StorageAccounts"
}
resource "azurerm_eventgrid_system_topic_event_subscription" "uploads" {
name = "uploads-to-queue"
system_topic = azurerm_eventgrid_system_topic.storage.name
resource_group_name = azurerm_resource_group.events.name
included_event_types = ["Microsoft.Storage.BlobCreated"]
subject_filter {
subject_begins_with = "/blobServices/default/containers/uploads/"
subject_ends_with = ".jpg"
}
storage_queue_endpoint {
storage_account_id = azurerm_storage_account.events.id
queue_name = azurerm_storage_queue.blob_created.name
}
retry_policy {
max_delivery_attempts = 10
event_time_to_live = 120
}
storage_blob_dead_letter_destination {
storage_account_id = azurerm_storage_account.events.id
storage_blob_container_name = azurerm_storage_container.dead_letters.name
}
}
# A custom topic for your own events, in the CloudEvents format.
resource "azurerm_eventgrid_topic" "orders" {
name = "orders-topic"
resource_group_name = azurerm_resource_group.events.name
location = azurerm_resource_group.events.location
input_schema = "CloudEventSchemaV1_0"
}
resource "azurerm_eventgrid_event_subscription" "orders" {
name = "orders-to-queue"
scope = azurerm_eventgrid_topic.orders.id
event_delivery_schema = "CloudEventSchemaV1_0"
included_event_types = ["com.example.order.placed"]
storage_queue_endpoint {
storage_account_id = azurerm_storage_account.events.id
queue_name = azurerm_storage_queue.orders_placed.name
}
retry_policy {
max_delivery_attempts = 10
event_time_to_live = 120
}
storage_blob_dead_letter_destination {
storage_account_id = azurerm_storage_account.events.id
storage_blob_container_name = azurerm_storage_container.dead_letters.name
}
}
# A namespace gives you the MQTT broker and pull delivery. Standard is the tier that has both.
resource "azurerm_eventgrid_namespace" "events" {
name = "events-namespace-demo"
resource_group_name = azurerm_resource_group.events.name
location = azurerm_resource_group.events.location
sku = "Standard"
capacity = 1
}
output "orders_topic_endpoint" {
value = azurerm_eventgrid_topic.orders.endpoint
}
# pip install azure-eventgrid azure-identity
# Publishes orders as CloudEvents to an Event Grid namespace topic and reads them back with pull delivery:
# acknowledge what worked, release what should be tried again, reject what can never work.
import os
from azure.core.messaging import CloudEvent
from azure.eventgrid import EventGridConsumerClient, EventGridPublisherClient
from azure.identity import DefaultAzureCredential
ENDPOINT = os.environ["EVENTGRID_NAMESPACE_ENDPOINT"] # https://<namespace>.<region>-1.eventgrid.azure.net
TOPIC = "orders"
SUBSCRIPTION = "billing"
credential = DefaultAzureCredential() # needs the EventGrid Data Sender and EventGrid Data Receiver roles
publisher = EventGridPublisherClient(ENDPOINT, credential, namespace_topic=TOPIC)
consumer = EventGridConsumerClient(ENDPOINT, credential, namespace_topic=TOPIC, subscription=SUBSCRIPTION)
def publish(orders):
"""Sends the orders in requests of 100 events, which keeps each request far below the 1 MB limit."""
for start in range(0, len(orders), 100):
batch = [CloudEvent(source="/shop/orders", type="com.example.order.placed",
subject="orders/%s" % order["orderId"], data=order) for order in orders[start:start + 100]]
publisher.send(batch)
def drain(handler, rounds=3):
"""Reads up to 50 events at a time. Returns how many were acknowledged, released and rejected."""
counts = {"acknowledged": 0, "released": 0, "rejected": 0}
for _ in range(rounds):
received = consumer.receive(max_events=50, max_wait_time=10)
if not received:
break
done, again, poison = [], [], []
for item in received:
token = item.broker_properties.lock_token
try:
handler(item.event)
done.append(token)
except ValueError: # the message itself is bad: retrying will never help
poison.append(token)
except Exception: # a dependency was down: let Event Grid hand it out again
again.append(token)
if done:
consumer.acknowledge(lock_tokens=done)
if again:
consumer.release(lock_tokens=again)
if poison:
consumer.reject(lock_tokens=poison)
counts["acknowledged"] += len(done)
counts["released"] += len(again)
counts["rejected"] += len(poison)
return counts
def charge(event):
order = event.data
if "total" not in order:
raise ValueError("order has no total")
print("charging", order["orderId"], order["total"])
if __name__ == "__main__":
publish([{"orderId": "A-%d" % n, "total": 400 + n * 300} for n in range(1, 6)] + [{"orderId": "A-BAD"}])
print(drain(charge))
// dotnet add package Azure.Identity
// dotnet add package Azure.ResourceManager.EventGrid
// Audits the subscription: event subscriptions with no dead-letter location, and ones that still retry for the full default.
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.EventGrid;
using Azure.ResourceManager.Resources;
var arm = new ArmClient(new DefaultAzureCredential());
SubscriptionResource subscription = await arm.GetDefaultSubscriptionAsync();
int problems = 0;
await foreach (SystemTopicResource topic in subscription.GetSystemTopicsAsync())
{
await foreach (SystemTopicEventSubscriptionResource sub in topic.GetSystemTopicEventSubscriptions().GetAllAsync())
{
var data = sub.Data;
if (data.DeadLetterDestination is null)
{
Console.WriteLine($"system topic {topic.Data.Name}/{data.Name}: no dead-letter location");
problems++;
}
if (data.RetryPolicy?.EventTimeToLiveInMinutes is null or >= 1440)
{
Console.WriteLine($"system topic {topic.Data.Name}/{data.Name}: events are retried for a full day");
problems++;
}
}
}
await foreach (EventGridTopicResource topic in subscription.GetEventGridTopicsAsync())
{
await foreach (TopicEventSubscriptionResource sub in topic.GetTopicEventSubscriptions().GetAllAsync())
{
if (sub.Data.DeadLetterDestination is null)
{
Console.WriteLine($"topic {topic.Data.Name}/{sub.Data.Name}: no dead-letter location");
problems++;
}
}
}
Console.WriteLine(problems == 0 ? "No problems found." : $"{problems} problem(s) found.");
return problems == 0 ? 0 : 1;
Best videos to explore
Videos picked for this service. Each one is labelled with its source, opens on YouTube if you prefer, and loads only when you press play.
Interview questions
BasicWhat is Azure Event Grid?
It’s the Azure service that routes events. A publisher, such as Blob Storage or your own app, sends an event to a topic, and subscriptions deliver it to handlers like a function, a queue or a webhook. It also offers an MQTT broker and pull delivery in namespaces.
BasicWhat is the difference between Event Grid, Service Bus and Event Hubs?
Event Grid reacts to discrete events, such as a file arriving, and pushes them to handlers. Service Bus is for reliable business messages with queues, topics, ordering options and transactions. Event Hubs ingests very high-volume streams that several consumers read. They are often combined, for example Event Grid sending a blob event to a Service Bus queue.
BasicWhat are system, custom and partner topics?
System topics belong to an Azure service and carry its events. Custom topics are endpoints for your own application events. Partner topics bring in events from a SaaS provider that has been set up as an event partner.
IntermediateHow do retries and dead-lettering work?
Event Grid retries a failed delivery with exponential backoff until the maximum attempts (up to 30) or the event time to live (up to 24 hours) is reached. If a dead-letter container is configured, the event is then written there. Without one it is dropped. Some errors, such as an invalid request, are not retried.
IntermediateWhen would you use pull delivery instead of push?
When the consumer should control the pace, for instance a worker that is sometimes busy or offline, or a system that cannot expose an HTTP endpoint. In pull delivery the consumer receives events, holds a lock, and then acknowledges, releases or rejects each one. Push suits handlers that are always ready, such as Functions.
IntermediateWhat does a webhook validation handshake do?
When you create a subscription to a webhook, Event Grid sends a validation event and expects the endpoint to echo the validation code, or to confirm through a URL. This proves that the endpoint owner agreed to receive events. An Event Grid-trigger function does it for you.
AdvancedHow would you design a reliable event flow from Blob Storage to an image-processing service?
Use a system topic on the storage account, filter on BlobCreated and the container prefix, and deliver to a Storage queue or Service Bus queue so the processors read at their own pace. Set retries and a dead-letter container, make the processor idempotent using the blob URL and ETag, alarm on dead-lettered events, and reprocess them from the container.
AdvancedHow do you secure an Event Grid setup end to end?
Use Entra roles for publishers and consumers, turn off local keys, deliver with a managed identity, use private endpoints with public access off, protect webhooks with Entra authentication, and keep personal data out of events. Apply Azure Policy to require these settings and send diagnostic logs to Azure Monitor.
AdvancedHow would you bring IoT devices into Azure services with Event Grid?
Create a namespace, register devices as MQTT clients in client groups, define topic spaces and permission bindings, and have devices connect with certificates. Route messages to an Azure service or a namespace topic, and let consumers pull or receive pushed events. Plan throughput units and watch the namespace metrics.
AdvancedWhat would you check before moving from the Basic tier to namespaces?
Which features you need: MQTT, pull delivery, or CloudEvents-only topics. Which handlers you push to, because namespace push delivery has had a narrower list than topics. Cost, since throughput units are billed by the hour. Limits such as event size and subscriptions, and whether the existing system topics have an equivalent.
Similar or alternative services on other clouds
| Capability | AWS | Azure | Google Cloud |
|---|---|---|---|
| Service | Amazon EventBridge | Azure Event Grid | Eventarc with Pub/Sub |
| Events from the platform | Default bus, AWS service events free | System topics for Azure services | Eventarc Standard triggers for Google Cloud sources and audit logs |
| Your own events | Custom buses with PutEvents | Custom topics, domains, namespace topics | Eventarc Advanced message bus, or Pub/Sub |
| Filtering | Event patterns on any field | Event type, subject and advanced filters | Trigger filters, and CEL conditions in Advanced |
| Delivery | Push to targets, five per rule | Push to handlers; pull delivery in namespaces | Push over HTTP, with Pub/Sub as the transport |
| Retry and dead letter | Retry policy and an SQS dead-letter queue | Backoff retries and a Blob Storage dead-letter location | Pub/Sub subscription retry and a dead-letter topic |
| Device messaging | AWS IoT Core (separate service) | MQTT broker in namespaces | No native MQTT broker; partner or self-managed |
| Schedules | EventBridge Scheduler | Timer triggers and Logic Apps | Cloud Scheduler |
| How you are billed | Per custom event, Pipes request, archive GB | Per operation; throughput units in namespaces | Per event or message, plus Pub/Sub transport |
Typical handlers include Azure Functions, and sources include Azure Blob Storage. Metrics and alerts for topics are in Azure Monitor.
Did you find this article helpful?
Your answer helps us improve this page for the next reader.
Sources and further reading
CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.
- What is Azure Event Grid?Microsoft
- Choose the right Event Grid tier for your solutionMicrosoft
- Event Grid namespaces: conceptsMicrosoft
- Pull delivery with Event Grid namespacesMicrosoft
- Event Grid message delivery and retryMicrosoft
- Event Grid quotas and limitsMicrosoft
- Choose between Azure messaging servicesMicrosoft
- Azure Event Grid pricingMicrosoft
- Terraform azurerm provider: azurerm_eventgrid_topicHashiCorp
