Event Buses, Rules & Pattern Matching
Every EventBridge integration is built from three calls: create or choose a bus, define a rule's pattern, and attach targets.
Busca en todas las páginas de la documentación
Every EventBridge integration is built from three calls: create or choose a bus, define a rule's pattern, and attach targets.
This page covers all three from both SDKs, plus the pattern-matching syntax that decides which events a rule actually fires on.
Create a rule with an event pattern, then attach targets. Publish events; matching ones fan out to every attached target.
# --- Python (boto3) ---
import boto3
import json
events = boto3.client("events")
events.put_rule(
Name="high-value-orders",
EventPattern=json.dumps({
"source": ["orders.api"],
"detail-type": ["OrderPlaced"],
"detail": {"total": [{"numeric": [">", 100]}]},
}),
)
events.put_targets(
Rule="high-value-orders",
Targets=[{"Id": "review-queue", "Arn": "arn:aws:sqs:us-east-1:111122223333:order-review"}],
)// --- TypeScript (AWS SDK v3) ---
import { EventBridgeClient, PutRuleCommand, PutTargetsCommand } from "@aws-sdk/client-eventbridge";
const events = new EventBridgeClient({});
await events.send(new PutRuleCommand({
Name: "high-value-orders",
EventPattern: JSON.stringify({
source: ["orders.api"],
"detail-type": ["OrderPlaced"],
detail: { total: [{ numeric: [">", 100] }] },
}),
}));
await events.send(new PutTargetsCommand({
Rule: "high-value-orders",
Targets: [{ Id: "review-queue", Arn: "arn:aws:sqs:us-east-1:111122223333:order-review" }],
}));When to reach for this:
Create a custom bus, a rule scoped to it, and two independent targets - a queue and a Step Functions workflow.
# --- Python (boto3) ---
import boto3
import json
events = boto3.client("events")
bus = events.create_event_bus(Name="orders-bus")
events.put_rule(
Name="order-placed-rule",
EventBusName="orders-bus",
EventPattern=json.dumps({
"source": ["orders.api"],
"detail-type": ["OrderPlaced"],
}),
State="ENABLED",
)
events.put_targets(
Rule="order-placed-rule",
EventBusName="orders-bus",
Targets=[
{
"Id": "audit-queue",
"Arn": "arn:aws:sqs:us-east-1:111122223333:order-audit",
},
{
"Id": "start-fulfillment",
"Arn": "arn:aws:states:us-east-1:111122223333:stateMachine:FulfillOrder",
"RoleArn": "arn:aws:iam::111122223333:role/eventbridge-invoke-sfn",
},
],
)// --- TypeScript (AWS SDK v3) ---
import {
EventBridgeClient,
CreateEventBusCommand,
PutRuleCommand,
PutTargetsCommand,
} from "@aws-sdk/client-eventbridge";
const events = new EventBridgeClient({});
await events.send(new CreateEventBusCommand({ Name: "orders-bus" }));
await events.send(new PutRuleCommand({
Name: "order-placed-rule",
EventBusName: "orders-bus",
EventPattern: JSON.stringify({
source: ["orders.api"],
"detail-type": ["OrderPlaced"],
}),
State: "ENABLED",
}));
await events.send(new PutTargetsCommand({
Rule: "order-placed-rule",
EventBusName: "orders-bus",
Targets: [
{
Id: "audit-queue",
Arn: "arn:aws:sqs:us-east-1:111122223333:order-audit",
},
{
Id: "start-fulfillment",
Arn: "arn:aws:states:us-east-1:111122223333:stateMachine:FulfillOrder",
RoleArn: "arn:aws:iam::111122223333:role/eventbridge-invoke-sfn",
},
],
}));What this demonstrates:
orders-bus) scopes the rule away from the account's default bus and any unrelated events on it.State: "ENABLED" (the default) means the rule is live immediately; set "DISABLED" to stage it without firing.RoleArn so EventBridge is authorized to call StartExecution on your behalf.An EventPattern is JSON matched structurally against an event's top-level fields (source, detail-type, account, region) and anything inside detail. Every array is an implicit OR: "source": ["orders.api", "billing.api"] matches either. Matching is AND across fields: an event must satisfy every key present in the pattern.
Content filters go beyond exact match. Common operators:
{
"detail": {
"total": [{ "numeric": [">", 100] }],
"status": [{ "anything-but": ["cancelled"] }],
"region": [{ "prefix": "us-" }]
}
}numeric compares numbers, anything-but excludes values, prefix matches string prefixes, and plain arrays do exact-value matching. A pattern with no operator on a field requires an exact match against one of the listed values.
The default bus already exists per account and per region, and it is the one AWS services publish to automatically (for example, EC2 state-change notifications). A custom bus is created with CreateEventBus purely for organizational isolation - your own application's events live there, separate from AWS-service noise and other teams' rules. Rules, targets, and permissions are all scoped per bus, so nothing on orders-bus interferes with anything on default.
PutTargets can attach up to five targets per rule (more with a service quota increase). Every attached target that a rule matches is invoked - there is no sequencing, no shared state, and no guarantee one finishes before another starts. If a target fails, EventBridge retries that target on its own retry policy; other targets on the same rule are unaffected.
# --- Python (boto3) ---
import boto3
events = boto3.client("events")
for page in events.get_paginator("list_rules").paginate(EventBusName="orders-bus"):
for rule in page["Rules"]:
print(rule["Name"], rule["State"])
events.remove_targets(Rule="order-placed-rule", EventBusName="orders-bus", Ids=["audit-queue"])
events.delete_rule(Name="order-placed-rule", EventBusName="orders-bus")// --- TypeScript (AWS SDK v3) ---
import {
EventBridgeClient,
paginateListRules,
RemoveTargetsCommand,
DeleteRuleCommand,
} from "@aws-sdk/client-eventbridge";
const events = new EventBridgeClient({});
for await (const page of paginateListRules({ client: events }, { EventBusName: "orders-bus" })) {
for (const rule of page.Rules ?? []) console.log(rule.Name, rule.State);
}
await events.send(new RemoveTargetsCommand({ Rule: "order-placed-rule", EventBusName: "orders-bus", Ids: ["audit-queue"] }));
await events.send(new DeleteRuleCommand({ Name: "order-placed-rule", EventBusName: "orders-bus" }));Remove targets before deleting a rule - DeleteRule fails if targets are still attached.
PutRule time. Fix: test the pattern with TestEventPattern against a sample event before relying on it.EventBusName on a custom bus. Rule and target calls default to the default bus if omitted. Fix: pass EventBusName consistently across PutRule, PutTargets, and PutEvents.DeleteRule rejects the call. Fix: call RemoveTargets (or RemoveTargets with Force, depending on target type) first.RoleArn on a Step Functions or Kinesis target. The target silently fails to invoke. Fix: attach an IAM role EventBridge can assume with permission to invoke that target.detail fields are typed. Pattern matching on detail compares against whatever type the JSON actually contains (string vs number). Fix: keep event producers consistent about field types.| Alternative | Use When | Don't Use When |
|---|---|---|
| EventBridge rule + targets | Independent consumers reacting to the same event | Consumers must run in a dependent order |
| SNS topic | Simple fan-out with no content-based filtering needed | You need to filter on nested JSON fields |
| SQS direct integration | A single known consumer polling a queue | Multiple decoupled consumers should react |
| Step Functions as the sole entry point | The reaction is itself a multi-step, ordered process | A single independent action is all that's needed |
No. The default bus works for most use cases. A custom bus is worth creating when you want to isolate an application's rules from AWS-service events and other teams' traffic.
Arrays are OR - "source": ["a", "b"] matches either. Multiple top-level keys are AND - all listed fields must match for the rule to fire.
Yes, using content-based filters like {"numeric": [">", 100]}, {"prefix": "us-"}, or {"anything-but": ["cancelled"]} inside the pattern.
Up to five by default, and all of them are invoked independently when the rule matches - there is no ordering guarantee between them.
Almost always a pattern mismatch - wrong bus, a typo in a key, or a value that doesn't match any array entry. Use TestEventPattern against a real sample event to debug it before assuming EventBridge itself is broken.
No, DeleteRule fails while targets remain attached. Call RemoveTargets with the target IDs first.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Revisado por Chris St. John·Última actualización: 23 jul 2026