Terraform EventBridge Rule Management for Serverless Event Routing

AWS EventBridge formerly CloudWatch Events is a serverless event bus service. Setting up AWS EventBridge Rules with Terraform is how you create and manage AWS EventBridge rules using Terraform, including event patterns, schedules, and targets. This guide demonstrates how to set up and manage EventBridge rules using Terraform.

EventBridge has three main concepts: Event Bus - Where events arrive. The default bus receives events from AWS services in your account; some services, such as S3 object events, require event delivery to EventBridge to be enabled first. Amazon EventBridge is the event bus that ties AWS services together. When an EC2 instance changes state, when a CodePipeline deployment fails, when an S3 object is created - EventBridge can catch those events and route them to targets like Lambda functions, SQS queues, or Step Functions. EventBridge scheduled rules can also run cron-style scheduled tasks in AWS, although EventBridge Scheduler is the recommended service for new standalone schedules.

Prerequisites and Project Structure

Prerequisites
- AWS CLI configured with appropriate permissions
- Terraform installed (version 1.0.0 or later)
- Basic understanding of event-driven architectures
- Familiarity with JSON/YAML

A typical project structure for Terraform EventBridge work is organized to separate configuration, modules, and patterns.

terraform-eventbridge/ ├── main.tf ├── variables.tf ├── outputs.tf ├── modules/ │ └── eventbridge/ │ ├── main.tf │ ├── variables.tf │ └── outputs.tf └── patterns/ └── events.json

This layout isolates the Event Bus, rules, and targets in a reusable module while keeping event patterns in a dedicated patterns directory for version control.

Core EventBridge Resources in Terraform

EventBridge Configuration can be built with several Terraform resources that map directly to AWS concepts.

Event Bus Creation

You can configure a new event bus with:

hcl resource "aws_cloudwatch_event_bus" "test_bus" { name = "test_bus" }

The default event bus is used throughout data blocks in many simple examples. We’ll keep this article simple and use the default event bus throughout the data block.

A more complete module definition for an event bus with tags is:

hcl resource "aws_cloudwatch_event_bus" "main" { name = "${var.project_name}-bus" tags = merge( var.tags, { Name = "${var.project_name}-bus" } ) }

You can contact AWS support to increase this quota if you need additional event buses beyond the default limit.

Event Bus Policy

An Event Bus Policy controls which accounts can put events into the bus.

hcl resource "aws_cloudwatch_event_bus_policy" "main" { event_bus_name = aws_cloudwatch_event_bus.main.name policy = jsonencode({ Version = "2012-10-17" Statement = [ { Sid = "AllowOtherAccountsPutEvents" Effect = "Allow" Principal = { AWS = var.allowed_account_ids } Action = "events:PutEvents" Resource = aws_cloudwatch_event_bus.main.arn } ] }) }

Rule Creation

To create a new rule with Terraform, you can use the resource aws_cloudwatch_event_rule.

Note: Older examples often use is_enabled = true/false to toggle a rule on or off. That argument is now deprecated — use state = "ENABLED" or state = "DISABLED" instead.

EventBridge rules are how EventBridge matches events sent to it and directs them to the target. It can match events through:

  • Event patterns – This is how you set EventBridge to match data with event properties, like detail, bucket, and name, for an S3:PutObject event.
  • Scheduler – You can define scheduled events sent to EventBridge at a specific time or regularly.

One limitation of rules is that a rule can only send an event to up to five targets. So, if you want to send an event to more than five targets, you’ll need to create multiple rules with the same pattern/scheduler. You can also always target an SNS topic and fan out your event to various subscribers.

Terraform comes with a considerable advantage: You can easily leverage Terraform variables and locals to pass the same event pattern to multiple rules.

Schedule Rule Example

hcl resource "aws_cloudwatch_event_rule" "schedule" { name = "${var.project_name}-schedule" description = "Schedule-based rule" event_bus_name = aws_cloudwatch_event_bus.main.name schedule_expression = "rate(5 minutes)" tags = merge( var.tags, { Name = "${var.project_name}-schedule" } ) }

Event Patterns and Scheduled Rules

Pattern-based Rule

hcl resource "aws_cloudwatch_event_rule" "pattern" { name = "${var.project_name}-pattern" description = "Pattern-based rule" event_bus_name = aws_cloudwatch_event_bus.main.name event_pattern = file("${path.module}/../patterns/events.json") }

Event patterns allow matching on source, detail-type, detail fields, and other event properties.

Scheduler Rules with Terraform

A big feature of EventBridge is the ability to create task scheduler rules. These rules trigger custom events to EventBridge at a specific time or periodically.

Let’s say you need to back up your data storage every week. To do that, you can set up a scheduler rule with a cron expression to be triggered every week. This event will be sent to a target responsible for backing up your data storage weekly at the designated time.

EventBridge Scheduler is now available in all AWS Regions, so the examples here work consistently across your environments, including GovCloud and most new regions.

We can use the same aws_cloudwatch_event_rule resource to define a scheduled rule, but we’ll use the property schedule_expression instead of the event_pattern.

Here, we pass a string with a cron expression, an expression in a pattern to define the minute, hour, day of the month, month, day of the week, and year of execution.

For example, the expression 0 12 * * ? * will run every day at 12:00 PM UTC.

The schedule_expression accepts both rate and cron formats. Rate examples include rate(5 minutes). Cron examples include daily, weekly, monthly schedules.

Targets, Limits, and Error Handling

