Lambda Function#
A flexible Terraform module for creating AWS Lambda functions with a kwargs-like approach for additional attributes, optional execution role creation, ARM64 architecture for optimal price-performance.
Features#
kwargs-like flexibility: Use
additional_attributesto pass any Lambda function attributeType-safe core attributes: Essential attributes are explicitly defined with proper types
Dynamic configuration: Support for VPC, file system, tracing, and more
Backward compatible: Works with minimal configuration or complex setups
Comprehensive outputs: Expose all useful Lambda function attributes
Optional execution role: Automatically create and configure Lambda execution role with security best practices
Confused deputy protection: IAM trust policies include account conditions to prevent security attacks
Configuration validation: Ensures required parameters are provided at plan time, not apply time
Custom policies: Attach custom execution policies to the Lambda role
ARM64 by default: Optimized for price-performance with Graviton2/Graviton3 processors
Robust hash-based change detection: Use an explicit hash for reliable, efficient deployments
Modern Usage Example: Hash-Based Lambda Deployment#
This pattern ensures your Lambda ZIP is only rebuilt and redeployed when the source code changes, using a dedicated folder hash module and builder module.
module "lambda_one" {
source = "./modules/lambda/function"
function_name = "simple-lambda-one"
description = "Simple Lambda function with minimal configuration..."
create_execution_role = true
zip_path = "path/to/zip_file.zip"
source_code_hash = "hash_code"
depends_on = [
module.folder_hash_lambda_one,
module.my_lambda_one_builder
]
}
Why this pattern?#
Efficient builds: The ZIP is only rebuilt when the source code changes.
Reliable deployments: Lambda is only updated when the code or configuration changes.
Explicit and reproducible: The hash is calculated in a dedicated module, making dependencies clear.
Note
The source_code_hash variable must be provided by the user. This module does not read .base64sha256 files automatically; you should pass the hash output from your builder or hash module.
ARM64 Architecture Benefits#
This module defaults to ARM64 architecture for the following benefits:
đź’° 20-34% cost savings compared to x86_64
⚡ Better performance for most workloads
🔋 Lower power consumption and carbon footprint
🔄 Faster cold starts in many scenarios
📦 Smaller deployment packages for some runtimes
You can still use x86_64 if needed for compatibility with specific libraries or requirements.
Integration with Lambda Builder Module#
locals {
root_path = abspath(path.module)
build_path = "${local.root_path}/.build"
lambdas_path = "${local.root_path}/project/lambdas"
}
# 1. Calculate a hash of all source files in the Lambda directory
module "folder_hash_lambda_one" {
source = "./modules/utils/folder_hash"
source_dir = "${local.lambdas_path}/lambda_one"
}
# 2. Build the Lambda ZIP only when the source hash changes
module "my_lambda_one_builder" {
source = "./modules/lambda/builder"
project_dir = local.root_path
source_dir = "${local.lambdas_path}/lambda_one"
build_dir = "${local.build_path}/project/lambdas/lambda_one"
output_zip = "${local.build_path}/project/lambdas/lambda_one/my_lambda.zip"
source_hash = module.folder_hash_lambda_one.folder_hash
depends_on = [
module.folder_hash_lambda_one
]
}
# 3. Deploy the Lambda function, using the ZIP and hash
module "lambda_one" {
source = "./modules/lambda/function"
function_name = "simple-lambda-one"
description = "Simple Lambda function with minimal configuration..."
create_execution_role = true
zip_path = module.my_lambda_one_builder.zip_file
source_code_hash = module.folder_hash_lambda_one.folder_hash
depends_on = [
module.folder_hash_lambda_one,
module.my_lambda_one_builder
]
}
Usage Examples#
Basic Usage with External Role#
module "simple_lambda" {
source = "./modules/lambda/function"
function_name = "my-function"
description = "A simple Lambda function (ARM64 by default)"
role_arn = aws_iam_role.lambda_role.arn
zip_path = "path/to/function.zip"
source_code_hash = filebase64sha256("path/to/function.zip")
}
# Access outputs
output "lambda_arn" {
value = module.simple_lambda.arn
}
output "lambda_architecture" {
value = module.simple_lambda.architectures # ["arm64"]
}
Basic Usage with Auto-Created Execution Role#
module "simple_lambda_with_role" {
source = "./modules/lambda/function"
function_name = "my-function"
description = "A simple Lambda function with auto-created role"
create_execution_role = true
zip_path = "path/to/function.zip"
source_code_hash = filebase64sha256("path/to/function.zip")
}
# Access execution role outputs
output "execution_role_arn" {
value = module.simple_lambda_with_role.execution_role_arn
}
Using x86_64 Architecture#
module "x86_lambda" {
source = "./modules/lambda/function"
function_name = "x86-function"
description = "Lambda function using x86_64 architecture"
create_execution_role = true
architectures = ["x86_64"] # Override default ARM64
zip_path = "path/to/function.zip"
source_code_hash = filebase64sha256("path/to/function.zip")
}
Advanced Usage with VPC and Custom Policies#
module "vpc_lambda" {
source = "./modules/lambda/function"
function_name = "vpc-lambda"
description = "Lambda function in VPC with custom policies"
create_execution_role = true
execution_policies = {
"s3-access" = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["s3:GetObject", "s3:PutObject"]
Resource = "arn:aws:s3:::my-bucket/*"
}
]
})
"dynamodb-access" = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["dynamodb:GetItem", "dynamodb:PutItem"]
Resource = "arn:aws:dynamodb:us-east-1:123456789012:table/my-table"
}
]
})
}
zip_path = "path/to/function.zip"
source_code_hash = filebase64sha256("path/to/function.zip")
additional_attributes = {
vpc_config = {
subnet_ids = ["subnet-12345678", "subnet-87654321"]
security_group_ids = ["sg-12345678"]
}
tracing_config = {
mode = "Active"
}
reserved_concurrent_executions = 10
}
}
Available additional_attributes#
The additional_attributes variable accepts any valid AWS Lambda function attribute.
Block Attributes#
vpc_config- VPC configurationfile_system_config- EFS mount configurationtracing_config- X-Ray tracing configurationimage_config- Container image configurationdead_letter_config- Dead letter queue configuration
Simple Attributes#
reserved_concurrent_executions- Concurrency limitpublish- Publish versionlayers- Lambda layerskms_key_arn- KMS encryption keypackage_type- Package type (Zip/Image)image_uri- Container image URIcode_signing_config_arn- Code signing configuration
Inputs#
Name |
Description |
Type |
Default |
Required |
|---|---|---|---|---|
function_name |
Name of the Lambda function |
string |
n/a |
yes |
description |
Description of the Lambda function |
string |
n/a |
yes |
role_arn |
IAM role ARN for the Lambda function (required if create_execution_role = false) |
string |
null |
no |
create_execution_role |
Whether to create a Lambda execution role automatically |
bool |
false |
no |
execution_policies |
Map of custom execution policies to attach to the Lambda execution role |
map(string) |
{} |
no |
handler |
Handler function |
string |
“handler.handler” |
no |
runtime |
Lambda runtime |
string |
“python3.12” |
no |
architectures |
Instruction set architecture for the Lambda function |
list(string) |
[“arm64”] |
no |
zip_path |
Path to the Lambda deployment package |
string |
n/a |
yes |
source_code_hash |
Code hash of the deployment package |
string |
n/a |
yes |
timeout |
Execution timeout in seconds |
number |
3 |
no |
memory_size |
Amount of memory in MB |
number |
128 |
no |
environment_variables |
Environment variables |
map(string) |
{} |
no |
tags |
Tags to apply |
map(string) |
{} |
no |
additional_attributes |
Additional attributes (kwargs-like) |
map(any) |
{} |
no |
Outputs#
Name |
Description |
|---|---|
name |
The Lambda Function name |
arn |
The Lambda Function ARN |
invoke_arn |
The Lambda Function invoke ARN (used for API Gateway integration) |
qualified_arn |
The Lambda Function qualified ARN (includes version) |
version |
The Lambda Function version |
last_modified |
The date the Lambda Function was last modified |
source_code_size |
The size of the Lambda Function deployment package in bytes |
runtime |
The Lambda Function runtime |
handler |
The Lambda Function handler |
architectures |
The Lambda Function architectures (ARM64 for better price-performance) |
memory_size |
The Lambda Function memory size in MB |
timeout |
The Lambda Function timeout in seconds |
environment_variables |
The Lambda Function environment variables |
vpc_config |
The Lambda Function VPC configuration (if configured) |
layers |
The Lambda Function layers (if configured) |
tags |
The Lambda Function tags |
function_url |
The Lambda Function URL (if configured via additional_attributes) |
reserved_concurrent_executions |
The Lambda Function reserved concurrency limit (if configured) |
kms_key_arn |
The Lambda Function KMS key ARN (if configured) |
signing_job_arn |
The Lambda Function signing job ARN (if code signing is configured) |
signing_profile_version_arn |
The Lambda Function signing profile version ARN (if code signing is configured) |
execution_role_arn |
The Lambda execution role ARN (only when create_execution_role = true) |
execution_role_name |
The Lambda execution role name (only when create_execution_role = true) |
execution_role_id |
The Lambda execution role ID (only when create_execution_role = true) |
Execution Role Features#
When create_execution_role = true, the module automatically:
Creates IAM Role: Lambda execution role with secure assume role policy
Includes
aws:SourceAccountcondition to prevent confused deputy attacksFollows AWS security best practices for service-to-service access
Attaches Basic Policy:
AWSLambdaBasicExecutionRolefor CloudWatch logsAttaches VPC Policy:
AWSLambdaVPCAccessExecutionRoleif VPC is configuredAttaches Custom Policies: Any policies provided in
execution_policiesApplies Tags: Uses the same tags as the Lambda function
Validates Configuration: Ensures
role_arnis provided whencreate_execution_role = false
Automatic Policy Attachments#
Basic Execution: Always attached for CloudWatch logs
VPC Access: Automatically attached when VPC configuration is present
Custom Policies: Attached based on
execution_policiesvariable
ARM64 Architecture Considerations#
Benefits#
Cost Savings: 20-34% lower costs compared to x86_64
Performance: Better performance for most workloads
Efficiency: Lower power consumption and carbon footprint
Cold Starts: Faster cold starts in many scenarios
Compatibility#
Most AWS SDKs: Fully compatible with ARM64
Popular Runtimes: Python, Node.js, Java, .NET, Go, Ruby
Layers: Many public layers available for ARM64
Custom Binaries: May need ARM64 versions of native libraries
When to Use x86_64#
Native Dependencies: Libraries that don’t have ARM64 versions
Legacy Code: Applications with x86_64-specific optimizations
Third-party Tools: Tools that don’t support ARM64
Testing: When testing compatibility with existing x86_64 deployments
Best Practices#
Use explicit attributes for commonly used configurations
Use additional_attributes for advanced or rarely used features
Document complex configurations in your module usage
Validate additional_attributes in your calling code
Use consistent naming for your additional attributes
Leverage outputs for integration with other AWS services
Use create_execution_role for simple Lambda functions
Use external roles for complex IAM requirements
Prefer ARM64 for cost and performance benefits
Test compatibility when migrating from x86_64 to ARM64