Skip to content
AWS aws serverless 5 min read

Amazon EventBridge

Amazon EventBridge is a serverless event bus. An event is just a small JSON message that says “something happened” — for example, an order was placed, a file was uploaded, or an EC2 instance changed state. EventBridge receives these events and routes each one to the right destinations (called targets) based on rules you define. It matters because it lets you connect many services together without wiring them directly to each other, so your system stays loosely coupled and easy to change.

What EventBridge actually does

Think of EventBridge as a smart post office for events. Producers (your apps, AWS services, or SaaS apps) drop events onto a bus. EventBridge looks at the JSON content of each event, compares it against your rules, and forwards matching events to one or more targets — such as a Lambda function, an SQS queue (Simple Queue Service, a message queue), a Step Functions workflow, or another event bus.

The key idea is content-based routing. Unlike a simple topic where everything published goes to everyone subscribed, EventBridge inspects the data inside each event and only delivers it where the pattern matches. This is what makes it a true many-to-many router.

There are three kinds of buses:

Bus typeWhat it carriesWhen to use
Default busEvents from AWS services in your accountReacting to AWS activity (e.g. EC2 state changes)
Custom busYour own application eventsDecoupling your own microservices
Partner busEvents from SaaS partners (Datadog, Shopify, etc.)Reacting to third-party SaaS events

Rules and event patterns

A rule ties an event pattern to one or more targets. The event pattern is a small JSON document that describes which events you care about. EventBridge matches the incoming event against this pattern field by field.

Here is a pattern that matches only failed orders over $500:

{
  "source": ["com.myshop.orders"],
  "detail-type": ["OrderPlaced"],
  "detail": {
    "status": ["FAILED"],
    "amount": [{ "numeric": [">", 500] }]
  }
}

When to use this: any time different parts of your system need to react to the same event differently — one rule sends big failed orders to a fraud queue, another logs all orders to a data lake. When NOT to: if every subscriber wants every message with no filtering, a plain SNS topic (see below) is simpler and cheaper.

Create a rule — Console

  1. Open the EventBridge console and choose Buses then Rules.
  2. Pick your event bus (e.g. default or your custom bus), then Create rule.
  3. Give it a name like big-failed-orders, choose Rule with an event pattern.
  4. Under Event pattern, paste the JSON pattern above.
  5. Choose a target — for example Lambda function — and pick your function.
  6. Review and Create rule.

Create a rule — AWS CLI

aws events put-rule \
  --name big-failed-orders \
  --event-bus-name default \
  --event-pattern '{"source":["com.myshop.orders"],"detail-type":["OrderPlaced"],"detail":{"status":["FAILED"]}}'

aws events put-targets \
  --rule big-failed-orders \
  --event-bus-name default \
  --targets 'Id=1,Arn=arn:aws:lambda:us-east-1:111122223333:function:handle-fraud'

Output:

{
    "RuleArn": "arn:aws:events:us-east-1:111122223333:rule/big-failed-orders"
}
{
    "FailedEntryCount": 0,
    "FailedEntries": []
}

Publishing your own events

Your application sends events with put-events. Each entry needs a Source, a DetailType, and a Detail (the JSON payload).

aws events put-events --entries '[
  {
    "Source": "com.myshop.orders",
    "DetailType": "OrderPlaced",
    "Detail": "{\"orderId\":\"o-0a1b2c3d\",\"status\":\"FAILED\",\"amount\":750}",
    "EventBusName": "default"
  }
]'

Output:

{
    "FailedEntryCount": 0,
    "Entries": [
        { "EventId": "9f8e7d6c-5b4a-3210-fedc-ba9876543210" }
    ]
}

Delivery guarantees — the big gotcha

EventBridge gives at-least-once delivery and only best-effort ordering. This means a target can occasionally receive the same event twice, and events may not arrive in the exact order they were sent. Always design your targets to be idempotent — processing the same event twice must produce the same result. A common trick is to record each EventId you have already handled and skip duplicates.

If a target fails, EventBridge retries with exponential backoff for up to 24 hours. Attach a dead-letter queue (an SQS queue that captures events that could never be delivered) so you never silently lose data.

Schema registry, archive and replay

The schema registry stores the structure (the shape of the JSON) of your events. EventBridge can auto-discover schemas from events flowing through a bus, then generate typed code bindings for Java, Python, or TypeScript so your code stops guessing field names.

Archive and replay lets you keep a copy of events for a chosen retention period and re-send them later. This is invaluable for testing a new consumer against real historical traffic or recovering after a bug.

aws events create-archive \
  --archive-name orders-archive \
  --event-source-arn arn:aws:events:us-east-1:111122223333:event-bus/default \
  --retention-days 30

EventBridge Scheduler

EventBridge Scheduler runs a target on a schedule — either a fixed rate, a cron expression, or a one-time future time. It is the modern replacement for the older CloudWatch Events scheduled rules and scales to millions of schedules.

aws scheduler create-schedule \
  --name nightly-report \
  --schedule-expression 'cron(0 2 * * ? *)' \
  --flexible-time-window '{"Mode":"OFF"}' \
  --target '{"Arn":"arn:aws:lambda:us-east-1:111122223333:function:nightly-report","RoleArn":"arn:aws:iam::111122223333:role/scheduler-role"}'

When to use this: cron jobs, sending a daily digest, expiring records at a specific timestamp. When NOT to: reacting to something that just happened — that is a normal rule, not a schedule.

EventBridge vs SNS — choose by filtering needs

EventBridgeSNSSQS
ModelMany-to-many event routerPub/sub fan-outPoint-to-point queue
RoutingRich content-based filtering on full JSONSimple message-attribute filteringNone (poll messages)
Targets35+ AWS services, SaaS, API destinationsHTTP, Lambda, SQS, email, SMSConsumers that poll
OrderingBest-effortBest-effort (FIFO option)FIFO option available
Latency~Half a second typicalLower (sub-100ms)Low
Best forDecoupling with smart routingCheap, low-latency fan-outBuffering / work queues

Pick EventBridge when you need rich filtering, schema tooling, or to connect SaaS apps. Pick SNS for simple, fast fan-out to a few subscribers. They are often used together: SNS for speed, EventBridge where routing logic earns its keep.

Cost note: EventBridge charges about $1.00 per million custom events published (AWS-service events on the default bus are free). Scheduler is about $1.00 per million invocations after a free tier of 14 million per month. At small scale this is effectively free.

Best practices

  • Make every target idempotent — dedupe on EventId because delivery is at-least-once.
  • Always attach a dead-letter queue to rules so failed events are never lost.
  • Use a custom bus per domain (orders, billing) instead of overloading the default bus.
  • Keep event payloads small; put large data in S3 and send a pointer in the event.
  • Enable the schema registry and generate code bindings to avoid typos in field names.
  • Use EventBridge Scheduler (not legacy scheduled rules) for new cron-style work.
  • Scope target IAM roles tightly — grant only the permissions each target truly needs.
Last updated June 15, 2026
Was this helpful?