Introdcution
AWS released that AWS ALB(ALB) can connect to AWS Lambda(Lambda).
We also can connect to AWS NLB(NLB) to ALB. So I want to write about this and how do we implement this
Overall
Component
What we want to discuss involves the following components. The request begins at the NLB, proceeds to the ALB, and finally reaches the Lambda. This flow is essential for understanding the system’s overall architecture and its operational efficiency. Let’s delve into the details to ensure we cover all aspects thoroughly.

Implementation
# nlb
resource "aws_lb" "sample_nlb" {
name = "nlb"
load_balancer_type = "network"
internal = true
enable_cross_zone_load_balancing = true
subnet_mapping {
subnet_id = aws_subnet.subnet["a"].id,
private_ipv4_address = "10.20.0.01"
}
}
resource "aws_lb_listener" "sample_nlb" {
load_balancer_arn = aws_lb.sample_nlb.arn
protocol = "TCP"
port = "80"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.sample_nlb_tg.arn
}
}
resource "aws_lb_target_group" "sample_nlb_tg" {
name = "nlb-tg"
target_type = "alb"
vpc_id = aws_vpc.sample.id
protocol = "TCP"
port = 80
}
resource "aws_lb_target_group_attachment" "sample_nlb_alb_attachment" {
target_group_arn = aws_lb_target_group.sample_nlb_tg.arn
target_id = aws_lb.alb.arn
port = 80
}
# alb
resource "aws_lb" "alb" {
name = "alb"
load_balancer_type = "application"
internal = true
subnets = [
aws_subnet.subnet["b"].id,
aws_subnet.subnet["c"].id,
]
security_groups = [
aws_security_group.alb_sg.id,
]
}
resource "aws_lb_listener" "alb_listener" {
load_balancer_arn = aws_lb.alb.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.alb_tg.arn
}
}
resource "aws_lb_target_group" "alb_tg" {
name = "alb-tg"
vpc_id = aws_vpc.sample.id
target_type = "lambda"
protocol = "HTTP"
port = 80
}
resource "aws_lb_target_group_attachment" "lambda_attachment" {
target_group_arn = aws_lb_target_group.alb_tg.arn
target_id = module.sample.lambda_function_arn
}
# lambda
module "sample" {
source = "terraform-aws-modules/lambda/aws"
function_name = "sample"
description = "sample"
create_package = false
package_type = "Image"
image_uri = "${aws_ecr_repository.sample.repository_url}:latest"
timeout = 30
vpc_subnet_ids = [
aws_subnet.subnet["d"].id,
aws_subnet.subnet["e"].id,
]
vpc_security_group_ids = [
aws_security_group.alb_to_lambda.id,
]
attach_network_policy = true
environment_variables = {
ENV = "hoge"
}
}
resource "aws_lambda_permission" "with_lb" {
statement_id = "AllowExecutionFromlb"
action = "lambda:InvokeFunction"
function_name = module.receive_notification.lambda_function_arn
principal = "elasticloadbalancing.amazonaws.com"
source_arn = aws_lb_target_group.alb_tg.arn
}
Checkpoint
NLB has heealth check by default
This means we have to implement health check path in lambda. Unlike with an ALB, where we can manually configure and manage health checks, this functionality cannot be manually removed or bypassed in the case of Lambda.
Request from NLB is a Event
The request from the NLB is structured as follows. We retrieve the path through the event object, which differs slightly from typical HTTP frameworks like Gin or Echo. This method introduces some unique nuances in handling requests. Although you might find this repository helpful for implementation, I haven’t had the chance to test it yet,
https://github.com/awslabs/aws-lambda-go-api-proxy
{
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
}
},
"httpMethod": "GET",
"path": "/lambda",
"queryStringParameters": {
"query": "1234ABCD"
},
...
...
}
Cross-zone load balancing in NLB
Enabling this function allows traffic to be distributed across all registered targets in every registered Availability Zone. This setup provides an efficient way to design redundancy, ensuring high availability, while keeping costs relatively low.
Lambda permission for Loadbalancer
Of course, it is essential to configure the permission to allow the LoadBalancer to invoke the Lambda.
resource "aws_lambda_permission" "with_lb" {
statement_id = "AllowExecutionFromlb"
action = "lambda:InvokeFunction"
function_name = module.sample.lambda_function_arn
principal = "elasticloadbalancing.amazonaws.com"
source_arn = aws_lb_target_group.alb_tg.arn
}