CloudBrum
CloudBrum · Cloud decision-support platform
AWS App modernization

Amazon EventBridgeLast reviewedReading time~12 minLevelBeginner to advanced

Amazon Web Services · App modernization · Event bus, rules, Pipes and Scheduler

EventBridge is the part of AWS that hears that something happened and tells whoever asked to know. A rule matches an event, such as an order placed or an instance stopped, and sends it to a target like a Lambda function, a queue or another account. The sender never learns who is listening, which is the point and also why debugging takes practice. Each event costs very little, but a chatty producer, a replay or a rule that matches too much can still surprise the bill.

On this page (17 sections)

    Mind map: Amazon EventBridge at a glance

    Amazon EventBridge mind map Amazon EventBridge at a glance: Event buses: Default bus, Custom buses, Partner buses; Rules: Event patterns, Up to five targets, Cross-account sends; Pipes: Queue and stream sources, Filter and enrich, One target; Scheduler: One-time schedules, Recurring and cron, Time zones; Reliability: Retries, Dead-letter queues, Archive and replay; Event shape: Event envelope, Schema registry, Input transformers; Security: Bus resource policy, IAM roles, KMS encryption; Pricing: Per custom event, Pipes requests, Archive and replay. Amazon EventBridge at a glance Event-driven integration on AWS: the main building blocks and decisions CloudBrum Cloud decision-support platform CloudBrum Default bus Custom buses Partner buses Event buses Event patterns Up to five targets Cross-account sends Rules Queue and stream sources Filter and enrich One target Pipes One-time schedules Recurring and cron Time zones Scheduler Retries Dead-letter queues Archive and replay Reliability Event envelope Schema registry Input transformers Event shape Bus resource policy IAM roles KMS encryption Security Per custom event Pipes requests Archive and replay Pricing EventBridge17-point analysis CloudBrum· 17-point cloud service analysis cloudbrum.com
    CloudBrum EventBridge at a glance · 17-point analysis Event buses Default bus Custom buses Partner buses Rules Event patterns Up to five targets Cross-account sends Pipes Queue and stream sources Filter and enrich One target Scheduler One-time schedules Recurring and cron Time zones Reliability Retries Dead-letter queues Archive and replay Event shape Event envelope Schema registry Input transformers Security Bus resource policy IAM roles KMS encryption Pricing Per custom event Pipes requests Archive and replay CloudBrum · cloudbrum.com

    Free to share. The downloaded image includes the CloudBrum link.

    Key features (summary)

    • AWS events for freeMany AWS services put events on your default bus on their own: an EC2 instance changing state, a build finishing, a management API call. A rule can react without a line of code to poll for it.
    • Your own events on custom busesCall PutEvents from your code with a source, a detail type and a JSON detail. Each domain can have its own bus, with its own permissions and its own archive.
    • Rules that read the contentA pattern can look at any field of the event: exact values, prefixes, numeric ranges, exists checks, anything-but and wildcards. The filtering happens in the service, so consumers only see what they asked for.
    • Many kinds of targetOne rule sends to up to five targets. Lambda, SQS, SNS, Step Functions, Kinesis, another bus (in this or another account or Region) and HTTPS endpoints through API destinations are all supported.
    • Reshape before deliveryAn input transformer picks fields out of the event and builds the message the target expects, so a legacy consumer doesn’t need to learn the full event.
    • Pipes for point-to-pointA pipe reads from a queue or stream (SQS, Kinesis, DynamoDB streams, Kafka, Amazon MQ), filters, optionally enriches with a call to Lambda or an API, and delivers to one target. No glue code in between.
    • SchedulerOne-time and recurring schedules with time zones and an optional flexible window. It is built for very large numbers of schedules, which is where cron rules on a bus fall short.
    • Archive and replayAn archive keeps events from a bus for as long as you choose. When a consumer had a bug, fix it and replay a time window back onto the bus.

    Basic concepts

    Event
    A JSON record that something happened. The envelope has fixed fields (source, detail-type, time, account, region, resources) and a free-form detail object that you design.
    Event bus
    The channel events are sent to. Every account has a default bus for AWS events. You can add custom buses for your own events and partner buses for SaaS providers.
    Rule
    Belongs to one bus. It either matches events with a pattern or fires on a schedule, and sends what it matches to up to five targets.
    Event pattern
    A JSON document that looks like the events it wants. Every field you list must match, and a list of values means any of them.
    Target
    Where a rule delivers: a function, a queue, a topic, a state machine, a stream, another bus or an HTTPS endpoint. Each target has its own role or resource policy.
    Input transformer
    Pulls values from the event with paths and builds a new message from a template, so the target gets the shape it needs.
    Dead-letter queue (DLQ)
    An SQS queue that keeps events a target never accepted, after the retries ran out. Without one, an undeliverable event is dropped.
    Retry policy
    How long and how often EventBridge retries a failed delivery. The default is up to 24 hours and 185 attempts, and you can shorten both per target.
    Archive and replay
    An archive stores events from one bus, optionally filtered by a pattern. A replay sends a chosen time window back to the same bus, and replayed events carry a replay-name so consumers can tell.
    Schema registry
    A catalogue of event structures. Discovery can infer schemas from the events on a bus, and code bindings can be generated from them.
    API destination
    An HTTPS endpoint with stored credentials (basic, API key or OAuth) and a rate limit, so a rule can call a web service and not only AWS services.
    Pipe
    A managed connection from one source to one target, with a filter and an optional enrichment step between them.
    EventBridge Scheduler
    The scheduling service for one-time and recurring invocations. A schedule has a target, a role, a time zone and an optional flexible window.

    How to create & configure it

    Create a bus, a rule and a safe target with the AWS CLI

    1. Name your events firstPick a source (for example com.example.orders) and a detail-type (OrderPlaced), and sketch the fields in detail. These names are a contract, so settle them before anyone consumes them.
    2. Create a custom busKeep your own events off the default bus. One bus per domain or per environment is a common starting point.
    3. Prepare the target and its dead-letter queueCreate the queue the consumer reads from and a second queue for events that cannot be delivered.
    4. Write the pattern and test itDescribe only the events the consumer needs, for example orders with a total of 1000 or more. Run the pattern against a sample event with test-event-pattern before it goes live.
    5. Let the rule send to the targetQueues and topics need a resource policy that names the rule. Functions need permission for events.amazonaws.com. Without this the rule matches and nothing arrives.
    6. Attach the target with retries and a DLQDecide how long delivery may be retried. An hour is plenty for most consumers, and a day is the default.
    7. Turn on an archiveKeep a few weeks of events on the bus. It costs little and lets you replay after a consumer bug.
    8. Send a test event and read the answerPutEvents can succeed as a call while a single entry fails. Check FailedEntryCount and the per-entry results, then look in the queue.
    9. Watch the rule’s metricsFailedInvocations, InvocationsFailedToBeSentToDlq and ThrottledRules tell you what the console hides. Alarm on them.

    Tip: put-targets accepts a target the rule isn’t allowed to call. The failure shows up later as FailedInvocations, so send a test event and check the metric before you call the setup done. See the code references for the same setup as Terraform.

    Common issues after configuration

    SymptomLikely causeWhat to check / fix
    The rule never firesThe pattern doesn’t match the real event (values are case-sensitive and every listed field must match), the event went to another bus, or the rule is disabledCompare the pattern with an actual event from the archive or a log rule. Check the bus name, then run test-event-pattern.
    The rule matches, but the target receives nothingThe target’s resource policy or role doesn’t allow EventBridge, or the target is deleted or throttlingLook at FailedInvocations for the rule. Add the permission for the rule’s ARN and read the dead-letter queue.
    PutEvents returns success, yet events are missingThe call returned FailedEntryCount above zero, or an entry was rejected for size or a missing fieldRead the per-entry results and retry the failed ones. Split large batches and keep the whole request under the size limit.
    Events reach another account but trigger nothingThe receiving bus has no resource policy that allows the sender, or the rule that forwards the event lacks a roleAdd a bus policy for the sending account or organisation, and give the sending rule a role that may call PutEvents on the target bus.
    A consumer sees the same event twiceDelivery is at least once, and retries or a replay can send an event againMake the consumer idempotent: store the event id or a business key, and ignore what you’ve already handled.
    Events arrive in a different orderThe bus doesn’t guarantee orderPut a version or a sequence number in the detail and let the consumer ignore stale ones. For ordered sources use a pipe from a stream or a FIFO queue.
    ThrottledRules goes upMore events match than the target or the account rate allowsSpread targets across several rules, add a queue between the bus and a slow consumer, and ask for a higher quota if the volume is real.
    A schedule runs one hour offA rule’s cron is in UTC, so a local time shifts when daylight saving changesUse Scheduler with an explicit time zone, and avoid the hour that doesn’t exist or happens twice.
    A replay triggers side effects againA replay goes through the same rules and targets as live eventsPause or filter the rules that send emails or charge cards, check for the replay-name field, and keep consumers idempotent.
    An API destination returns 401 or 429The stored credentials expired, or the endpoint limits requestsRefresh the connection secret, and set the destination’s invocation rate below the endpoint’s limit.
    The bill is higher than expectedA producer publishes far more events than planned, a wildcard rule fires targets that bill by the call, or replays and Pipes enrichment add requestsLook at PutEvents volume by bus, tighten the patterns, and sample or batch chatty events at the source.

    Use cases: when and where to use it

    Good fit

    • Applications split into services that should not call each other directly
    • Reacting to AWS events, such as a stopped instance or a failed job, without polling
    • Teams that need to fan one event out to several consumers, each with its own filter
    • Connecting SaaS products and your own systems through partner event sources and API destinations
    • Large numbers of scheduled jobs, including one-off reminders
    • Systems that need to replay history after fixing a bug

    Consider something else

    • A queue that one consumer pulls from, with visibility timeouts → Amazon SQS
    • A simple fan-out of a message to many subscribers, including email and SMS → Amazon SNS
    • A multi-step workflow with state, waits and error branches → AWS Step Functions
    • High-volume ordered streams that consumers read at their own pace → Amazon Kinesis or Managed Streaming for Apache Kafka
    • The same job on other clouds → compare Azure Event Grid and Eventarc

    Pros: why consider it?

    Why teams choose it

    • Producers and consumers stay independent of each other
    • AWS service events reach the default bus at no charge
    • Content-based filtering in the service, not in every consumer
    • Retries, dead-letter queues, archive and replay are built in
    • Pipes and Scheduler remove a lot of glue code and cron servers
    • Pay per event, with nothing to run or patch

    Trade-offs to weigh

    • At-least-once delivery without ordering, so consumers must cope with duplicates
    • Debugging follows an event through several places, and the tooling is limited
    • Event size and rate quotas need design, not luck
    • No built-in view of who consumes which event unless you keep one
    • Per-event pricing adds up for very chatty producers
    • Regional: cross-Region flows need extra rules or global endpoints

    Common threats, vulnerabilities & risks

    RiskSeverityWhy it mattersMitigation
    Targets without a dead-letter queueHighWhen a target keeps failing, the event is dropped after the retries and nobody knows.Set a dead-letter queue and alarm on InvocationsFailedToBeSentToDlq and on the queue depth.
    A bus that anyone can write toHighA broad resource policy lets another account inject events that trigger real actions.Allow named accounts or an organisation only, and check policies with a regular audit.
    Sensitive data in event detailsHighEvents are copied to archives, queues, logs and partner endpoints, each with its own access rules.Keep personal data and secrets out of the detail. Send an ID and let the consumer fetch the record.
    Consumers that aren’t idempotentMediumRetries and replays deliver the same event again, and an order is charged twice.Store handled event IDs or use business keys with conditional writes.
    Replay without a planMediumA replay re-runs every rule, including the ones that send mail or move money.Replay into a test bus first, filter rules, and watch for the replay-name field.
    Event contracts that change silentlyMediumA producer renames a field and three consumers break, days later.Version the detail type, publish schemas, and add contract tests in the producer’s pipeline.
    Over-wide patternsMediumA rule that matches a whole source on the default bus triggers far more targets than you expect, and every target bills for its own work.Match on detail type and key fields, and review rules that have no filter on detail.
    Cron rules for time-sensitive workLow–MedRules run in UTC and have no flexible window, so a shifted clock or a burst of rules at midnight causes surprises.Use Scheduler for jobs with a time zone, and spread the start times.
    No owner for each ruleLow–MedOld rules keep firing for systems that were switched off years ago.Tag rules with an owner and a ticket, and review unused ones every quarter.

    Performance optimisation

    • Use PutEvents in batches of up to ten entries, and check every result in the response.
    • Keep events small. Put a large payload in S3 and send the key in the detail, so every hop stays quick.
    • Put a queue between the bus and a slow consumer, so bursts don’t turn into throttling or failures.
    • Filter in the pattern, not in the consumer, so unwanted events are never delivered.
    • Use Pipes to read from queues and streams instead of a polling function that only forwards messages.
    • Choose targets in the same Region as the bus where you can, since cross-Region hops add latency and cost.
    • Set retry settings per target to match how long the consumer can really wait.
    • Treat delivery as at least once and design for duplicates, because that is what keeps the system quick and simple.

    Reduce monthly cost

    FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for Amazon EventBridge.

    • Remember that AWS service events are free, and custom and partner events are billed per million.
    • Tighten patterns so fewer events match, and so fewer targets are invoked and billed downstream.
    • Batch and sample chatty producers: a progress event every second per user is rarely needed.
    • Archive only what you will replay, using a pattern on the archive, and set a retention period.
    • Keep replays short and targeted, since they are billed like events.
    • Count Pipes by requests after filtering: filter first, and enrich only what is left.
    • Move cron-style rules to Scheduler, where the first 14 million invocations a month are free.
    • Don’t send events through several buses when one rule can reach the target directly.
    • Use schema discovery on a test bus, not on every production bus all the time.
    • Tag buses and rules with the owning team, and put a budget alert on EventBridge spend.

    Figures here come from AWS's pricing page and other published guides, read in October 2026. Regions differ, sources disagree on some rates and prices move, so confirm on the live page (see Pricing).

    Security optimisation

    • Give each producer and consumer a role with only the actions it needs, such as events:PutEvents on one bus.
    • Write resource policies on buses that name accounts or an organisation, and avoid * principals.
    • Use customer managed KMS keys for buses and archives when a rule demands it, and keep the key policy in step.
    • Keep secrets out of events. Store API destination credentials in the connection, which keeps them in Secrets Manager for you.
    • Restrict who can change rules and targets, since a new target can send your events somewhere else.
    • Limit events:PutPermission so a bus can’t be opened to another account by accident.
    • Send events to CloudWatch Logs with a rule for the buses where you need an audit of what flowed.
    • Record API calls with CloudTrail, and alert on PutPermission, DeleteRule and RemoveTargets.
    • Use VPC endpoints where private workloads publish events, so traffic stays off the internet.
    • Validate the sender inside the event for sensitive flows, and don’t trust the source field alone on a shared bus.

    Governance & compliance

    Guardrails

    • A shared Terraform module for a bus, rule and target that always sets a retry policy, a dead-letter queue and tags
    • A permissions boundary or service control policy that limits who may call events:PutPermission and who may delete rules
    • A naming rule for source and detail-type, with the schema kept in the registry or in the producer’s repository
    • An owner tag on every rule, checked at creation, and a quarterly review of rules without traffic

    Continuous checks (AWS Config, Security Hub and your own scripts)

    • A scheduled script or custom rule that lists targets without a dead-letter queue (the C# tab does this)
    • Security Hub controls for EventBridge, where your standard includes them
    • Alarms on FailedInvocations, ThrottledRules and InvocationsFailedToBeSentToDlq
    • A CloudTrail alert for PutPermission, DeleteRule, DisableRule and RemoveTargets
    • A report of rules with no matched events in 90 days

    AWS CloudTrail records who changed buses, rules and targets, AWS Config can record the configuration over time, Security Hub reports on settings, and AWS Artifact holds compliance reports. AWS runs the service and keeps the events safe in transit and at rest. The event design, who may publish and consume, how long you archive, and what a failed delivery triggers are yours.

    Reduce carbon footprint

    • Send fewer, smaller events, and sample chatty producers, so less data is routed and stored.
    • Filter in the pattern so consumers aren’t woken for events they discard.
    • Archive only what you would replay, and set a retention period.
    • Retire rules and schedules that no longer have a consumer.
    • Where data rules and latency allow, run the bus in a Region on a cleaner grid.
    • The AWS carbon tool reports per account and does not list EventBridge on its own, so quote no EventBridge figure.

    Pricing

    Purchase options

    Custom events About $1.00 per million events

    Events you or a SaaS partner publish. Events from AWS services on the default bus are free. Sizes are counted in chunks, so large events cost more than one unit.

    Pipes About $0.40 per million requests

    Billed on requests after filtering, so a tight filter saves money. Enrichment calls are billed by the service you call.

    Archive and replay Per GB processed and stored

    Sources list about $0.10 per GB processed and $0.023 per GB-month stored. A replay is billed like custom events.

    Scheduler and extras Free up to 14 million a month

    Scheduler invocations beyond the free allowance, API destination calls and schema discovery above its free allowance are charged separately.

    What you actually pay for

    • Custom and partner events published to a bus
    • Pipes requests after filtering
    • Archive processing and storage, and replayed events
    • Scheduler invocations above the free monthly allowance
    • API destination invocations, cross-Region and cross-account hops, and schema discovery

    AWS lists free allowances for some features, and rates differ by Region. See the official Amazon EventBridge pricing page and the AWS Pricing Calculator.

    Important code references

    An orders domain: a custom bus, a rule for orders of 1000 or more that sends to a queue with retries and a dead-letter queue, a 30-day archive, a nightly schedule in India time and a look at the rule’s failure metric. The CLI tab builds it and sends a test event; Terraform describes the same resources. The Python tab publishes in batches and reads every result, tests a pattern and starts a replay, and the C# tab audits buses for disabled rules, empty rules and targets without a dead-letter queue. Replace the Region, account and names with your own.

    # Placeholders: replace the Region and account with your own.
    REGION=ap-south-1
    ACCOUNT=111122223333
    BUS=orders
    
    # 1. A custom bus for the orders domain. Events from your own code go here, not to the default bus.
    aws events create-event-bus --region $REGION --name $BUS
    
    # 2. A queue for large orders and a second queue that keeps whatever could not be delivered.
    DLQ_URL=$(aws sqs create-queue --region $REGION --queue-name $BUS-large-dlq --query QueueUrl --output text)
    DLQ_ARN=$(aws sqs get-queue-attributes --region $REGION --queue-url "$DLQ_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)
    Q_URL=$(aws sqs create-queue --region $REGION --queue-name $BUS-large --query QueueUrl --output text)
    Q_ARN=$(aws sqs get-queue-attributes --region $REGION --queue-url "$Q_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)
    
    # 3. A rule that matches orders of 1000 or more. Test the pattern against a sample event before you rely on it.
    cat > pattern.json <<JSON
    {"source": ["com.example.orders"], "detail-type": ["OrderPlaced"], "detail": {"total": [{"numeric": [">=", 1000]}]}}
    JSON
    cat > sample-event.json <<JSON
    {"id": "1", "account": "$ACCOUNT", "time": "2026-11-01T10:00:00Z", "region": "$REGION", "resources": [],
     "source": "com.example.orders", "detail-type": "OrderPlaced", "detail": {"orderId": "A-1001", "total": 2500}}
    JSON
    aws events test-event-pattern --region $REGION --event-pattern file://pattern.json --event file://sample-event.json
    aws events put-rule --region $REGION --event-bus-name $BUS --name large-orders --event-pattern file://pattern.json
    RULE_ARN=$(aws events describe-rule --region $REGION --event-bus-name $BUS --name large-orders --query Arn --output text)
    
    # 4. Let that one rule send to both queues. Without this policy the rule matches but nothing arrives.
    for ARN in "$Q_ARN" "$DLQ_ARN"; do
      URL=$([ "$ARN" = "$Q_ARN" ] && echo "$Q_URL" || echo "$DLQ_URL")
      cat > policy.json <<JSON
    {"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"Service": "events.amazonaws.com"},
      "Action": "sqs:SendMessage", "Resource": "$ARN", "Condition": {"ArnEquals": {"aws:SourceArn": "$RULE_ARN"}}}]}
    JSON
      python3 -c "import json;print(json.dumps({'Policy': open('policy.json').read()}))" > attrs.json
      aws sqs set-queue-attributes --region $REGION --queue-url "$URL" --attributes file://attrs.json
    done
    
    # 5. The target: retry for up to an hour, then park the event in the dead-letter queue.
    aws events put-targets --region $REGION --event-bus-name $BUS --rule large-orders \
      --targets "Id=large-queue,Arn=$Q_ARN,RetryPolicy={MaximumRetryAttempts=10,MaximumEventAgeInSeconds=3600},DeadLetterConfig={Arn=$DLQ_ARN}"
    
    # 6. Keep 30 days of events on this bus, so a bug in a consumer can be fixed and the events replayed.
    aws events create-archive --region $REGION --archive-name $BUS-30d --retention-days 30 \
      --event-source-arn arn:aws:events:$REGION:$ACCOUNT:event-bus/$BUS
    
    # 7. Send one event, and look at FailedEntryCount: PutEvents can succeed as a call and still reject an entry.
    aws events put-events --region $REGION --entries '[{"EventBusName": "orders", "Source": "com.example.orders",
      "DetailType": "OrderPlaced", "Detail": "{\"orderId\": \"A-1001\", \"total\": 2500}"}]'
    aws sqs receive-message --region $REGION --queue-url "$Q_URL" --wait-time-seconds 5
    
    # 8. A nightly job at 02:30 India time with a 15-minute window, from EventBridge Scheduler instead of a cron rule.
    cat > target.json <<JSON
    {"Arn": "$Q_ARN", "RoleArn": "arn:aws:iam::$ACCOUNT:role/scheduler-to-sqs", "Input": "{\\"job\\": \\"orders-report\\"}"}
    JSON
    aws scheduler create-schedule --region $REGION --name nightly-orders-report --schedule-expression "cron(30 2 * * ? *)" \
      --schedule-expression-timezone Asia/Kolkata --flexible-time-window Mode=FLEXIBLE,MaximumWindowInMinutes=15 --target file://target.json
    
    # 9. Is anything failing to reach a target? Look at the rule's metrics for the last hour.
    aws cloudwatch get-metric-statistics --region $REGION --namespace AWS/Events --metric-name FailedInvocations \
      --dimensions Name=RuleName,Value=large-orders --statistics Sum --period 300 \
      --start-time $(date -u -d '-1 hour' +%FT%TZ) --end-time $(date -u +%FT%TZ)
    # Placeholders: pass in your own names. The role and account values below are examples.
    variable "region" {
      type    = string
      default = "ap-south-1"
    }
    
    variable "bus_name" {
      type    = string
      default = "orders"
    }
    
    provider "aws" {
      region = var.region
    }
    
    data "aws_caller_identity" "me" {}
    
    resource "aws_cloudwatch_event_bus" "orders" {
      name = var.bus_name
    }
    
    resource "aws_cloudwatch_event_archive" "orders" {
      name             = "${var.bus_name}-30d"
      event_source_arn = aws_cloudwatch_event_bus.orders.arn
      retention_days   = 30
    }
    
    resource "aws_sqs_queue" "large_dlq" {
      name = "${var.bus_name}-large-dlq"
    }
    
    resource "aws_sqs_queue" "large" {
      name = "${var.bus_name}-large"
    }
    
    resource "aws_cloudwatch_event_rule" "large_orders" {
      name           = "large-orders"
      event_bus_name = aws_cloudwatch_event_bus.orders.name
      event_pattern = jsonencode({
        source        = ["com.example.orders"]
        "detail-type" = ["OrderPlaced"]
        detail        = { total = [{ numeric = [">=", 1000] }] }
      })
    }
    
    # Both queues must allow this one rule to send. Without it the rule matches and nothing arrives.
    data "aws_iam_policy_document" "from_rule" {
      for_each = {
        large     = aws_sqs_queue.large.arn
        large_dlq = aws_sqs_queue.large_dlq.arn
      }
    
      statement {
        actions   = ["sqs:SendMessage"]
        resources = [each.value]
    
        principals {
          type        = "Service"
          identifiers = ["events.amazonaws.com"]
        }
    
        condition {
          test     = "ArnEquals"
          variable = "aws:SourceArn"
          values   = [aws_cloudwatch_event_rule.large_orders.arn]
        }
      }
    }
    
    resource "aws_sqs_queue_policy" "large" {
      queue_url = aws_sqs_queue.large.id
      policy    = data.aws_iam_policy_document.from_rule["large"].json
    }
    
    resource "aws_sqs_queue_policy" "large_dlq" {
      queue_url = aws_sqs_queue.large_dlq.id
      policy    = data.aws_iam_policy_document.from_rule["large_dlq"].json
    }
    
    resource "aws_cloudwatch_event_target" "large_queue" {
      rule           = aws_cloudwatch_event_rule.large_orders.name
      event_bus_name = aws_cloudwatch_event_bus.orders.name
      target_id      = "large-queue"
      arn            = aws_sqs_queue.large.arn
    
      retry_policy {
        maximum_retry_attempts       = 10
        maximum_event_age_in_seconds = 3600
      }
    
      dead_letter_config {
        arn = aws_sqs_queue.large_dlq.arn
      }
    }
    
    resource "aws_iam_role" "scheduler" {
      name = "scheduler-to-sqs"
      assume_role_policy = jsonencode({
        Version = "2012-10-17"
        Statement = [{
          Effect    = "Allow"
          Principal = { Service = "scheduler.amazonaws.com" }
          Action    = "sts:AssumeRole"
          Condition = { StringEquals = { "aws:SourceAccount" = data.aws_caller_identity.me.account_id } }
        }]
      })
    }
    
    resource "aws_iam_role_policy" "scheduler_send" {
      role = aws_iam_role.scheduler.id
      policy = jsonencode({
        Version   = "2012-10-17"
        Statement = [{ Effect = "Allow", Action = "sqs:SendMessage", Resource = aws_sqs_queue.large.arn }]
      })
    }
    
    resource "aws_scheduler_schedule" "nightly_report" {
      name                         = "nightly-orders-report"
      schedule_expression          = "cron(30 2 * * ? *)"
      schedule_expression_timezone = "Asia/Kolkata"
    
      flexible_time_window {
        mode                      = "FLEXIBLE"
        maximum_window_in_minutes = 15
      }
    
      target {
        arn      = aws_sqs_queue.large.arn
        role_arn = aws_iam_role.scheduler.arn
        input    = jsonencode({ job = "orders-report" })
      }
    }
    
    output "bus_arn" {
      value = aws_cloudwatch_event_bus.orders.arn
    }
    # pip install boto3
    # Sends orders to a bus in batches of ten (the PutEvents limit per call), checks the answer entry by entry,
    # tests an event pattern without deploying it, and replays a time window from the archive.
    import datetime as dt
    import json
    
    import boto3
    
    events = boto3.client("events", region_name="ap-south-1")
    BUS = "orders"
    
    
    def publish(orders):
        """Returns the orders EventBridge refused. A call can succeed while single entries fail, so read every result."""
        refused = []
        for start in range(0, len(orders), 10):
            batch = orders[start:start + 10]
            entries = [{"EventBusName": BUS, "Source": "com.example.orders", "DetailType": "OrderPlaced",
                        "Detail": json.dumps(order)} for order in batch]
            reply = events.put_events(Entries=entries)
            if reply["FailedEntryCount"]:
                for order, result in zip(batch, reply["Entries"]):
                    if "ErrorCode" in result:
                        refused.append((order, result["ErrorCode"], result.get("ErrorMessage", "")))
        return refused
    
    
    def matches(pattern, event):
        """True when the pattern would select the event. Handy in unit tests for your rules."""
        return events.test_event_pattern(EventPattern=json.dumps(pattern), Event=json.dumps(event))["Result"]
    
    
    def replay(archive_arn, bus_arn, hours=2):
        """Sends the events of the last few hours from the archive back to the bus they came from."""
        end = dt.datetime.now(dt.timezone.utc)
        name = "fix-" + end.strftime("%Y%m%d-%H%M%S")
        events.start_replay(ReplayName=name, EventSourceArn=archive_arn, Destination={"Arn": bus_arn},
                            EventStartTime=end - dt.timedelta(hours=hours), EventEndTime=end)
        return name
    
    
    if __name__ == "__main__":
        pattern = {"source": ["com.example.orders"], "detail-type": ["OrderPlaced"], "detail": {"total": [{"numeric": [">=", 1000]}]}}
        sample = {"id": "1", "account": "111122223333", "time": "2026-11-01T10:00:00Z", "region": "ap-south-1", "resources": [],
                  "source": "com.example.orders", "detail-type": "OrderPlaced", "detail": {"orderId": "A-1001", "total": 2500}}
        print("pattern matches the sample:", matches(pattern, sample))
        problems = publish([{"orderId": "A-%d" % n, "total": 400 + n * 300} for n in range(1, 26)])
        print("refused:", problems or "none")
    // dotnet add package AWSSDK.EventBridge
    // Audits every event bus in the Region: disabled rules, rules without targets, and targets that have no dead-letter queue.
    using Amazon.EventBridge;
    using Amazon.EventBridge.Model;
    
    using var events = new AmazonEventBridgeClient();
    int problems = 0;
    
    var buses = await events.ListEventBusesAsync(new ListEventBusesRequest());
    foreach (EventBus bus in buses.EventBuses)
    {
        string? token = null;
        do
        {
            var page = await events.ListRulesAsync(new ListRulesRequest { EventBusName = bus.Name, NextToken = token });
            foreach (Rule rule in page.Rules)
            {
                // rules an AWS service created for you carry a ManagedBy value, and they are not yours to fix
                if (!string.IsNullOrEmpty(rule.ManagedBy)) continue;
    
                if (rule.State == RuleState.DISABLED)
                {
                    Console.WriteLine($"{bus.Name}/{rule.Name}: rule is disabled");
                    problems++;
                }
    
                var targets = await events.ListTargetsByRuleAsync(new ListTargetsByRuleRequest { EventBusName = bus.Name, Rule = rule.Name });
                if (targets.Targets.Count == 0)
                {
                    Console.WriteLine($"{bus.Name}/{rule.Name}: rule has no target");
                    problems++;
                }
                foreach (Target target in targets.Targets.Where(t => t.DeadLetterConfig?.Arn is null))
                {
                    Console.WriteLine($"{bus.Name}/{rule.Name}: target {target.Id} has no dead-letter queue");
                    problems++;
                }
            }
            token = page.NextToken;
        } while (token != null);
    }
    
    Console.WriteLine(problems == 0 ? "No problems found." : $"{problems} problem(s) found.");
    return problems == 0 ? 0 : 1;

    Best videos to explore

    Videos picked for this service. Each one is labelled with its source, opens on YouTube if you prefer, and loads only when you press play.

    Deep Dive on Amazon EventBridge - AWS Online Tech TalksOfficial · AWS · Intermediate · Watch on YouTube
    AWS re:Invent 2023 - Advanced event-driven patterns with Amazon EventBridge (COM301-R)Official · AWS · Advanced · Watch on YouTube
    Intro to Amazon EventBridgeCommunity video · Beginner · Watch on YouTube
    EventBridge Pipe Crash CourseCommunity video · Intermediate · Watch on YouTube

    Interview questions

    BasicWhat is Amazon EventBridge?

    It’s the AWS service that routes events. Producers send events to an event bus, and rules match them and deliver them to targets such as Lambda functions, queues, topics, state machines or web endpoints. AWS services publish to it too, so you can react to things like an instance stopping without polling.

    BasicHow does EventBridge differ from SNS and SQS?

    SQS is a queue that one consumer group pulls from. SNS pushes one message to many subscribers by topic. EventBridge routes by the content of the event, with rules you can change without touching the producer, and it receives events from AWS services and SaaS partners. They combine well: a rule often sends matching events to an SQS queue so a consumer can work at its own pace.

    BasicWhat happened to CloudWatch Events?

    EventBridge grew out of it. The service launched in 2019 as the successor, and the default bus and the rules you created in CloudWatch Events appear in EventBridge. New features, such as custom buses, archives, Pipes and the schema registry, are only in EventBridge.

    IntermediateHow does an event pattern work?

    It’s a JSON document shaped like the events you want. Every field you list has to match, and an array of values means any one of them. You can match on prefixes, numeric ranges, whether a field exists, values that are not in a list, and wildcards. Test a pattern with test-event-pattern before you deploy a rule.

    IntermediateWhat happens when a target fails?

    EventBridge retries delivery with exponential backoff and jitter. For rule targets the default is up to 24 hours and 185 attempts, and you can shorten both. When the retries run out, the event goes to the dead-letter queue if you set one, and is dropped if not. Errors that cannot succeed, such as most 4xx answers, are not retried.

    IntermediateWhen would you pick Pipes, a bus rule or Scheduler?

    Use a bus and rules when many consumers care about an event and the producer shouldn’t know them. Use a pipe for a point-to-point link from one queue or stream to one target, where you want filtering and enrichment without a function in the middle. Use Scheduler for time-based work, especially one-off schedules, time zones and large numbers of schedules.

    AdvancedHow would you design events and contracts for a domain with many teams?

    Treat events as public contracts. Agree names for source and detail-type, include a version, keep the detail small and free of personal data, and send an ID when a consumer needs more. Publish schemas in the registry or the producer’s repository, and add contract tests so a change that breaks a consumer fails the producer’s pipeline.

    AdvancedHow do you make consumers safe with at-least-once delivery and no ordering?

    Make every handler idempotent: store the event ID or a business key and skip what you have seen. Put a version or sequence number in the detail so a late older event cannot overwrite newer data. When order matters strictly, read from a source that preserves it, such as a stream or a FIFO queue through a pipe, and don’t depend on the bus for it.

    AdvancedHow would you share events across accounts and Regions, and plan for a Regional failure?

    Give the receiving bus a resource policy that names the sending accounts or the organisation, and forward with a rule whose target is the other bus. For Regional failover, use global endpoints for custom buses with health-check based failover, or forward to a bus in a second Region. Archives and replays stay on the Region and bus where they were created, so plan how you would rebuild state.

    AdvancedA consumer bug was fixed and you must reprocess three hours of events. What is your plan?

    Check that the archive covers the window and that the consumer is idempotent. Replay into a test bus first if the rules have side effects, or pause or filter those rules for the replay. Start a replay for the exact window, watch FailedInvocations and the dead-letter queue, and look for the replay-name field to tell replayed events from live ones.

    Similar or alternative services on other clouds

    CapabilityAWSAzureGoogle Cloud
    ServiceAmazon EventBridgeAzure Event GridEventarc with Pub/Sub
    Events from the platformDefault bus, AWS service events freeSystem topics for Azure servicesEventarc Standard triggers for Google Cloud sources and audit logs
    Your own eventsCustom buses with PutEventsCustom topics, and namespace topics with CloudEventsEventarc Advanced message bus, or Pub/Sub
    FilteringEvent patterns on any fieldEvent type, subject and advanced filtersTrigger filters, and CEL conditions in Advanced
    DeliveryPush to targets, five per rulePush to handlers; pull delivery in namespacesPush over HTTP, with Pub/Sub as the transport
    Retry and dead letterRetry policy and an SQS dead-letter queueRetry policy and a Blob Storage dead-letter locationPub/Sub subscription retry and a dead-letter topic
    Point-to-point linksPipes with filter and enrichmentEvent Grid with Functions or Logic AppsEventarc Advanced pipelines
    SchedulesEventBridge SchedulerTimer triggers and Logic AppsCloud Scheduler
    How you are billedPer custom event, Pipes request, archive GBPer operation; throughput units in namespacesPer event or message, plus Pub/Sub transport

    Typical targets and sources include AWS Lambda, Amazon API Gateway and Amazon S3 notifications. Metrics and alarms for rules live in Amazon CloudWatch, and customer managed keys come from AWS KMS.

    Did you find this article helpful?

    Your answer helps us improve this page for the next reader.

    Sources and further reading

    CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.