🌐 Azure Event Grid¶
Fully managed event routing service for building reactive, event-driven applications at scale.
🌟 Service Overview¶
Azure Event Grid is a highly scalable, serverless event broker that enables you to build event-driven architectures. It provides uniform event consumption using a publish-subscribe model, enabling real-time reactions to state changes across Azure services and custom applications.
🔥 Key Value Propositions¶
- Serverless Architecture: Pay only for events published, no infrastructure to manage
- Native Azure Integration: Built-in events from 100+ Azure services
- Advanced Filtering: Route events based on content, headers, or metadata
- Reliable Delivery: Built-in retry logic with dead-letter queues
- Global Scale: Handle millions of events per second across regions
🏗️ Architecture Overview¶
graph TB
subgraph "Event Sources"
Azure[Azure Services<br/>Storage, IoT, etc.]
Custom[Custom Applications]
SaaS[SaaS Providers]
end
subgraph "Event Grid"
Topics[Event Grid Topics]
System[System Topics]
Domains[Event Domains]
Filter[Advanced Filtering]
end
subgraph "Event Handlers"
Functions[Azure Functions]
Logic[Logic Apps]
Webhooks[Webhooks]
EventHub[Event Hubs]
Queue[Storage Queues]
ServiceBus[Service Bus]
end
Azure -->|System Events| System
Custom -->|Custom Events| Topics
SaaS -->|Partner Events| Topics
System --> Filter
Topics --> Filter
Domains --> Filter
Filter -->|Route| Functions
Filter -->|Route| Logic
Filter -->|Route| Webhooks
Filter -->|Route| EventHub
Filter -->|Route| Queue
Filter -->|Route| ServiceBus 💰 Pricing Tiers¶
🥉 Basic Tier¶
Best For: Standard event-driven workloads
Features:
- Operations pricing: $0.60 per million operations
- Standard throughput: Up to 10 MB/s ingress
- Event retention: 24 hours
- Public endpoints: HTTPS webhooks
- Filtering: Subject and basic filtering
Operations include: - Event publish - Subscription match and delivery - Advanced matching operations
🥇 Premium Tier¶
Best For: Enterprise workloads requiring enhanced security and performance
Additional Features:
- Private Link support: VNet integration
- IP firewall: Restrict access by IP
- Managed identity: Azure AD authentication
- Higher throughput: Increased limits
- Geo-disaster recovery: Multi-region support
🎯 Core Concepts¶
Topics and Event Subscriptions¶
graph LR
Publisher[Event Publisher] -->|Publish| Topic[Event Grid Topic]
Topic -->|Filter: type=user.created| Sub1[Subscription 1<br/>Azure Function]
Topic -->|Filter: type=order.*| Sub2[Subscription 2<br/>Logic App]
Topic -->|Filter: All events| Sub3[Subscription 3<br/>Event Hub] Custom Topics¶
Create custom topics for your application events:
# Create resource group
az group create --name rg-eventgrid --location eastus
# Create custom topic
az eventgrid topic create \
--name my-custom-topic \
--resource-group rg-eventgrid \
--location eastus
# Get topic endpoint
TOPIC_ENDPOINT=$(az eventgrid topic show \
--name my-custom-topic \
--resource-group rg-eventgrid \
--query endpoint -o tsv)
# Get topic key
TOPIC_KEY=$(az eventgrid topic key list \
--name my-custom-topic \
--resource-group rg-eventgrid \
--query key1 -o tsv)
Publish Events¶
from azure.eventgrid import EventGridPublisherClient
from azure.core.credentials import AzureKeyCredential
from azure.eventgrid import EventGridEvent
import datetime
# Initialize client
credential = AzureKeyCredential(topic_key)
client = EventGridPublisherClient(topic_endpoint, credential)
# Create events
events = [
EventGridEvent(
event_type="user.created",
data={
"user_id": "user-123",
"email": "user@example.com",
"created_at": datetime.datetime.utcnow().isoformat()
},
subject="users/user-123",
data_version="1.0"
),
EventGridEvent(
event_type="order.placed",
data={
"order_id": "order-456",
"total_amount": 99.99,
"items": 3
},
subject="orders/order-456",
data_version="1.0"
)
]
# Publish events
client.send(events)
print(f"Published {len(events)} events")
🔗 Event Subscriptions¶
Create Subscription to Azure Function¶
# Create Azure Function as event handler
az functionapp create \
--name eventgrid-handler \
--resource-group rg-eventgrid \
--storage-account mystorageaccount \
--consumption-plan-location eastus \
--runtime python \
--functions-version 4
# Create event subscription
az eventgrid event-subscription create \
--name user-events-subscription \
--source-resource-id $(az eventgrid topic show \
--name my-custom-topic \
--resource-group rg-eventgrid \
--query id -o tsv) \
--endpoint-type azurefunction \
--endpoint $(az functionapp function show \
--name eventgrid-handler \
--resource-group rg-eventgrid \
--function-name ProcessUserEvent \
--query invokeUrlTemplate -o tsv) \
--included-event-types "user.created" "user.updated"
Advanced Filtering¶
# Create subscription with advanced filtering
az eventgrid event-subscription create \
--name filtered-subscription \
--source-resource-id $(az eventgrid topic show \
--name my-custom-topic \
--resource-group rg-eventgrid \
--query id -o tsv) \
--endpoint https://mywebhook.example.com/api/events \
--advanced-filter data.order_amount NumberGreaterThan 100 \
--advanced-filter data.region StringIn westus eastus \
--subject-begins-with orders/ \
--subject-ends-with /completed
Filter Examples¶
{
"filter": {
"includedEventTypes": [
"Microsoft.Storage.BlobCreated",
"Microsoft.Storage.BlobDeleted"
],
"subjectBeginsWith": "/blobServices/default/containers/images/",
"subjectEndsWith": ".jpg",
"advancedFilters": [
{
"operatorType": "NumberGreaterThan",
"key": "data.contentLength",
"value": 1048576
},
{
"operatorType": "StringContains",
"key": "subject",
"values": ["prod", "production"]
}
]
}
}
🎯 Event Handlers¶
Azure Function Handler¶
import logging
import json
import azure.functions as func
def main(event: func.EventGridEvent):
"""Process Event Grid event in Azure Function."""
logging.info('Python EventGrid trigger processed an event')
# Parse event
event_data = event.get_json()
logging.info(f'Event Type: {event.event_type}')
logging.info(f'Event Subject: {event.subject}')
logging.info(f'Event Data: {json.dumps(event_data, indent=2)}')
# Process based on event type
if event.event_type == "user.created":
process_user_creation(event_data)
elif event.event_type == "order.placed":
process_order(event_data)
else:
logging.warning(f'Unknown event type: {event.event_type}')
def process_user_creation(data):
"""Handle user creation event."""
user_id = data.get('user_id')
email = data.get('email')
# Send welcome email
logging.info(f'Sending welcome email to {email}')
# Create user profile
logging.info(f'Creating profile for user {user_id}')
def process_order(data):
"""Handle order placement event."""
order_id = data.get('order_id')
total = data.get('total_amount')
logging.info(f'Processing order {order_id} for ${total}')
Webhook Handler¶
from flask import Flask, request, jsonify
import json
app = Flask(__name__)
@app.route('/api/events', methods=['POST', 'OPTIONS'])
def handle_event():
"""Webhook endpoint for Event Grid events."""
if request.method == 'OPTIONS':
# Handle validation handshake
return '', 200
if request.method == 'POST':
events = request.get_json()
# Handle validation event
for event in events:
if event['eventType'] == 'Microsoft.EventGrid.SubscriptionValidationEvent':
validation_code = event['data']['validationCode']
return jsonify({
'validationResponse': validation_code
})
# Process actual events
process_event(event)
return '', 200
def process_event(event):
"""Process individual event."""
event_type = event['eventType']
subject = event['subject']
data = event['data']
print(f"Event Type: {event_type}")
print(f"Subject: {subject}")
print(f"Data: {json.dumps(data, indent=2)}")
if __name__ == '__main__':
app.run(port=5000)
📚 Common Patterns¶
Fan-Out Pattern¶
Route single event to multiple handlers:
graph LR
Event[Order Placed Event] --> Topic[Event Grid Topic]
Topic --> Sub1[Email Service<br/>Send Confirmation]
Topic --> Sub2[Inventory Service<br/>Update Stock]
Topic --> Sub3[Analytics Service<br/>Track Metrics]
Topic --> Sub4[Notification Service<br/>SMS Alert] Event Aggregation¶
Collect events from multiple sources:
graph LR
subgraph "Sources"
Web[Web App Events]
Mobile[Mobile App Events]
API[API Events]
end
subgraph "Event Grid"
Topic[Central Topic]
end
subgraph "Handlers"
Analytics[Analytics Pipeline]
end
Web --> Topic
Mobile --> Topic
API --> Topic
Topic --> Analytics 🔒 Security¶
Authentication Methods¶
# Method 1: Access Key
from azure.eventgrid import EventGridPublisherClient
from azure.core.credentials import AzureKeyCredential
credential = AzureKeyCredential(topic_key)
client = EventGridPublisherClient(endpoint, credential)
# Method 2: Managed Identity (Premium tier)
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
client = EventGridPublisherClient(endpoint, credential)
Webhook Security¶
import hmac
import hashlib
import base64
def validate_event_grid_signature(request):
"""Validate Event Grid webhook signature."""
# Get signature from header
signature = request.headers.get('aeg-signature')
# Get shared secret
shared_secret = os.getenv('EVENTGRID_WEBHOOK_SECRET')
# Compute expected signature
payload = request.get_data()
expected = base64.b64encode(
hmac.new(
shared_secret.encode('utf-8'),
payload,
hashlib.sha256
).digest()
).decode('utf-8')
return hmac.compare_digest(signature, expected)
📊 Monitoring¶
Track Metrics¶
from azure.monitor.query import MetricsQueryClient
from azure.identity import DefaultAzureCredential
from datetime import datetime, timedelta
credential = DefaultAzureCredential()
client = MetricsQueryClient(credential)
# Query Event Grid metrics
resource_id = "/subscriptions/{sub}/resourceGroups/rg-eventgrid/providers/Microsoft.EventGrid/topics/my-custom-topic"
response = client.query_resource(
resource_id,
metric_names=["PublishSuccessCount", "PublishFailCount", "DeliverySuccessCount"],
timespan=timedelta(hours=1),
granularity=timedelta(minutes=5)
)
for metric in response.metrics:
print(f"{metric.name}: {metric.timeseries}")
Key Metrics¶
| Metric | Description | Threshold |
|---|---|---|
| PublishSuccessCount | Successfully published events | Monitor for drops |
| PublishFailCount | Failed publish attempts | Alert if > 0 |
| DeliverySuccessCount | Successfully delivered events | Compare with published |
| DeliveryFailCount | Failed delivery attempts | Alert if increasing |
| MatchedEventCount | Events matched to subscriptions | Monitor routing |
| DeadLetteredCount | Events sent to dead letter | Investigate failures |
🔗 Related Topics¶
Deep Dive Guides¶
- Event-driven Architecture - Design patterns and best practices
- System Topics - Azure service events
Integration Scenarios¶
Best Practices¶
- Reliability Patterns
- Security Configuration
- Performance Optimization
Last Updated: 2025-01-28 Service Version: General Availability Documentation Status: Complete