Reacting to Events with an Event Grid System Topic

Preview

Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in

Reacting to Events with an Event Grid System Topic

This guide shows you how to react to events from an Azure service using an Event Grid System Topic against Locally. We'll subscribe to a Storage Account's blob events, upload a file, and watch the BlobCreated event land on a storage queue.

Before you start

Plugins required

Locally v2026.10+ automatically installs these Resource Provider plugins when their Resource Providers are registered, but you can also install them via:

$ locally plugin install --name Microsoft.EventGrid
$ locally plugin install --name Microsoft.Storage

1. Start Locally

Firstly, we need to launch Locally which we can do from a terminal by running:

$ locally build

Once Locally has started, the Locally Dashboard will open automatically:

Screenshot of the Locally Dashboard

2. Create a Resource Group

Next we can create the Resource Group to hold everything:

$ locally run az group create -n sample-event-grid-system-topics -l berlin

There's two things to note here:

  1. The Azure CLI supports Automatic Configuration, meaning that it can automatically be configured to work against Locally just by prefixing commands with locally run.
  2. Locally intentionally uses a different set of locations to Azure as a safety precaution, so that you can be confident you're deploying against Locally rather than regular Azure. You can also configure Locally to use the Azure locations too, but you'll want to be extra sure that you're prefixing commands with locally run when you do.

3. Create the Storage Account

The Storage Account is both the source of the events and where we'll deliver them, so let's create it:

$ locally run az storage account create --name sampleegsystopic1 --resource-group sample-event-grid-system-topics --location berlin --sku Standard_LRS --query "{name:name, provisioningState:provisioningState}"
{
  "name": "sampleegsystopic1",
  "provisioningState": "Succeeded"
}

We need a container to upload into, and a queue for the events to arrive on:

$ locally storage container create --account sampleegsystopic1 --name uploads $ locally storage queue create --account sampleegsystopic1 --name blob-events

Note

locally storage is part of Locally itself, so it doesn't take the locally run prefix. Every az command does.

4. Create the System Topic

A System Topic represents the events an Azure resource publishes. It points at its source by resource ID, so let's grab the Storage Account's:

$ export STORAGE_ACCOUNT_ID=$(locally run az storage account show -n sampleegsystopic1 -g sample-event-grid-system-topics --query id -o tsv)

Now we can create a System Topic for the Storage Account's events:

$ locally run az eventgrid system-topic create -g sample-event-grid-system-topics -n sample-storage-events -l berlin --topic-type Microsoft.Storage.StorageAccounts --source "$STORAGE_ACCOUNT_ID" --query "{name:name, topicType:topicType, provisioningState:provisioningState}"
{
  "name": "sample-storage-events",
  "provisioningState": "Succeeded",
  "topicType": "Microsoft.Storage.StorageAccounts"
}

5. Subscribe a queue to blob events

The topic doesn't deliver anything until it has an event subscription. Let's send BlobCreated events to the blob-events queue:

$ locally run az eventgrid system-topic event-subscription create -g sample-event-grid-system-topics --system-topic-name sample-storage-events -n blob-created --endpoint-type storagequeue --endpoint "$STORAGE_ACCOUNT_ID/queueServices/default/queues/blob-events" --included-event-types Microsoft.Storage.BlobCreated --query "{name:name, endpointType:destination.endpointType, queueName:destination.queueName, includedEventTypes:filter.includedEventTypes, provisioningState:provisioningState}"
{
  "endpointType": "StorageQueue",
  "includedEventTypes": [
    "Microsoft.Storage.BlobCreated"
  ],
  "name": "blob-created",
  "provisioningState": "Succeeded",
  "queueName": "blob-events"
}

Because of that filter, other blob events, such as deletes, won't reach the queue. We can list the topic's subscriptions:

$ locally run az eventgrid system-topic event-subscription list -g sample-event-grid-system-topics --system-topic-name sample-storage-events --query "[].{Name:name, Destination:destination.endpointType, Queue:destination.queueName, State:provisioningState}" -o table
Name          Destination    Queue        State
------------  -------------  -----------  ---------
blob-created  StorageQueue   blob-events  Succeeded

6. Upload a blob

The az storage data plane commands need the account's connection string. Putting it in AZURE_STORAGE_CONNECTION_STRING means we don't have to pass it to each one:

$ export AZURE_STORAGE_CONNECTION_STRING=$(locally storage connection-string --account sampleegsystopic1)

Now let's upload a small file:

$ echo "hello from Locally" > hello.txt $ locally run az storage blob upload --container-name uploads --name hello.txt --file hello.txt -o none

7. See the event arrive

Event Grid writes each event to the queue as base64-encoded JSON. Let's peek at the message and decode it:

$ locally run az storage message peek --queue-name blob-events --query "[0].content" -o tsv | base64 --decode | jq "{eventType, subject, data: {api: .data.api, blobType: .data.blobType, contentLength: .data.contentLength}}"
{
  "eventType": "Microsoft.Storage.BlobCreated",
  "subject": "/blobServices/default/containers/uploads/blobs/hello.txt",
  "data": {
    "api": "PutBlob",
    "blobType": "BlockBlob",
    "contentLength": 19
  }
}

Delivery happens in the background, so if the command prints nothing, give it a second and run it again. The subject tells a handler which blob was created, which is all it needs to go and process it.

8. Tidy up

Finally, we can tidy up. To remove the Resource Group and everything within it:

$ locally run az group delete -n sample-event-grid-system-topics --yes

Doing this with other tooling

Whilst this guide used the Azure CLI, System Topics work the same way through any of the tooling that Locally supports - Microsoft.EventGrid/systemTopics and Microsoft.EventGrid/systemTopics/eventSubscriptions resources in HashiCorp Terraform or OpenTofu, Pulumi, Bicep or an ARM Template all provision against Locally in the same way.

On the receiving end, any application reading the queue with the Azure SDK for .NET, Go or Python gets the same events.

Next steps

To publish your own events rather than a service's, see Event Grid Topic. For more on working with the queue the events land on, see Storage Queues.

Should you encounter any issues, please take a look at the troubleshooting section.

Resource types this guide uses

These are the Azure resource types this guide creates in Locally:

  • Microsoft.EventGrid/systemTopics
  • Microsoft.EventGrid/systemTopics/eventSubscriptions
  • Microsoft.Storage/storageAccounts
  • Microsoft.Storage/storageAccounts/queueServices/queues
Preview

Sign in during Public Preview to get the Team plan free, plus an early-adopter discount when we launch. Sign in

A local cloud for you and your AI agents.

Your Azure infrastructure, running on your machine. Deploy in seconds, break things freely, and ship to Azure when you're ready.