In the world of cloud computing, serverless architectures and Infrastructure as Code (IaC) are two paradigms that have revolutionized how we build and manage applications. AWS Lambda, a leading serverless compute service, allows you to run code without provisioning servers. Terraform, an open-source IaC tool, enables you to define and manage infrastructure with code. Combining them is a match made in DevOps heaven. This guide provides a deep dive into deploying, managing, and automating your serverless functions with AWS Lambda Terraform, transforming your workflow from manual clicks to automated, version-controlled deployments.
Table of Contents
Why Use Terraform for AWS Lambda Deployments?
While you can easily create a Lambda function through the AWS Management Console, this approach doesn’t scale and is prone to human error. Using Terraform to manage your Lambda functions provides several key advantages:
- Repeatability and Consistency: Define your Lambda function, its permissions, triggers, and environment variables in code. This ensures you can deploy the exact same configuration across different environments (dev, staging, prod) with a single command.
- Version Control: Store your infrastructure configuration in a Git repository. This gives you a full history of changes, the ability to review updates through pull requests, and the power to roll back to a previous state if something goes wrong.
- Automation: Integrate your Terraform code into CI/CD pipelines to fully automate the deployment process. A `git push` can trigger a pipeline that plans, tests, and applies your infrastructure changes seamlessly.
- Full Ecosystem Management: Lambda functions rarely exist in isolation. They need IAM roles, API Gateway triggers, S3 bucket events, or DynamoDB streams. Terraform allows you to define and manage this entire ecosystem of related resources in a single, cohesive configuration.
Prerequisites
Before we start writing code, make sure you have the following tools installed and configured on your system:
- AWS Account: An active AWS account with permissions to create IAM roles and Lambda functions.
- AWS CLI: The AWS Command Line Interface installed and configured with your credentials (e.g., via `aws configure`).
- Terraform: The Terraform CLI (version 1.0 or later) installed.
- A Code Editor: A text editor or IDE like Visual Studio Code.
- Python 3: We’ll use Python for our example Lambda function, so ensure you have a recent version installed.
Core Components of an AWS Lambda Terraform Deployment
A typical serverless deployment involves more than just the function code. With Terraform, we define each piece as a resource. Let’s break down the essential components.
1. The Lambda Function Code (Python Example)
This is the actual application logic you want to run. For this guide, we’ll use a simple “Hello World” function in Python.
# src/lambda_function.py
import json
def lambda_handler(event, context):
print("Lambda function invoked!")
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda deployed by Terraform!')
}
2. The Deployment Package (.zip)
AWS Lambda requires your code and its dependencies to be uploaded as a deployment package, typically a `.zip` file. Instead of creating this file manually, we can use Terraform’s built-in `archive_file` data source to do it automatically during the deployment process.
# main.tf
data "archive_file" "lambda_zip" {
type = "zip"
source_dir = "${path.module}/src"
output_path = "${path.module}/dist/lambda_function.zip"
}
3. The IAM Role and Policy
Every Lambda function needs an execution role. This is an IAM role that grants the function permission to interact with other AWS services. At a minimum, it needs permission to write logs to Amazon CloudWatch. We define the role and attach a policy to it.
# main.tf
# IAM role that the Lambda function will assume
resource "aws_iam_role" "lambda_exec_role" {
name = "lambda_basic_execution_role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
# Attaching the basic execution policy to the role
resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" {
role = aws_iam_role.lambda_exec_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
The `assume_role_policy` document specifies that the AWS Lambda service is allowed to “assume” this role. We then attach the AWS-managed `AWSLambdaBasicExecutionRole` policy, which provides the necessary CloudWatch Logs permissions. For more details, refer to the official documentation on AWS Lambda Execution Roles.
4. The Lambda Function Resource (`aws_lambda_function`)
This is the central resource that ties everything together. It defines the Lambda function itself, referencing the IAM role and the deployment package.
# main.tf
resource "aws_lambda_function" "hello_world_lambda" {
function_name = "HelloWorldLambdaTerraform"
# Reference to the zipped deployment package
filename = data.archive_file.lambda_zip.output_path
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
# Reference to the IAM role
role = aws_iam_role.lambda_exec_role.arn
# Function configuration
handler = "lambda_function.lambda_handler" # filename.handler_function_name
runtime = "python3.9"
}
Notice the `source_code_hash` argument. This is crucial. It tells Terraform to trigger a new deployment of the function only when the content of the `.zip` file changes.
Step-by-Step Guide: Your First AWS Lambda Terraform Project
Let’s put all the pieces together into a working project.
Step 1: Project Structure
Create a directory for your project with the following structure:
my-lambda-project/
├── main.tf
└── src/
└── lambda_function.py
Step 2: Writing the Lambda Handler
Place the simple Python “Hello World” code into `src/lambda_function.py` as shown in the previous section.
Step 3: Defining the Full Terraform Configuration
Combine all the Terraform snippets into your `main.tf` file. This single file will define our entire infrastructure.
# main.tf
# Configure the AWS provider
provider "aws" {
region = "us-east-1" # Change to your preferred region
}
# 1. Create a zip archive of our Python code
data "archive_file" "lambda_zip" {
type = "zip"
source_dir = "${path.module}/src"
output_path = "${path.module}/dist/lambda_function.zip"
}
# 2. Create the IAM role for the Lambda function
resource "aws_iam_role" "lambda_exec_role" {
name = "lambda_basic_execution_role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
# 3. Attach the basic execution policy to the role
resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" {
role = aws_iam_role.lambda_exec_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
# 4. Create the Lambda function resource
resource "aws_lambda_function" "hello_world_lambda" {
function_name = "HelloWorldLambdaTerraform"
filename = data.archive_file.lambda_zip.output_path
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
role = aws_iam_role.lambda_exec_role.arn
handler = "lambda_function.lambda_handler"
runtime = "python3.9"
# Ensure the IAM role is created before the Lambda function
depends_on = [
aws_iam_role_policy_attachment.lambda_policy_attachment,
]
tags = {
ManagedBy = "Terraform"
}
}
# 5. Output the Lambda function name
output "lambda_function_name" {
value = aws_lambda_function.hello_world_lambda.function_name
}
Step 4: Deploying the Infrastructure
Now, open your terminal in the `my-lambda-project` directory and run the standard Terraform workflow commands:
- Initialize Terraform: This downloads the necessary AWS provider plugin.
terraform init
- Plan the deployment: This shows you what resources Terraform will create. It’s a dry run.
terraform plan
- Apply the changes: This command actually creates the resources in your AWS account.
terraform apply
Terraform will prompt you to confirm the action. Type `yes` and hit Enter. After a minute, your IAM role and Lambda function will be deployed!
Step 5: Invoking and Verifying the Lambda Function
You can invoke your newly deployed function directly from the AWS CLI:
aws lambda invoke \
--function-name HelloWorldLambdaTerraform \
--region us-east-1 \
output.json
This command calls the function and saves the response to `output.json`. If you inspect the file (`cat output.json`), you should see:
{"statusCode": 200, "body": "\"Hello from Lambda deployed by Terraform!\""}
Success! You’ve just automated a serverless deployment.
Advanced Concepts and Best Practices
Let’s explore some more advanced topics to make your AWS Lambda Terraform deployments more robust and feature-rich.
Managing Environment Variables
You can securely pass configuration to your Lambda function using environment variables. Simply add an `environment` block to your `aws_lambda_function` resource.
resource "aws_lambda_function" "hello_world_lambda" {
# ... other arguments ...
environment {
variables = {
LOG_LEVEL = "INFO"
API_URL = "https://api.example.com"
}
}
}
Triggering Lambda with API Gateway
A common use case is to trigger a Lambda function via an HTTP request. Terraform can manage the entire API Gateway setup for you. Here’s a minimal example of creating an HTTP endpoint that invokes our function.
# Create the API Gateway
resource "aws_apigatewayv2_api" "lambda_api" {
name = "lambda-gw-api"
protocol_type = "HTTP"
}
# Create the integration between API Gateway and Lambda
resource "aws_apigatewayv2_integration" "lambda_integration" {
api_id = aws_apigatewayv2_api.lambda_api.id
integration_type = "AWS_PROXY"
integration_uri = aws_lambda_function.hello_world_lambda.invoke_arn
}
# Define the route (e.g., GET /hello)
resource "aws_apigatewayv2_route" "api_route" {
api_id = aws_apigatewayv2_api.lambda_api.id
route_key = "GET /hello"
target = "integrations/${aws_apigatewayv2_integration.lambda_integration.id}"
}
# Grant API Gateway permission to invoke the Lambda
resource "aws_lambda_permission" "api_gw_permission" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.hello_world_lambda.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.lambda_api.execution_arn}/*/*"
}
output "api_endpoint" {
value = aws_apigatewayv2_api.lambda_api.api_endpoint
}
Frequently Asked Questions
- How do I handle function updates with Terraform?
- Simply change your Python code in the `src` directory. The next time you run `terraform plan` and `terraform apply`, the `archive_file` data source will compute a new `source_code_hash`, and Terraform will automatically upload the new version of your code.
- What’s the best way to manage secrets for my Lambda function?
- Avoid hardcoding secrets in Terraform files or environment variables. The best practice is to use AWS Secrets Manager or AWS Systems Manager Parameter Store. You can grant your Lambda’s execution role permission to read from these services and fetch secrets dynamically at runtime.
- Can I use Terraform to manage multiple Lambda functions in one project?
- Absolutely. You can define multiple `aws_lambda_function` resources. For better organization, consider using Terraform modules to create reusable templates for your Lambda functions, each with its own code, IAM role, and configuration.
- How does the `source_code_hash` argument work?
- It’s a base64-encoded SHA256 hash of the content of your deployment package. Terraform compares the hash in your state file with the newly computed hash from the `archive_file` data source. If they differ, Terraform knows the code has changed and initiates an update to the Lambda function. For more details, consult the official Terraform documentation.

Conclusion
You have successfully configured, deployed, and invoked a serverless function using an Infrastructure as Code approach. By leveraging Terraform, you’ve created a process that is automated, repeatable, and version-controlled. This foundation is key to building complex, scalable, and maintainable serverless applications on AWS. Adopting an AWS Lambda Terraform workflow empowers your team to move faster and with greater confidence, eliminating manual configuration errors and providing a clear, auditable history of your infrastructure’s evolution. Thank you for reading the DevopsRoles page!