EventBridge rule patterns are the secret sauce for getting precisely the events you want, and most people use them like a blunt instrument when they could be using a scalpel.
Let’s say you’ve got a stream of aws.ec2 events, and you’re specifically interested in instances that have just been stopped. You don’t want running, you don’t want terminated, you want stopped. Here’s a snippet of an event you might see:
{
"version": "0",
"id": "a1b2c3d4-e5f6-7890-1234-abcdef123456",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "123456789012",
"time": "2023-10-27T10:00:00Z",
"region": "us-east-1",
"resources": [
"arn:aws:ec2:us-east-1:123456789012:instance/i-0abcdef1234567890"
],
"detail": {
"instance-id": "i-0abcdef1234567890",
"state": "stopped",
"reason": "User initiated stop",
"tags": [
{
"key": "Name",
"value": "MyWebServer"
}
]
}
}
Now, how do you write a pattern to only catch that stopped state change?
The most basic pattern uses source and detail-type:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"]
}
This gets you all EC2 instance state changes, which is too broad. We need to dive into the detail field. To match a specific value within a field, you simply specify it:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["stopped"]
}
}
This is much better. It targets only events where the state field inside detail is exactly "stopped".
But what if you want to be even more specific? Maybe you only care about instances in a particular region, or instances with a specific tag. Let’s say you want to catch stopped instances in us-west-2:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"region": ["us-west-2"],
"detail": {
"state": ["stopped"]
}
}
Notice how region is a top-level field in the event, so it’s matched at that level.
Now, let’s get fancy with tags. Tags are a list of objects. To match a tag, you need to specify the key and value within the tags array. If you want to match an instance with the tag Environment set to Production:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["stopped"],
"tags": [
{
"key": "Environment",
"value": "Production"
}
]
}
}
This pattern will only trigger if the stopped instance has at least the Environment: Production tag. If it has other tags, that’s fine.
What if you need to match a tag and a specific instance ID? You can combine them:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"instance-id": ["i-0abcdef1234567890"],
"state": ["stopped"],
"tags": [
{
"key": "Environment",
"value": "Production"
}
]
}
}
This rule will only match if the i-0abcdef1234567890 instance is stopped and has the Environment: Production tag.
The power of EventBridge patterns really shines when you understand that you can use:
- Exact string matching (e.g.,
"state": ["stopped"]) - Wildcards for multiple values (e.g.,
"state": ["stopped", "pending"]) - Prefix matching for strings (e.g.,
"instance-id": ["prefix:i-0abcdef"]) – this matches anyinstance-idstarting withi-0abcdef. - Numeric ranges (e.g.,
"port": [{"numeric": [">", 8080]}]) – useful for CloudTrail data events. - Anything-but matching (e.g.,
"state": [{"anything-but": ["terminated"]}]) – this matches any state exceptterminated.
Consider this pattern that captures any EC2 instance state change except for instances being terminated:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": [{"anything-but": ["terminated"]}]
}
}
This is incredibly powerful for creating general alerts for operational issues without being noisy about normal shutdown events.
The most common pitfall is trying to match nested fields without specifying the full path. For example, if you try to match tags.key directly, it won’t work because tags is an array. You must match the structure of the array itself, as shown in the tags examples above. EventBridge evaluates array matches by checking if any element in the event’s array satisfies the pattern’s array specification.
When you’re debugging your patterns, use the EventBridge console’s "Test pattern" feature. You can paste in a sample event and see if your pattern matches it. This is invaluable for iterating quickly.
Once you’ve got your rule matching exactly what you need, the next thing you’ll wrestle with is ensuring your target (like a Lambda function or SQS queue) can actually process the event data, which often involves understanding how to extract specific fields from the event payload within your target’s code.