Lambda Function VPC Multi-AZ Configuration
Overview
This check verifies that AWS Lambda functions connected to a VPC use subnets in at least two different Availability Zones (AZs). When a Lambda function needs access to resources inside a VPC (like databases or internal APIs), it creates Elastic Network Interfaces (ENIs) in the subnets you configure. Spreading these across multiple AZs ensures your function keeps working even if one AZ has problems.
Risk
If your Lambda function only uses subnets in a single Availability Zone, you face several risks:
- AZ outages: If that AZ goes down, your function cannot create ENIs and will fail to connect to VPC resources
- IP exhaustion: If the subnet runs out of IP addresses, new function invocations cannot start
- Service disruptions: Failed invocations cause timeouts and event backlogs, delaying critical processing
Multi-AZ deployment provides fault tolerance. If one AZ has issues, Lambda can use ENIs in the other AZ.
Remediation Steps
Prerequisites
You need:
- Access to the AWS Console with permissions to modify Lambda functions
- At least two subnets in different Availability Zones within your VPC
- A security group that allows your function's required network access
How to find subnets in different AZs
- Go to VPC > Subnets in the AWS Console
- Note the Availability Zone column for each subnet
- Select subnets from at least two different AZs (e.g.,
us-east-1aandus-east-1b) - Ensure the subnets have available IP addresses and appropriate route tables
AWS Console Method
- Open the Lambda console at https://console.aws.amazon.com/lambda/
- Click on your function name to open its configuration
- Select the Configuration tab
- Click VPC in the left sidebar
- Click Edit
- Under Subnets, select subnets from at least two different Availability Zones
- The AZ is shown next to each subnet name
- Verify a Security group is selected that allows your function's network needs
- Click Save
- Wait for the function to update (this may take a minute while Lambda provisions ENIs)
AWS CLI
View current VPC configuration:
aws lambda get-function-configuration \
--function-name <your-function-name> \
--region us-east-1 \
--query 'VpcConfig'
Update function to use multiple AZ subnets:
aws lambda update-function-configuration \
--function-name <your-function-name> \
--vpc-config SubnetIds=<subnet-id-az1>,<subnet-id-az2>,SecurityGroupIds=<security-group-id> \
--region us-east-1
Replace:
<your-function-name>with your Lambda function name<subnet-id-az1>with a subnet ID in the first AZ (e.g.,subnet-abc123)<subnet-id-az2>with a subnet ID in a different AZ (e.g.,subnet-def456)<security-group-id>with your security group ID (e.g.,sg-xyz789)
Example with real-looking values:
aws lambda update-function-configuration \
--function-name my-api-function \
--vpc-config SubnetIds=subnet-0a1b2c3d4e5f6a7b8,subnet-1b2c3d4e5f6a7b8c9,SecurityGroupIds=sg-0123456789abcdef0 \
--region us-east-1
CloudFormation
Use this template to create a Lambda function with multi-AZ VPC configuration:
AWSTemplateFormatVersion: '2010-09-09'
Description: Lambda function with Multi-AZ VPC configuration
Parameters:
FunctionName:
Type: String
Description: Name of the Lambda function
SubnetId1:
Type: AWS::EC2::Subnet::Id
Description: First subnet ID (in AZ 1)
SubnetId2:
Type: AWS::EC2::Subnet::Id
Description: Second subnet ID (in AZ 2)
SecurityGroupId:
Type: AWS::EC2::SecurityGroup::Id
Description: Security group ID for the Lambda function
Resources:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub '${FunctionName}-execution-role'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Ref FunctionName
Runtime: python3.12
Handler: index.handler
Role: !GetAtt LambdaExecutionRole.Arn
Code:
ZipFile: |
def handler(event, context):
return {'statusCode': 200, 'body': 'Hello from Lambda'}
VpcConfig:
SecurityGroupIds:
- !Ref SecurityGroupId
SubnetIds:
- !Ref SubnetId1
- !Ref SubnetId2
Outputs:
FunctionArn:
Description: Lambda function ARN
Value: !GetAtt LambdaFunction.Arn
FunctionName:
Description: Lambda function name
Value: !Ref LambdaFunction
Key points:
- The
VpcConfigblock requires bothSubnetIdsandSecurityGroupIds - The IAM role must include
AWSLambdaVPCAccessExecutionRolefor VPC access - Pass subnet IDs from different AZs as parameters when deploying
Terraform
variable "function_name" {
description = "Name of the Lambda function"
type = string
}
variable "subnet_ids" {
description = "List of subnet IDs in different AZs"
type = list(string)
}
variable "security_group_ids" {
description = "List of security group IDs"
type = list(string)
}
variable "handler" {
description = "Lambda function handler"
type = string
default = "index.handler"
}
variable "runtime" {
description = "Lambda runtime"
type = string
default = "python3.12"
}
# IAM role for Lambda VPC access
resource "aws_iam_role" "lambda_vpc_role" {
name = "${var.function_name}-vpc-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
# Attach the VPC access policy
resource "aws_iam_role_policy_attachment" "lambda_vpc_policy" {
role = aws_iam_role.lambda_vpc_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
}
# Lambda function with multi-AZ VPC configuration
resource "aws_lambda_function" "multi_az_function" {
function_name = var.function_name
role = aws_iam_role.lambda_vpc_role.arn
handler = var.handler
runtime = var.runtime
filename = "lambda.zip"
source_code_hash = filebase64sha256("lambda.zip")
vpc_config {
subnet_ids = var.subnet_ids
security_group_ids = var.security_group_ids
}
}
output "function_arn" {
description = "ARN of the Lambda function"
value = aws_lambda_function.multi_az_function.arn
}
output "function_name" {
description = "Name of the Lambda function"
value = aws_lambda_function.multi_az_function.function_name
}
Example tfvars:
function_name = "my-api-function"
subnet_ids = ["subnet-0a1b2c3d4e5f6a7b8", "subnet-1b2c3d4e5f6a7b8c9"]
security_group_ids = ["sg-0123456789abcdef0"]
Verification
After making changes, verify your function uses subnets in multiple AZs:
- Open your function in the Lambda console
- Go to Configuration > VPC
- Check that the listed subnets are in different Availability Zones
CLI verification
# Get the function's subnet configuration
aws lambda get-function-configuration \
--function-name <your-function-name> \
--region us-east-1 \
--query 'VpcConfig.SubnetIds'
# Check which AZs those subnets are in
aws ec2 describe-subnets \
--subnet-ids <subnet-id-1> <subnet-id-2> \
--region us-east-1 \
--query 'Subnets[*].[SubnetId,AvailabilityZone]' \
--output table
Re-run the Prowler check:
prowler aws --checks awslambda_function_vpc_multi_az --region us-east-1
Additional Resources
- AWS Lambda VPC Configuration
- Configuring a Lambda function to access resources in a VPC
- AWS Lambda resilience best practices
- VPC subnet sizing for Lambda
Notes
- Update time: Changing VPC configuration can take up to a minute while Lambda provisions new ENIs
- IP addresses: Each concurrent Lambda execution needs an IP address from the subnet. Ensure subnets have enough available IPs
- NAT Gateway: If your function needs internet access, each AZ needs a route to a NAT Gateway
- VPC Endpoints: For AWS service access without internet, consider VPC endpoints in each AZ
- Existing functions: You can update existing functions without deleting them. The update is applied to new invocations
- Cost consideration: Using multiple AZs may require NAT Gateways in each AZ, which adds cost