Networking & Content Delivery

Lambda functions as targets for Application Load Balancers

As of today, Application Load Balancers (ALBs) now support AWS Lambda functions as targets. Build websites and web applications as serverless code, using AWS Lambda to manage and run your functions, and then configure an ALB to provide a simple HTTP/S frontend for requests coming from web browsers and clients.

Triggering a Lambda Function from an Application Load Balancer

To get started, you can associate Lambda functions with ALBs on the Load Balancing section of the Amazon EC2 console or on the AWS Lambda console. Let’s begin with how things work in the Lambda console. In the example below, we’ve chosen Application Load Balancer from the Add triggers list so we can configure a trigger for the HelloWorld Lambda function.

To configure the trigger, you specify which Application Load Balancer to use, and which listeners, hosts, and URL paths to forward to AWS Lambda. If you don’t have an ALB already, when you choose to configure the trigger, there’s a link to create one.

Listeners are the ports that the ALB receives traffic on. For example, there’s typically an HTTP listener on port 80 and an HTTPS listener on port 443. You can choose to send each listener to different Lambda functions, or multiple listeners can go to the same function.

You can also choose to send traffic to different Lambda functions based on a host or a host and URL path in the requests that come to ALB. This is especially useful for hybrid applications where requests from specific domains or URLs are handled with instances—or even legacy on-premises hosts—and other requests are handled with serverless infrastructure provided by AWS Lambda.  For example, you might choose to migrate the user account management functionality from an existing application to a serverless setup. Using the content-based routing provided by an ALB, you can specify that every request that starts with /account/ triggers a Lambda function.

When you complete the configuration, choose Add to finish your Application Load Balancer trigger setup and start forwarding the specified traffic to AWS Lambda. Now when requests that match your listener, host, and path settings arrive on the ALB, the Lambda function is invoked with an event that supplies all of details about the incoming request and load balancer.

Requests can include HTTP GET, HEAD, PUT, POST, DELETE, PATCH and OPTIONS methods, and request and response bodies can be text or binary. The Application Load Balancer that you’ve set up with AWS Lambda takes care of translating an HTTP/S request into an AWS Lambda-compatible event.

Here’s an example of a translated request, after ALB has made the required changes for AWS Lambda:

{
'requestContext': {
'elb': {
'targetGroupArn': 'arn:aws:elasticloadbalancing:us-east-1:XXXXXXXXXXX:targetgroup/sample/6d0ecf831eec9f09'
}
},
'httpMethod': 'GET',
'path': '/',
'queryStringParameters': {},
'headers': {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-encoding': 'gzip',
'accept-language': 'en-US,en;q=0.5',
'connection': 'keep-alive',
'cookie': ‘name=value',
'host': 'lambda-YYYYYYYY.elb.amazonaws.com',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:60.0) Gecko/20100101 Firefox/60.0',
'x-amzn-trace-id': 'Root=1-5bdb40ca-556d8b0c50dc66f0511bf520',
'x-forwarded-for': '192.0.2.1,
'x-forwarded-port': '80',
'x-forwarded-proto': 'http'
},
'body': '',
'isBase64Encoded': False
}

When the request arrives, your AWS Lambda function must then respond with parameters that specify the status code, description, headers, and body to serve to the client. As a simple example, the following is an AWS Lambda function written in Python that renders a HTML “Hello World” message:

def lambda_handler(event, context):
response = {
"statusCode": 200,
"statusDescription": "200 OK",
"isBase64Encoded": False,
"headers": {
"Content-Type": "text/html; charset=utf-8"
}
}

response['body'] = """<html>
<head>
<title>Hello World!</title>
<style>
html, body {
margin: 0; padding: 0;
font-family: arial; font-weight: 700; font-size: 3em;
text-align: center;
}
</style>
</head>
<body>
<p>Hello World!</p>
</body>
</html>"""
return response

With your function written and your ALB trigger configured, you should be all set! A lot of work went into Lambda function as a target “behind the scenes”, to make sure that setting up an ALB as a trigger for a Lambda function would be easy and straightforward.

As another benefit, there’s also a lot of overlap and commonality between the parameters used by Amazon API Gateway for triggering Lambda functions and ALB’s parameters. This makes it easy to use the same Lambda function with either service, or both. If you’re already using AWS Lambda with API Gateway, you’ll feel at home with this new feature very quickly.

Advanced settings: Multi-Value Headers and Failover Configurations

Application Load Balancers provide two advanced options that you may want to configure when you use ALBs with AWS Lambda: support for multi-value headers and health check configurations. You can set up these options in Target Groups section on the Amazon EC2 console.

 

To enable multi-value headers, under Attributes, choose Edit attributes. When you enable multi-value headers, HTTP headers and query string parameters that are sent with multiple values are shown as arrays within the AWS Lambda event and response objects.

For example, suppose the client supplies a query string like “?name=foo&name=bar”. If you’ve enabled multi-value headers, ALB supplies these duplicate parameters as a ‘name’: [‘foo’, ‘bar’] entry in the event object. ALB applies the same processing to duplicate HTTP headers.

Another advanced feature you may find helpful is ALB health checks. When you enable health checks, your load balancer sends requests to your Lambda function to ensure that it’s still working.

Enabling health checks is useful if your load balancer is part of a failover configuration. For example, if your domain is hosted on Amazon Route 53, you can configure failover between multiple Application Load Balancers, CloudFront distributions, S3 buckets, and other resources. Failover ensures that if there’s a problem with your application in one location or deployment, DNS-level failover reroutes incoming traffic to another resource.

The default settings for health checks are shown in the following screenshot. It’s unlikely that you’ll need to change the defaults, but if you like, you can adjust settings for health checks, such as how often they occur, the URL path to use to check the function, and more.

You can choose other options in the Load Balancing section on the EC2 console if you want to configure additional advanced functionality. For example, you can add more content-based routing rules, enable built-in authentication, set up Web Application Firewall (WAF), or send HTTP redirects directly from your Application Load Balancer.

Each Application Load Balancer also includes two new CloudWatch metrics: LambdaTargetProcessedBytes and StandardProcessedBytes. These metrics indicate how much data is processed by AWS Lambda functions as targets and how much is processed by other targets such as EC2 instances, containers, and IP address targets.

Availability and Pricing

AWS Lambda function as a target for ALB is available today in US East (N. Virginia), US East (Ohio), US West (Northern California), US West (Oregon), Asia Pacific (Mumbai), Asia Pacific (Seoul), Asia Pacific (Singapore), Asia Pacific (Sydney), Asia Pacific (Tokyo), Canada ( Central), EU (Frankfurt), EU (Ireland), EU (London), EU (Paris), South America (São Paulo), and GovCloud (US-West) AWS Regions.

There is no change to the hourly price of ALB. The load balancer capacity units (LCUs) of ALB now include 0.4 GB per hour of data processing to AWS Lambda targets.

 


About the Author

Colm MacCárthaigh is a Principal Engineer at AWS. He works on networking, cryptography, and open-source technologies.