AWS EventBridge Rules and Targets with Terraform
Build event-driven architectures with AWS EventBridge managed by Terraform — custom buses, rules, and cross-account events.
Cloud Computing
Step-by-step guide to deploying serverless AWS Lambda functions using Terraform with IAM roles, API Gateway triggers, and CloudWatch logging.
AWS Lambda lets you run code without provisioning servers. Combined with Terraform, you can version-control your entire serverless infrastructure. This guide walks through creating a production-ready Lambda function with proper IAM permissions, API Gateway integration, and monitoring.
lambda-project/
├── main.tf
├── variables.tf
├── outputs.tf
├── lambda/
│ └── handler.py
└── terraform.tfvars# lambda/handler.py
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info(f"Received event: {json.dumps(event)}")
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({
'message': 'Hello from Terraform-managed Lambda!',
'input': event
})
}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" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
role = aws_iam_role.lambda_exec.name
}data "archive_file" "lambda_zip" {
type = "zip"
source_dir = "${path.module}/lambda"
output_path = "${path.module}/lambda.zip"
}
resource "aws_lambda_function" "api" {
filename = data.archive_file.lambda_zip.output_path
function_name = var.function_name
role = aws_iam_role.lambda_exec.arn
handler = "handler.lambda_handler"
runtime = "python3.12"
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
timeout = 30
memory_size = 256
environment {
variables = {
ENVIRONMENT = var.environment
LOG_LEVEL = "INFO"
}
}
tracing_config {
mode = "Active"
}
tags = {
Environment = var.environment
ManagedBy = "terraform"
}
}resource "aws_apigatewayv2_api" "lambda_api" {
name = "${var.function_name}-api"
protocol_type = "HTTP"
cors_configuration {
allow_origins = ["*"]
allow_methods = ["GET", "POST", "OPTIONS"]
allow_headers = ["Content-Type"]
max_age = 300
}
}
resource "aws_apigatewayv2_stage" "default" {
api_id = aws_apigatewayv2_api.lambda_api.id
name = "$default"
auto_deploy = true
access_log_settings {
destination_arn = aws_cloudwatch_log_group.api_gw.arn
format = jsonencode({
requestId = "$context.requestId"
ip = "$context.identity.sourceIp"
requestTime = "$context.requestTime"
httpMethod = "$context.httpMethod"
routeKey = "$context.routeKey"
status = "$context.status"
protocol = "$context.protocol"
responseLength = "$context.responseLength"
})
}
}
resource "aws_apigatewayv2_integration" "lambda" {
api_id = aws_apigatewayv2_api.lambda_api.id
integration_type = "AWS_PROXY"
integration_uri = aws_lambda_function.api.invoke_arn
integration_method = "POST"
}
resource "aws_apigatewayv2_route" "default" {
api_id = aws_apigatewayv2_api.lambda_api.id
route_key = "GET /"
target = "integrations/${aws_apigatewayv2_integration.lambda.id}"
}
resource "aws_lambda_permission" "api_gw" {
statement_id = "AllowAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.api.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.lambda_api.execution_arn}/*/*"
}resource "aws_cloudwatch_log_group" "lambda" {
name = "/aws/lambda/${aws_lambda_function.api.function_name}"
retention_in_days = 14
}
resource "aws_cloudwatch_log_group" "api_gw" {
name = "/aws/apigateway/${aws_apigatewayv2_api.lambda_api.name}"
retention_in_days = 14
}# variables.tf
variable "function_name" {
default = "my-api-function"
}
variable "environment" {
default = "production"
}
# outputs.tf
output "api_endpoint" {
value = aws_apigatewayv2_stage.default.invoke_url
}
output "function_name" {
value = aws_lambda_function.api.function_name
}terraform init
terraform plan
terraform applyAfter deployment, Terraform outputs the API endpoint URL. Test it with:
curl $(terraform output -raw api_endpoint)source_code_hash to detect code changes automaticallyLearn by doing with interactive courses on CopyPasteLearn:
Terraform makes Lambda deployments repeatable and version-controlled. By combining Lambda with API Gateway, IAM, and CloudWatch through Terraform, you get a complete serverless stack that's easy to maintain, replicate across environments, and roll back when needed.
Build event-driven architectures with AWS EventBridge managed by Terraform — custom buses, rules, and cross-account events.
Orchestrate serverless workflows with AWS Step Functions and Terraform — state machines, error handling, and retries. Step-by-step guide with code examples a...
Configure AWS SNS topics and SQS queues with Terraform for reliable event-driven messaging architectures. Step-by-step guide with code examples and best prac...
Protect your applications with AWS WAF rules managed by Terraform — rate limiting, IP blocking, and SQL injection prevention.