Your First Event Subscription
This guide walks you through creating your first Event Grid subscription end-to-end. You'll set up a storage account, create an Azure Function as the event handler, subscribe to blob events, trigger an event, and verify delivery.
Prerequisites
Before starting, ensure you have:
- An active Azure subscription (free tier works)
- Azure CLI installed and logged in (
az login) - The Event Grid provider registered
- Node.js or .NET installed (for the Function app)
# Verify you're logged in
az account show --query "name" --output tsv
# Register the Event Grid resource provider (one-time)
az provider register --namespace Microsoft.EventGrid
# Confirm registration is complete
az provider show --namespace Microsoft.EventGrid --query "registrationState" --output tsv
# Expected output: Registered
Step 1: Create a Resource Group
# Create a resource group to hold all resources for this tutorial
az group create \
--name eg-tutorial-rg \
--location eastus
Step 2: Create a Storage Account
This storage account will be the event source — when blobs are uploaded, it emits events.
# Create a general-purpose v2 storage account
# Name must be globally unique, 3-24 lowercase letters/numbers
az storage account create \
--name egtutorialstorage123 \
--resource-group eg-tutorial-rg \
--location eastus \
--sku Standard_LRS \
--kind StorageV2
# Create a container to upload blobs into
az storage container create \
--name images \
--account-name egtutorialstorage123
Step 3: Create a Function App as Handler
The Function app will receive and log the events. We'll use the Consumption plan (serverless, free tier).
# Create a storage account for the Function app (required)
az storage account create \
--name egtutorialfuncstor \
--resource-group eg-tutorial-rg \
--location eastus \
--sku Standard_LRS
# Create the Function app
az functionapp create \
--name eg-tutorial-func \
--resource-group eg-tutorial-rg \
--storage-account egtutorialfuncstor \
--consumption-plan-location eastus \
--runtime node \
--runtime-version 18 \
--functions-version 4
For this tutorial, you can also use the Event Grid Viewer — a pre-built web app that displays received events. Deploy it from the Azure samples:
# Alternative: deploy the Event Grid Viewer web app
az deployment group create \
--resource-group eg-tutorial-rg \
--template-uri "https://raw.githubusercontent.com/Azure-Samples/azure-event-grid-viewer/main/azuredeploy.json" \
--parameters siteName=eg-tutorial-viewer hostingPlanName=viewerPlan
Step 4: Create the Event Subscription via CLI
Now connect the storage account (source) to your handler (endpoint):
# Get the storage account resource ID
STORAGE_ID=$(az storage account show \
--name egtutorialstorage123 \
--resource-group eg-tutorial-rg \
--query "id" --output tsv)
# Create the event subscription
az eventgrid event-subscription create \
--name my-first-subscription \
--source-resource-id $STORAGE_ID \
--endpoint "https://eg-tutorial-viewer.azurewebsites.net/api/updates" \
--included-event-types Microsoft.Storage.BlobCreated Microsoft.Storage.BlobDeleted
Creating via the Azure Portal
- Navigate to your storage account in the Azure Portal
- In the left menu, click Events
- Click + Event Subscription
- Fill in:
- Name: my-first-subscription
- Event Schema: Event Grid Schema
- Filter to Event Types: Blob Created, Blob Deleted
- Endpoint Type: Web Hook
- Endpoint: Your function or viewer URL
- Click Create
Step 5: Upload a Blob to Trigger the Event
# Create a simple test file
echo "Hello Event Grid!" > test-file.txt
# Upload it to the images container
az storage blob upload \
--account-name egtutorialstorage123 \
--container-name images \
--name test-file.txt \
--file test-file.txt
# Upload another file to see multiple events
az storage blob upload \
--account-name egtutorialstorage123 \
--container-name images \
--name photo.jpg \
--file test-file.txt
Step 6: Verify the Event Was Received
If using the Event Grid Viewer, open https://eg-tutorial-viewer.azurewebsites.net in your browser. You should see the BlobCreated events appear within seconds.
If using Azure Functions, check the function logs:
# Stream function logs in real-time
az webapp log tail \
--name eg-tutorial-func \
--resource-group eg-tutorial-rg
Step 7: View Delivery Metrics
# Check subscription delivery status
az eventgrid event-subscription show \
--name my-first-subscription \
--source-resource-id $STORAGE_ID \
--include-full-endpoint-url
# List all event subscriptions for the storage account
az eventgrid event-subscription list \
--source-resource-id $STORAGE_ID \
--output table
In the portal, navigate to your storage account → Events → your subscription to see:
- Delivered events count
- Failed deliveries
- Delivery latency graph
Troubleshooting Common Issues
| Issue | Cause | Solution |
|---|---|---|
| 403 Forbidden | Endpoint doesn't have proper permissions | Ensure the function/webhook is publicly accessible or has the correct auth key |
| Endpoint validation failed | Webhook didn't respond to validation handshake | Your endpoint must return the validationCode from the validation event |
| No events received | Subscription filter too restrictive | Check --included-event-types and subject filters match your upload path |
| Events delayed | Handler returning errors, triggering retries | Check handler logs for exceptions; Event Grid retries on 4xx/5xx |
| Subscription creation fails | Event Grid provider not registered | Run az provider register --namespace Microsoft.EventGrid |
Webhook Validation Explained
When you create a subscription with a webhook endpoint, Event Grid sends a validation event:
{
"eventType": "Microsoft.EventGrid.SubscriptionValidationEvent",
"data": {
"validationCode": "abc123-def456-..."
}
}
Your endpoint must respond with HTTP 200 and body: {"validationResponse": "abc123-def456-..."}. Azure Functions with the Event Grid trigger handle this automatically.
Step 8: Clean Up Resources
# Delete the entire resource group and all resources within it
az group delete \
--name eg-tutorial-rg \
--yes \
--no-wait
# Verify deletion is in progress
az group show --name eg-tutorial-rg --query "properties.provisioningState"
Tips
- Start with the Event Grid Viewer — It's the fastest way to see events without writing handler code
- Use
--subject-begins-with— Filter events to specific containers or paths to reduce noise - Check provider registration first — Most "subscription creation failed" errors are due to an unregistered provider
- Use system-assigned managed identity — For production, avoid webhook keys and use managed identity for secure delivery
Key Takeaways
- Creating an event subscription requires: a source (storage account), a handler (function/webhook), and filter criteria
- The CLI command
az eventgrid event-subscription createis the core command for setting up subscriptions - Webhook endpoints must pass a validation handshake before receiving events
- Events are delivered within seconds of the triggering action (blob upload)
- Always clean up tutorial resources to avoid unexpected charges
- Use delivery metrics in the portal to monitor subscription health
- The Event Grid Viewer sample app is ideal for learning and debugging