A single EventBridge rule can route the same event to up to five targets, which run in parallel.

If more than five targets are required, create multiple rules with the same pattern/scheduler or target an SNS topic for fan-out.

Common targets include SQS queues, Lambda functions, Step Functions, and CloudWatch Logs. Dead-letter queues can be configured on targets to handle errors.

We set up Terraform with Spacelift to trigger builds and deploy to AWS, managed event buses, rules, and targets, and handled errors with monitoring tools like dead-letter queues.

To test, you can add a new file to your S3 bucket and then go to the rule monitoring to see if an event was matched for that rule.

The metrics can take a few minutes to show on CloudWatch or the monitoring tab.

Terraform Module for EventBridge

Terraform module to create EventBridge resources.

The module creates AWS EventBridge Resources:
- bus, rules, targets, permissions, connections, destinations, pipes, schedules and schedule groups
- Attach resources to an existing EventBridge bus
- Support AWS EventBridge Archives and Replays
- Conditional creation for many types of resources
- Support IAM policy attachments and various ways to create and attach additional policies

Most common use-case which creates custom bus, logging, rules and targets.

Example usage:

hcl module "eventbridge" { source = "terraform-aws-modules/eventbridge/aws" bus_name = "my-bus" log_config = { include_detail = "FULL" level = "INFO" } log_delivery = { cloudwatch_logs = { destination_arn = "arn:aws:logs:us-east-1:123456789012:log-group:my-log-group" } s3 = { destination_arn = "arn:aws:s3:::my-log-bucket" } } rules = { orders = { description = "Capture all order data" event_pattern = jsonencode({ "source" : ["myapp.orders"] }) enabled = true } } targets = { orders = [ { name = "send-orders-to-sqs" arn = aws_sqs_queue.queue.arn dead_letter_arn = aws_sqs_queue.dlq.arn }, { name = "send-orders-to-kinesis" arn = aws_kinesis_stream.this.arn dead_letter_arn = aws_sqs_queue.dlq.arn input_transformer = local.kinesis_input_transformer }, { name = "log-orders-to-cloudwatch" arn = aws_cloudwatch_log_group.this.arn } ] } tags = { Name = "my-bus" } }

Minimal module usage:

hcl module "eventbridge" { source = "terraform-aws-modules/eventbridge/aws" bus_name = "my-bus" tags = { Name = "my-bus" } }

Resource Comparison

Resource Purpose Key Arguments
awscloudwatchevent_bus Create custom event bus name, tags
awscloudwatcheventbuspolicy Authorize cross-account PutEvents eventbusname, policy
awscloudwatchevent_rule Define pattern or schedule matching name, eventbusname, eventpattern, scheduleexpression, state
Module eventbridge/aws Full stack bus, rules, targets busname, rules, targets, logconfig

Rules vs Scheduler vs Pipes

Concept Description
Rules Route events from an event bus to targets based on event patterns or basic schedules
Scheduler Standalone serverless service for managing scheduled tasks at scale with time zones, one-time invocations, and flexible windows
Pipes Creates point-to-point integrations between a source like SQS or DynamoDB Streams and a target, with optional filtering and enrichment

What's the difference between EventBridge rules and EventBridge Scheduler?

EventBridge rules trigger targets either by matching event patterns on a bus or running on a basic cron or rate schedule. Scheduler is a dedicated service built specifically for time-based tasks, offering time zone support, one-time invocations, higher scalability, retries, and a broader set of target APIs.

What's the difference between EventBridge Rules, Scheduler, and Pipes?

Rules route events from an event bus to targets based on event patterns or basic schedules. Scheduler is a standalone serverless service for managing scheduled tasks at scale with time zones, one-time invocations, and flexible windows. Pipes creates point-to-point integrations between a source like SQS or DynamoDB Streams and a target, with optional filtering and enrichment.

Deployment Workflow

  • Define project structure with modules and patterns.
  • Create event bus and policy for cross-account access.
  • Define rules with aws_cloudwatch_event_rule using event_pattern or schedule_expression.
  • Attach targets with dead-letter queues for reliability.
  • Apply with Terraform and confirm plan.
  • Test by generating events, e.g., adding a file to S3 bucket, and verify rule matching in monitoring.

Turning it on will send all events to EventBridge.

You can now push the code to your repository and confirm the Terraform plan in Spacelift.

Orchestrate Terraform deployments with Spacelift. Orchestrate your Terraform workflows and build governed pipelines using policy as code, programmatic configuration, context sharing, drift detection, resource visualization, and many more.

Conclusion

Terraform provides a declarative way to define and manage AWS EventBridge rules, event buses, policies, schedules, and targets. Using aws_cloudwatch_event_rule with schedule_expression for rate or cron schedules and event_pattern for pattern matching enables both time-driven and event-driven architectures. The module terraform-aws-modules/eventbridge/aws streamlines creation of buses, logging, rules, and targets with conditional resources, archives, replays, and IAM policy attachments. Key operational constraints to remember are the five-target limit per rule, the deprecation of is_enabled in favor of state = "ENABLED" or state = "DISABLED", and the availability of EventBridge Scheduler for advanced scheduling needs. With proper project structure, variable-driven patterns, and dead-letter error handling, Terraform EventBridge configurations remain repeatable, auditable, and scalable across AWS environments.

Sources

  1. AWS EventBridge Terraform Blog
  2. Terraform EventBridge Spacelift Blog
  3. Terraform AWS Modules EventBridge
  4. Create EventBridge Rules Terraform

Related Posts