# AWS Lambda Function with API Gateway trigger
# === Lambda function ===
resource "aws_lambda_function" "api_handler" {
function_name = "${var.project}-api-handler"
description = "API request handler for ${var.project}"
runtime = "python3.12"
handler = "handler.lambda_handler"
timeout = 30
memory_size = 256
filename = data.archive_file.lambda_zip.output_path
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
role = aws_iam_role.lambda_exec.arn
environment {
variables = {
ENVIRONMENT = var.environment
DATABASE_URL = var.database_url
LOG_LEVEL = "INFO"
CORS_ORIGINS = "https://myapp.example.com"
}
}
vpc_config {
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.lambda.id]
}
tracing_config {
mode = "Active" # Enable X-Ray tracing
}
dead_letter_config {
target_arn = aws_sqs_queue.lambda_dlq.arn
}
tags = {
Environment = var.environment
Service = "api"
}
}
# === Package the Lambda code ===
data "archive_file" "lambda_zip" {
type = "zip"
source_dir = "${path.module}/src"
output_path = "${path.module}/dist/lambda.zip"
}
# === IAM Role ===
resource "aws_iam_role" "lambda_exec" {
name = "${var.project}-lambda-exec"
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/AWSLambdaVPCAccessExecutionRole"
}
resource "aws_iam_role_policy" "lambda_custom" {
name = "${var.project}-lambda-custom"
role = aws_iam_role.lambda_exec.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Query",
]
Resource = var.dynamodb_table_arn
},
{
Effect = "Allow"
Action = ["sqs:SendMessage"]
Resource = aws_sqs_queue.lambda_dlq.arn
}
]
})
}
# === API Gateway v2 (HTTP API) ===
resource "aws_apigatewayv2_api" "main" {
name = "${var.project}-api"
protocol_type = "HTTP"
cors_configuration {
allow_origins = ["https://myapp.example.com"]
allow_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
allow_headers = ["Authorization", "Content-Type"]
max_age = 3600
}
}
resource "aws_apigatewayv2_stage" "default" {
api_id = aws_apigatewayv2_api.main.id
name = "$default"
auto_deploy = true
access_log_settings {
destination_arn = aws_cloudwatch_log_group.api_gateway.arn
format = jsonencode({
requestId = "$context.requestId"
ip = "$context.identity.sourceIp"
method = "$context.httpMethod"
path = "$context.path"
status = "$context.status"
responseLength = "$context.responseLength"
latency = "$context.responseLatency"
})
}
}
resource "aws_apigatewayv2_integration" "lambda" {
api_id = aws_apigatewayv2_api.main.id
integration_type = "AWS_PROXY"
integration_uri = aws_lambda_function.api_handler.invoke_arn
payload_format_version = "2.0"
}
resource "aws_apigatewayv2_route" "default" {
api_id = aws_apigatewayv2_api.main.id
route_key = "$default"
target = "integrations/${aws_apigatewayv2_integration.lambda.id}"
}
resource "aws_lambda_permission" "api_gateway" {
statement_id = "AllowAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.api_handler.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.main.execution_arn}/*/*"
}
# === CloudWatch Logs ===
resource "aws_cloudwatch_log_group" "lambda" {
name = "/aws/lambda/${aws_lambda_function.api_handler.function_name}"
retention_in_days = 14
}
resource "aws_cloudwatch_log_group" "api_gateway" {
name = "/aws/apigateway/${var.project}"
retention_in_days = 14
}
# === Dead Letter Queue ===
resource "aws_sqs_queue" "lambda_dlq" {
name = "${var.project}-lambda-dlq"
message_retention_seconds = 1209600 # 14 days
}
# === Outputs ===
output "api_endpoint" {
value = aws_apigatewayv2_api.main.api_endpoint
}
output "function_name" {
value = aws_lambda_function.api_handler.function_name
}
Deploy serverless functions on AWS Lambda using Terraform. Configure API Gateway integration, CloudWatch logging, environment variables, and IAM roles. Package Python or Node.js handlers with dependencies, set up event triggers, and manage function versioning with aliases.