AWS EventBridge: Event-Driven Architecture on AWS (2026)
AWS EventBridge is a serverless event bus that connects applications using events. Originally launched as CloudWatch Events, it evolved into the backbone of AWS's event-driven story — supporting custom events, partner integrations from Stripe and Datadog, sophisticated event filtering, schema discovery, point-to-point Pipes, and a fully managed Scheduler. If you're building microservices, integrating SaaS data, or replacing cron-based workflows, EventBridge is the right starting point in 2026.
EventBridge vs SNS vs SQS
These three services are frequently confused. They serve different roles and the right choice depends on your routing needs, subscriber model, and whether you need filtering.
| Feature | EventBridge | SNS | SQS |
|---|---|---|---|
| Primary model | Event bus (pub/sub with routing) | Fan-out (pub/sub) | Queue (point-to-point) |
| Message filtering | Rich JSON content filtering | Attribute-based filtering | None (SQS itself) |
| Max targets per rule | 5 (expandable) | Unlimited subscribers | 1 consumer group |
| SaaS integrations | Yes (Stripe, GitHub, Datadog) | No | No |
| Schema discovery | Yes | No | No |
| Replay events | Yes (archive + replay) | No | No |
| Delivery guarantee | At-least-once | At-least-once | At-least-once |
| Latency | ~0.5s typical | ~10ms | Polling-based |
| Best use case | Cross-service routing, SaaS integration, audit events | Fan-out to many subscribers | Decoupled async processing, work queues |
Event Buses
EventBridge has three types of event buses:
- Default bus: Receives events from AWS services (EC2 state changes, CodePipeline events, Scheduled Events). Cannot be deleted.
- Custom buses: For your own application events. Create one per domain or per microservice.
- Partner buses: Receive events from SaaS partners (Stripe payment events, GitHub push events, Auth0 login events). Requires partner setup.
# Create a custom event bus
aws events create-event-bus \
--name "ecommerce-orders" \
--region us-east-1
# Put a custom event onto the bus
aws events put-events \
--entries '[
{
"Source": "com.mystore.orders",
"DetailType": "OrderPlaced",
"Detail": "{\"orderId\":\"ORD-001\",\"customerId\":\"CUST-123\",\"totalAmount\":249.99,\"currency\":\"USD\"}",
"EventBusName": "ecommerce-orders"
}
]'
Event Patterns and Filtering
Event patterns are the most powerful feature of EventBridge. They let you filter millions of events and only trigger rules on the subset that matters, without any compute cost for filtered events.
{
"source": ["com.mystore.orders"],
"detail-type": ["OrderPlaced"],
"detail": {
"currency": ["USD", "EUR"],
"totalAmount": [{ "numeric": [">", 100, "<=", 10000] }],
"customerId": [{ "prefix": "CUST-" }],
"fraudScore": [{ "exists": false }]
}
}
EventBridge supports these matching operators:
- Exact match:
["value1", "value2"] - Prefix:
[{ "prefix": "CUST-" }] - Suffix:
[{ "suffix": ".pdf" }] - Numeric range:
[{ "numeric": [">=", 0, "<", 100] }] - Exists check:
[{ "exists": true }]or[{ "exists": false }] - Anything-but:
[{ "anything-but": ["CANCELLED", "REFUNDED"] }] - IP address CIDR:
[{ "cidr": "10.0.0.0/8" }]
Rules and Targets
Rules bind an event pattern to one or more targets. You can add up to 5 targets per rule. Targets include Lambda, SQS, SNS, Step Functions, API Gateway, Kinesis, ECS tasks, CodePipeline, and cross-account event buses.
# Create a rule on a custom bus
aws events put-rule \
--name "HighValueOrders" \
--event-bus-name "ecommerce-orders" \
--event-pattern '{
"source": ["com.mystore.orders"],
"detail-type": ["OrderPlaced"],
"detail": {
"totalAmount": [{ "numeric": [">", 500] }]
}
}' \
--state ENABLED
# Add Lambda as a target with input transformation
aws events put-targets \
--rule "HighValueOrders" \
--event-bus-name "ecommerce-orders" \
--targets '[
{
"Id": "FraudCheckLambda",
"Arn": "arn:aws:lambda:us-east-1:123456789012:function:FraudCheck",
"InputTransformer": {
"InputPathsMap": {
"orderId": "$.detail.orderId",
"amount": "$.detail.totalAmount"
},
"InputTemplate": "{\"orderId\": \"\", \"amount\": , \"priority\": \"HIGH\"}"
}
},
{
"Id": "FraudCheckSQS",
"Arn": "arn:aws:sqs:us-east-1:123456789012:fraud-review-queue"
}
]'
For cross-account event routing, add the target account's event bus ARN as a target. The target account must grant events:PutEvents permission to the source account via a resource policy.
Schema Registry and Code Bindings
The EventBridge Schema Registry auto-discovers schemas from events flowing through your buses and generates strongly-typed code bindings in Python, Java, TypeScript, and Go.
# Enable schema discovery on a bus
aws schemas create-discoverer \
--source-arn "arn:aws:events:us-east-1:123456789012:event-bus/ecommerce-orders" \
--description "Auto-discover order event schemas"
# List discovered schemas
aws schemas list-schemas \
--registry-name "discovered-schemas"
# Download code bindings for Python
aws schemas get-code-binding-source \
--registry-name "discovered-schemas" \
--schema-name "com.mystore.orders@OrderPlaced" \
--language "Python36" \
--outfile order_placed_binding.zip
EventBridge Pipes
EventBridge Pipes connects a source (SQS, Kinesis, DynamoDB Streams, Kafka) to a target with optional filtering and enrichment — without writing any glue code. Each pipe has four stages: source → filter → enrichment → target.
# Create a pipe: DynamoDB Streams → filter → Lambda enrichment → EventBridge bus
aws pipes create-pipe \
--name "OrderStreamToEventBridge" \
--role-arn "arn:aws:iam::123456789012:role/PipesRole" \
--source "arn:aws:dynamodb:us-east-1:123456789012:table/Orders/stream/2026-01-01T00:00:00.000" \
--source-parameters '{
"DynamoDBStreamParameters": {
"StartingPosition": "LATEST",
"BatchSize": 10
},
"FilterCriteria": {
"Filters": [
{ "Pattern": "{\"dynamodb\":{\"NewImage\":{\"status\":{\"S\":[\"CONFIRMED\"]}}}}" }
]
}
}' \
--enrichment "arn:aws:lambda:us-east-1:123456789012:function:EnrichOrderEvent" \
--target "arn:aws:events:us-east-1:123456789012:event-bus/ecommerce-orders" \
--target-parameters '{
"EventBridgeEventBusParameters": {
"DetailType": "OrderConfirmed",
"Source": "com.mystore.dynamodb"
}
}'
EventBridge Scheduler
EventBridge Scheduler replaced CloudWatch Events cron rules in 2022 and is now the recommended way to schedule AWS API calls. It supports one-time schedules, cron expressions, and rate expressions with timezone awareness.
# One-time schedule: trigger a Lambda at a specific time
aws scheduler create-schedule \
--name "FlashSaleStart" \
--schedule-expression "at(2026-07-04T12:00:00)" \
--schedule-expression-timezone "America/New_York" \
--flexible-time-window '{"Mode": "OFF"}' \
--target '{
"Arn": "arn:aws:lambda:us-east-1:123456789012:function:StartFlashSale",
"RoleArn": "arn:aws:iam::123456789012:role/SchedulerRole",
"Input": "{\"saleId\":\"FLASH-2026-JULY4\",\"discountPercent\":20}"
}'
# Recurring schedule: nightly report every day at 2am UTC
aws scheduler create-schedule \
--name "NightlyOrderReport" \
--schedule-expression "cron(0 2 * * ? *)" \
--flexible-time-window '{"Mode": "FLEXIBLE", "MaximumWindowInMinutes": 15}' \
--target '{
"Arn": "arn:aws:states:::aws-sdk:lambda:invoke",
"RoleArn": "arn:aws:iam::123456789012:role/SchedulerRole",
"Input": "{\"FunctionName\":\"GenerateOrderReport\"}"
}'
FLEXIBLE time window lets the Scheduler distribute executions over a window (up to 15 minutes) to avoid thundering herds when many schedules fire at the same time. Use it for non-latency-sensitive batch jobs.Replay and Archiving
EventBridge archives let you retain events for debugging, testing, and disaster recovery. You can replay archived events to any rule or a new bus — invaluable when you add a new microservice and need to catch up on historical events.
# Create an archive for the orders bus (retain 30 days)
aws events create-archive \
--archive-name "ecommerce-orders-archive" \
--event-source-arn "arn:aws:events:us-east-1:123456789012:event-bus/ecommerce-orders" \
--retention-days 30 \
--event-pattern '{
"source": ["com.mystore.orders"]
}'
# Replay events from a time range
aws events start-replay \
--replay-name "replay-may-orders" \
--source-archive-arn "arn:aws:events:us-east-1:123456789012:archive/ecommerce-orders-archive" \
--event-start-time 2026-05-01T00:00:00Z \
--event-end-time 2026-05-31T23:59:59Z \
--destination '{
"Arn": "arn:aws:events:us-east-1:123456789012:event-bus/ecommerce-orders-replay"
}'
Real Example: E-Commerce Order Events
Here's a complete Python producer using boto3 that publishes order events, plus a Lambda consumer that processes them.
import boto3
import json
from datetime import datetime
events_client = boto3.client('events', region_name='us-east-1')
def publish_order_event(order_id: str, customer_id: str, items: list, total: float):
"""Publish an OrderPlaced event to the ecommerce-orders bus."""
event = {
'orderId': order_id,
'customerId': customer_id,
'items': items,
'totalAmount': total,
'currency': 'USD',
'placedAt': datetime.utcnow().isoformat() + 'Z',
'channel': 'WEB'
}
response = events_client.put_events(
Entries=[
{
'Source': 'com.mystore.orders',
'DetailType': 'OrderPlaced',
'Detail': json.dumps(event),
'EventBusName': 'ecommerce-orders'
}
]
)
failed = response.get('FailedEntryCount', 0)
if failed > 0:
raise RuntimeError(f"Failed to publish {failed} event entries: {response['Entries']}")
return response['Entries'][0]['EventId']
# Lambda handler — receives the OrderPlaced event
def lambda_handler(event, context):
detail = event.get('detail', {})
order_id = detail['orderId']
total = detail['totalAmount']
print(f"Processing order {order_id} for ${total}")
if total > 500:
trigger_fraud_check(order_id, total)
send_confirmation_email(detail['customerId'], order_id)
return {'statusCode': 200, 'body': f'Processed order {order_id}'}
def trigger_fraud_check(order_id, amount):
events_client.put_events(Entries=[{
'Source': 'com.mystore.fraud',
'DetailType': 'FraudCheckRequested',
'Detail': json.dumps({'orderId': order_id, 'amount': amount}),
'EventBusName': 'ecommerce-orders'
}])
def send_confirmation_email(customer_id, order_id):
ses = boto3.client('ses')
# SES send logic here
print(f"Sent confirmation to customer {customer_id} for order {order_id}")
FAQ
Q: What is the delivery guarantee for EventBridge?
EventBridge delivers events at-least-once. For targets that fail, it retries with exponential backoff for up to 24 hours. You can configure a Dead Letter Queue (DLQ) on a target to capture events that exhaust retries. Your consumers should be idempotent — use the event ID (available as $.id in the event envelope) as an idempotency key.
Q: How much does EventBridge cost?
Custom events cost $1.00 per million events published. Events from AWS services on the default bus are free. Schema discovery is free; schema registrations cost $0.10 per schema per month after the first 5. EventBridge Pipes cost $0.40 per million events processed. The Scheduler costs $1.00 per million invocations (first 14 million are free per month).
Q: Can I use EventBridge for cross-account event routing?
Yes. Add the target account's event bus ARN as a rule target. The target account must add a resource-based policy to its event bus granting events:PutEvents to the source account. Cross-region routing works the same way — just specify the full ARN including the target region.
Q: What's the maximum event size for EventBridge?
256 KB per event. If your events are larger, store the payload in S3 and put a reference (S3 bucket + key) in the event detail. The consumer Lambda fetches the full payload from S3. This pattern is sometimes called "claim check."
Q: How do I test EventBridge rules locally?
Use the aws events test-event-pattern CLI command to verify a pattern matches a given event without creating any rules. For integration tests, the LocalStack emulator supports EventBridge, or you can use a dedicated test event bus in your AWS account and replay events against it.