Event Grid
Introduction
Section titled “Introduction”Azure Event Grid is a fully managed event routing service that enables event-driven architectures using a publish-subscribe model. It supports custom topics for application events, system topics for Azure resource events, domains for multi-tenant scenarios, and namespaces for MQTT and CloudEvents pull delivery. Event Grid handles routing, filtering, and reliable delivery to multiple destination types. For more information, see What is Azure Event Grid?
LocalStack for Azure provides a local environment for building and testing applications that make use of Azure Event Grid. The supported APIs are available on our API Coverage section, which provides information on the extent of Event Grid’s integration with LocalStack.
Getting started
Section titled “Getting started”This guide is designed for users new to Event Grid and assumes basic knowledge of the Azure CLI and our lstk az proxy.
Launch LocalStack using your preferred method. For more information, see Introduction to LocalStack for Azure. Once the container is running, enable Azure CLI interception by running:
lstk az start-interceptionThis command points the az CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API.
To revert this configuration, run:
lstk az stop-interceptionThis reconfigures the az CLI to send commands to the official Azure management REST API.
Create a resource group
Section titled “Create a resource group”Create a resource group to contain your Event Grid resources:
az group create \ --name rg-eventgrid-demo \ --location westeurope{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-eventgrid-demo", "location": "westeurope", "managedBy": null, "name": "rg-eventgrid-demo", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups"}Create a custom topic
Section titled “Create a custom topic”Create an Event Grid topic for publishing custom events:
az eventgrid topic create \ --resource-group rg-eventgrid-demo \ --name topic-orders \ --location westeurope{ "dataResidencyBoundary": "WithinGeopair", "disableLocalAuth": false, "endpoint": "https://topic-orders.azure.localhost.localstack.cloud:4566/api/events", "extendedLocation": null, "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-eventgrid-demo/providers/Microsoft.EventGrid/topics/topic-orders", "identity": null, "inboundIpRules": null, "inputSchema": "EventGridSchema", "inputSchemaMapping": null, "kind": null, "location": "westeurope", "metricResourceId": "6f4b8a01-41c7-45ec-bfc8-2c51978d9ed1", "name": "topic-orders", "privateEndpointConnections": null, "provisioningState": "Succeeded", "publicNetworkAccess": "Enabled", "resourceGroup": "rg-eventgrid-demo", "sku": null, "systemData": null, "tags": null, "type": "Microsoft.EventGrid/topics"}Get the topic endpoint and access key:
TOPIC_ENDPOINT=$(az eventgrid topic show \ --resource-group rg-eventgrid-demo \ --name topic-orders \ --query endpoint -o tsv)
TOPIC_KEY=$(az eventgrid topic key list \ --resource-group rg-eventgrid-demo \ --name topic-orders \ --query key1 -o tsv)Create an event subscription with filtering
Section titled “Create an event subscription with filtering”Create an event subscription that delivers events to a Storage Queue with event type and subject filtering:
az storage account create \ --resource-group rg-eventgrid-demo \ --name stegdemo83 \ --location westeurope \ --sku Standard_LRS \ --output none
az storage queue create \ --account-name stegdemo83 \ --name orders-queue \ --output none
STORAGE_ID=$(az storage account show \ --resource-group rg-eventgrid-demo \ --name stegdemo83 \ --query id -o tsv)
az eventgrid event-subscription create \ --source-resource-id "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-eventgrid-demo/providers/Microsoft.EventGrid/topics/topic-orders" \ --name orders-to-queue \ --endpoint-type storagequeue \ --endpoint "$STORAGE_ID/queueServices/default/queues/orders-queue" \ --included-event-types "OrderCreated" "OrderUpdated" \ --subject-begins-with "orders/" \ --event-delivery-schema CloudEventSchemaV1_0{ "deadLetterDestination": null, "deadLetterWithResourceIdentity": null, "deliveryWithResourceIdentity": null, "destination": { "endpointType": "StorageQueue", "queueMessageTimeToLiveInSeconds": null, "queueName": "orders-queue", "resourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-eventgrid-demo/providers/Microsoft.Storage/storageAccounts/stegdemo83" }, "eventDeliverySchema": "CloudEventSchemaV1_0", "expirationTimeUtc": null, "filter": { "advancedFilters": null, "enableAdvancedFilteringOnArrays": null, "includedEventTypes": [ "OrderCreated", "OrderUpdated" ], "isSubjectCaseSensitive": null, "subjectBeginsWith": "orders/", "subjectEndsWith": "" }, "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-eventgrid-demo/providers/Microsoft.EventGrid/topics/topic-orders/providers/Microsoft.EventGrid/eventSubscriptions/orders-to-queue", "labels": null, "name": "orders-to-queue", "provisioningState": "Succeeded", "resourceGroup": "rg-eventgrid-demo", "retryPolicy": { "eventTimeToLiveInMinutes": 1440, "maxDeliveryAttempts": 30 }, "systemData": null, "topic": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-eventgrid-demo/providers/microsoft.eventgrid/topics/topic-orders", "type": "Microsoft.EventGrid/eventSubscriptions"}Publish events to the topic
Section titled “Publish events to the topic”Publish an event to the custom topic:
curl -X POST "$TOPIC_ENDPOINT" \ -H "aeg-sas-key: $TOPIC_KEY" \ -H "Content-Type: application/json" \ -d '[{ "id": "1001", "eventType": "OrderCreated", "subject": "orders/1001", "eventTime": "2026-09-28T10:00:00Z", "data": { "orderId": 1001, "status": "created" }, "dataVersion": "1.0" }]'{}Check that the event was delivered to the queue:
az storage message peek \ --account-name stegdemo83 \ --queue-name orders-queue \ --num-messages 1[ { "content": "eyJpZCI6ICIxMDAxIiwgInNvdXJjZSI6ICIvc3Vic2NyaXB0aW9ucy8wMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAvcmVzb3VyY2VHcm91cHMvcmctZXZlbnRncmlkLWRlbW8vcHJvdmlkZXJzL01pY3Jvc29mdC5FdmVudEdyaWQvdG9waWNzL3RvcGljLW9yZGVycyIsICJzcGVjdmVyc2lvbiI6ICIxLjAiLCAidHlwZSI6ICJPcmRlckNyZWF0ZWQiLCAic3ViamVjdCI6ICJvcmRlcnMvMTAwMSIsICJ0aW1lIjogIjIwMjYtMDktMjhUMTA6MDA6MDBaIiwgImRhdGEiOiB7Im9yZGVySWQiOiAxMDAxLCAic3RhdHVzIjogImNyZWF0ZWQifX0=", "dequeueCount": 0, "expirationTime": "2026-10-06T15:51:59+00:00", "id": "a7523087-3ae1-421a-a21e-d72a95f8c7a4", "insertionTime": "2026-09-29T15:51:59+00:00", "popReceipt": null, "timeNextVisible": null }]Create a namespace for pull delivery
Section titled “Create a namespace for pull delivery”Create an Event Grid namespace with a topic and queue subscription for CloudEvents pull delivery:
az eventgrid namespace create \ --resource-group rg-eventgrid-demo \ --name egns-demo \ --location westeurope
az eventgrid namespace topic create \ --resource-group rg-eventgrid-demo \ --namespace-name egns-demo \ --name orders
az eventgrid namespace topic event-subscription create \ --resource-group rg-eventgrid-demo \ --namespace-name egns-demo \ --topic-name orders \ --name orders-pull \ --delivery-configuration "{deliveryMode:Queue,queue:{receiveLockDurationInSeconds:60,maxDeliveryCount:4,eventTimeToLive:P1D}}" \ --event-delivery-schema CloudEventSchemaV1_0Publish and receive events using the namespace data plane endpoint:
NAMESPACE_ENDPOINT=$(az eventgrid namespace show \ --resource-group rg-eventgrid-demo \ --name egns-demo \ --query topicsConfiguration.hostname -o tsv)
NAMESPACE_KEY=$(az eventgrid namespace list-key \ --resource-group rg-eventgrid-demo \ --namespace-name egns-demo \ --query key1 -o tsv)
# Publish a CloudEventcurl -X POST "https://$NAMESPACE_ENDPOINT/topics/orders:publish?api-version=2023-06-01-preview" \ -H "aeg-sas-key: $NAMESPACE_KEY" \ -H "Content-Type: application/cloudevents+json" \ -d '{ "specversion": "1.0", "id": "2001", "type": "OrderCreated", "source": "/myapp/orders", "time": "2026-09-28T10:00:00Z", "data": { "orderId": 2001, "status": "created" } }'
# Receive events from the queue subscriptioncurl -X POST "https://$NAMESPACE_ENDPOINT/topics/orders/eventsubscriptions/orders-pull:receive?api-version=2023-06-01-preview&maxEvents=1" \ -H "aeg-sas-key: $NAMESPACE_KEY"The receive call returns the event together with the lock token to acknowledge, reject, or release it with:
{"value": [{"brokerProperties": {"lockToken": "84238b76-4baf-42b4-90ed-563993b9b161", "deliveryCount": 1}, "event": {"id": "2001", "source": "/myapp/orders", "data": {"orderId": 2001, "status": "created"}, "type": "OrderCreated", "time": "2026-09-28T10:00:00Z", "specversion": "1.0"}}]}Features
Section titled “Features”The emulator includes the following core capabilities:
Control Plane
Section titled “Control Plane”- Idempotent resource management: Repeated create-or-update operations for topics, domains, system topics, namespaces, namespace topics, and topic and system topic event subscriptions update in place without resetting access keys, child resources, or subscriptions. A create-or-update of an existing namespace topic event subscription, including
az eventgrid namespace topic event-subscription update, replaces it and discards the events not yet acknowledged; only aPATCHupdates it in place. - Configuration storage: Topics, domains, and subscriptions store and return
inputSchema,eventDeliverySchema,retryPolicy,publicNetworkAccess,disableLocalAuth,inboundIpRules,minimumTlsVersionAllowed,dataResidencyBoundary, andidentity.inputSchemaMappingis not stored, so custom input schemas are not mapped. - Resource hierarchy: Deleting a topic, system topic, or domain automatically deletes its child resources. Namespace resource updates via PATCH are supported.
- Access key management: Topics, domains, and namespaces support key regeneration with
key1andkey2.
Event Filtering
Section titled “Event Filtering”Event subscriptions apply filters before delivery:
- Event type filtering: Only events with types in
includedEventTypesare delivered. - Subject filtering:
subjectBeginsWithandsubjectEndsWithfilters with optional case sensitivity viaisSubjectCaseSensitive. - Advanced filters: All 19 operators are evaluated: the numeric operators, including
NumberInRangeandNumberNotInRange,BoolEquals, the string operators,IsNullOrUndefined, andIsNotNull. String comparisons are case-insensitive, and an array-valued key is compared only whenenableAdvancedFilteringOnArraysistrue.
Push Delivery Destinations
Section titled “Push Delivery Destinations”Event subscriptions support the following destination types:
- Storage Queue: Events delivered as base64-encoded messages, one event per message, with configurable
queueMessageTimeToLiveInSeconds. - Service Bus Queue: Events delivered with
aeg-*application properties and the configured delivery schema. - Service Bus Topic: Events delivered to Service Bus topics with
aeg-*application properties. - Event Hubs: One event per Event Grid event, whose body is a one-element JSON array.
- WebHook: Events delivered via HTTP POST with
aeg-*headers in a background thread.
Schema Conversion
Section titled “Schema Conversion”- When a subscription’s
eventDeliverySchemais set toCloudEventSchemaV1_0, Event Grid schema events are automatically converted to CloudEvents 1.0 format before delivery.
Namespace Pull Delivery
Section titled “Namespace Pull Delivery”The namespace data plane supports:
- CloudEvents publishing: Accepts structured single-event, batch, and binary-mode CloudEvents with validation of required attributes.
- Queue subscriptions: Receive operations honour
receiveLockDurationInSecondsandmaxDeliveryCount, which are read again on every receive.eventTimeToLiveis applied to each event when it is published. - Lock management: Every delivery gets a fresh lock token. Operations support
acknowledge,reject,releasewith configurablereleaseDelayInSeconds, andrenewLock. - Validation:
maxEventsdefaults to 1 (range 1-100) andmaxWaitTimeis validated (range 10-120 seconds).
System Topics
Section titled “System Topics”System topics can be created and subscribed to, but the only system event the emulator raises is Microsoft.EventHub.CaptureFileCreated, which Event Hubs Capture publishes when it writes an archive. It reaches the system topics whose source is the Event Hubs namespace.
Limitations
Section titled “Limitations”The current version of the emulator does not support the following:
Push Delivery Limitations
Section titled “Push Delivery Limitations”- No retries or dead-lettering: Push delivery makes a single attempt. Failed deliveries are not retried and are not written to the dead-letter destination. In namespace pull delivery, rejected events and events that exceed
maxDeliveryCountare dropped. - No webhook validation handshake: WebHook destinations receive neither the
SubscriptionValidationhandshake nor the CloudEventsOPTIONSrequest that real Azure sends before activating the subscription. - Single-attempt delivery: Retry policies and exponential backoff are stored but not enforced.
- Unsupported destinations:
AzureFunction,HybridConnection,MonitorAlert, andNamespaceTopicdestinations are accepted, but their events are logged and dropped. - No delivery properties or managed identity: Custom delivery properties (static and dynamic headers) and managed-identity delivery (
deliveryWithResourceIdentity) are ignored.
Resource Limitations
Section titled “Resource Limitations”- No domain publishing: Publishing events to domain endpoints is not supported. Use custom topics instead.
- No automatic system topic creation: System topics must be created explicitly. Azure automatically creates system topics when you subscribe to resource events, but the emulator does not.
- Resource group scoping: Stores are keyed by name within a subscription and region, so the same resource name in two resource groups may collide.
- No domain subscriptions: Domain and domain topic event subscriptions are not supported. An event subscription created at a subscription or resource group scope is stored but receives no events.
- Namespace subscriptions deliver every event: Namespace topic event subscriptions ignore
filtersConfiguration, so each receives every event published to its topic, and thePushdelivery mode delivers nothing. - Access keys are not checked: Publishing to a custom topic does not check the
aeg-sas-keyheader, and the namespace data plane is protected only when RBAC enforcement is enabled.
Partner and Extension Limitations
Section titled “Partner and Extension Limitations”- No partner events: Partner namespaces, partner topics, partner registrations, and channels are not supported.
- No extension topics: Extension topics are not available.
- No MQTT broker: MQTT clients, client groups, permission bindings, CA certificates, and topic spaces are not supported.
Advanced Filtering
Section titled “Advanced Filtering”- Where Microsoft Learn does not specify a behavior, filtering is approximated:
includedEventTypesis compared case-insensitively, keys afterdata.are case-sensitive, anullvalue counts as missing, and an array-valued key contributes no values unlessenableAdvancedFilteringOnArraysistrue.
Samples
Section titled “Samples”Explore the following samples to get started with Event Grid on LocalStack:
API Coverage
Section titled “API Coverage”75 of 170 operations implemented
| Operation ▲ | Implemented ▼ |
|---|