How to Configure a Terraform Lambda Trigger for Scheduled Events
You can configure a terraform lambda trigger for scheduled events by creating an aws_cloudwatch_event_rule with a schedule expression, an aws_cloudwatch_event_target to link the rule to your Lambda, and an aws_lambda_permission to authorize CloudWatch Events to invoke the function.
This guide demonstrates how to implement a terraform lambda trigger for AWS Lambda functions using scheduled event sources. Based on the architecture of the hashicorp/terraform repository, we'll explore how Terraform's core graph engine resolves dependencies between CloudWatch Events and Lambda resources to create reliable, time-based automation.
Understanding the Terraform Lambda Trigger Architecture
A terraform lambda trigger for scheduled events requires wiring together four distinct AWS resources. When Terraform applies your configuration, it executes a dependency graph built by the core engine (see internal/terraform/transform_resource_count.go for the graph resolution logic) to ensure resources create in the correct order.
The four resources you need are:
aws_lambda_function– The compute resource that executes your code.aws_cloudwatch_event_rule– Defines the schedule using either arate()expression or acron()expression.aws_lambda_permission– Grants CloudWatch Events service principal permission to invoke your specific Lambda function.aws_cloudwatch_event_target– Connects the rule to the Lambda by specifying the function ARN as the target.
Complete Terraform Lambda Trigger Example
Below is a production-ready configuration that creates a Lambda function triggered every five minutes. This example demonstrates the complete resource chain required for a functional terraform lambda trigger.
# -------------------------------------------------
# 1. The Lambda function (source code zipped in S3)
# -------------------------------------------------
resource "aws_lambda_function" "my_lambda" {
function_name = "my-scheduled-function"
role = aws_iam_role.lambda_exec.arn
handler = "index.handler"
runtime = "nodejs20.x"
# The .zip file containing the Lambda code
s3_bucket = aws_s3_bucket.lambda_code.bucket
s3_key = aws_s3_bucket_object.lambda_zip.key
}
# -------------------------------------------------
# 2. IAM role for the Lambda (basic execution role)
# -------------------------------------------------
resource "aws_iam_role" "lambda_exec" {
name = "lambda-exec-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = { Service = "lambda.amazonaws.com" }
}]
})
}
resource "aws_iam_role_policy_attachment" "lambda_basic" {
role = aws_iam_role.lambda_exec.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
# -------------------------------------------------
# 3. CloudWatch Event rule (schedule)
# -------------------------------------------------
resource "aws_cloudwatch_event_rule" "every_five_minutes" {
name = "every-five-minutes"
schedule_expression = "rate(5 minutes)" # or use cron: "cron(0/5 * * * ? *)"
}
# -------------------------------------------------
# 4. Permission so CloudWatch can invoke the Lambda
# -------------------------------------------------
resource "aws_lambda_permission" "allow_cloudwatch" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.my_lambda.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.every_five_minutes.arn
}
# -------------------------------------------------
# 5. Attach the rule to the Lambda
# -------------------------------------------------
resource "aws_cloudwatch_event_target" "lambda_target" {
rule = aws_cloudwatch_event_rule.every_five_minutes.name
target_id = "lambda"
arn = aws_lambda_function.my_lambda.arn
}
Breaking Down the Resource Dependencies
Terraform's core engine resolves the implicit dependencies between these resources using graph transformations defined in internal/terraform/transform_*.go files. Understanding these relationships helps troubleshoot deployment failures.
The Lambda Function Resource
The aws_lambda_function resource serves as the compute target. According to the provider loading mechanism in internal/getproviders/reattach/reattach.go, Terraform loads the AWS provider plugin which supplies this resource schema. The function must exist before you can attach triggers to it.
The CloudWatch Event Rule
The aws_cloudwatch_event_rule defines the schedule expression. You can use either rate() for simple intervals or cron() for complex schedules. This resource creates the event bus rule but does not yet specify what runs when the rule fires.
The Lambda Permission Resource
The aws_lambda_permission is critical for security. Without this resource, CloudWatch Events lacks the IAM authorization to invoke your function. The source_arn parameter ensures that only the specific CloudWatch rule can trigger the Lambda, following the principle of least privilege.
The Event Target Resource
The aws_cloudwatch_event_target completes the circuit by declaring that the Lambda function (specified by arn) is the destination for the CloudWatch rule. Terraform's graph builder ensures this resource creates after both the Lambda and the rule exist, as documented in internal/terraform/transform_resource_count.go.
Key Files in the Terraform Core Repository
Understanding how Terraform processes your lambda trigger configuration requires familiarity with these core components:
| File | Role in Lambda Trigger Deployment |
|---|---|
main.go |
Entry point that bootstraps the CLI, loads providers, and executes the plan/apply lifecycle for your terraform lambda trigger resources. |
internal/command/* |
Handles sub-commands such as apply, plan, and destroy that process your AWS resource definitions. |
internal/terraform/transform_*.go |
Implements the graph building logic that resolves inter-resource dependencies, ensuring the aws_lambda_permission creates after the Lambda function exists. |
internal/getproviders/reattach/reattach.go |
Loads the AWS provider plugin that supplies the aws_lambda_function and aws_cloudwatch_event_rule resource schemas. |
internal/terraform/upgrade_resource_state.go |
Manages state upgrades when provider versions change, ensuring your terraform lambda trigger configuration remains compatible across Terraform updates. |
Summary
Configuring a terraform lambda trigger for scheduled events requires orchestrating four AWS resources through explicit and implicit dependencies:
- Create the
aws_lambda_functionas your compute target. - Define the schedule using
aws_cloudwatch_event_rulewithrate()orcron()expressions. - Grant invocation rights via
aws_lambda_permissionto secure the trigger. - Link the rule to the function using
aws_cloudwatch_event_target.
Terraform's core graph engine, implemented in internal/terraform/transform_*.go, automatically resolves the creation order of these resources, ensuring your scheduled trigger deploys reliably.
Frequently Asked Questions
What is the difference between rate and cron expressions in a terraform lambda trigger?
Rate expressions use the format rate(value unit) (e.g., rate(5 minutes)) to trigger at regular intervals, while cron expressions use the format cron(fields) (e.g., cron(0 12 * * ? *)) for complex schedules that run at specific times. Rate expressions are simpler but less flexible than cron for calendar-based scheduling.
Do I need aws_lambda_permission for every terraform lambda trigger?
Yes, you must create an aws_lambda_permission resource for each service that invokes your Lambda. Without this permission, CloudWatch Events (or EventBridge) cannot invoke the function due to AWS's resource-based policies. The principal must be events.amazonaws.com and the source_arn should reference your specific CloudWatch rule ARN to follow least-privilege security practices.
How do I troubleshoot a terraform lambda trigger that isn't firing?
First, verify the CloudWatch Events rule is enabled and the cron/rate expression is valid in the AWS Console. Check CloudWatch Logs for the Lambda function to ensure it isn't erroring on invocation. Confirm the aws_lambda_permission resource exists with the correct source_arn matching the rule, as missing or incorrect permissions are the most common cause of silent trigger failures.
Can I use terraform lambda triggers with Amazon EventBridge instead of CloudWatch Events?
Yes, EventBridge uses the same underlying API as CloudWatch Events, so the aws_cloudwatch_event_rule and aws_cloudwatch_event_target resources work for both. For EventBridge-specific features like event buses, use the aws_cloudwatch_event_bus resource and reference it in your rule's event_bus_name parameter. The permission structure remains identical, using events.amazonaws.com as the principal.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →