Guide to AWS Lambda Function URLs
- Authors
- Name
- Tomasz Łakomy
- @tlakomy
For the longest time, the go-to way of calling an AWS Lambda function via HTTP(S) was to put an API Gateway in front of it. While this works well (and it's still a required pattern for many, many serverless use cases), sometimes developers wanted to "just call an AWS Lambda function" by sending a network request.
Introducing AWS Lambda Function URLs - a new feature in AWS Lambda that allows you to call a Lambda function without an API Gateway.
What is a Lambda Function URL?
Simply put - it's an URL that you can send a network request to to call a Lambda function. An example URL may look like this:
https://vg7sczk62ycloct63yi3wjpoj40sgkuz.lambda-url.eu-central-1.on.aws/
or, in general:
https://<url-id>.lambda-url.<region>.on.aws/
Lambda function URL can point to either $LATEST
or to an user-defined alias. Even though no additional resources are required (e.g. API Gateway or an ALB), function URL is a separate CloudFormation resource which needs to be provisioned separately.
How do I create an AWS Lambda function URL?
You can create an AWS Lambda function URL via:
- AWS Management Console (Cloudash team does not recommend so-called ClickOps for production usage, use IaC instead)
- AWS CLI
- AWS CloudFormation
- AWS Serverless Application Model (AWS SAM)
- AWS CDK
Could you give me an example?
Sure thing, this is how one might create an AWS Lambda function + and a function url to call it directly using AWS CDK:
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
export class LambdaUrlStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const myLambda = new cdk.aws_lambda.Function(this, "myLambda", {
code: cdk.aws_lambda.Code.fromAsset("lambda"),
handler: "index.handler",
runtime: cdk.aws_lambda.Runtime.NODEJS_16_X,
});
const lambdaUrl = new cdk.aws_lambda.CfnUrl(this, "lambdaUrl", {
targetFunctionArn: myLambda.functionArn,
authType: cdk.aws_lambda.FunctionUrlAuthType.NONE,
});
}
}
And yes, authType: cdk.aws_lambda.FunctionUrlAuthType.NONE
is not exactly secure. Keep reading to learn more:
Security and auth model for Lambda function URLs
Controlling access to Lambda function URLs is performed using the AuthType
parameter combined with resource-based policies attached to a particular function.
To quote AWS docs, there are two possible values of AuthType
parameter:
AWS_IAM
– Lambda uses AWS Identity and Access Management (IAM) to authenticate and authorize requests based on the IAM principal's identity policy and the function's resource-based policy. Choose this option if you want only authenticated IAM users and roles to invoke your function via the function URL.
NONE
– Lambda doesn't perform any authentication before invoking your function. However, your function's resource-based policy is always in effect and must grant public access before your function URL can receive requests. Choose this option to allow public, unauthenticated access to your function URL.
AWS_IAM
auth type
When a Lambda function URL has an AWS_IAM
AuthType
then whoever needs to invoke this particular Lambda function URL must have the lambda:InvokeFunctionUrl
permission for a particular Lambda function.
Note: lambda:InvokeFunctionUrl
is different than lambda:InvokeFunction
, so you may need to adjust your IAM permissions accordingly when opting in to use this feature.
NONE
auth type
When a Lambda function URL AuthType
is set to NONE
then any unauthenticated user with your function URL can invoke your function - proceed with caution. This might be useful whenever you might want to allow public access to your function URL e.g. via a web browser.
Even though the auth type is set to NONE
and Lambda does not use IAM to authenticate requests to a function URL, whoever tries to the function needs to have the lambda:InvokeFunctionUrl
permissions.
An example function URL invoke policy for all unauthenticated principals:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "lambda:InvokeFunctionUrl",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
"Condition": {
"StringEquals": {
"lambda:FunctionUrlAuthType": "NONE"
}
}
}
]
}
When creating a function URL with auth type set to NONE
via the AWS Console or AWS SAM, the resource-based policy statement listed above will be automatically created for you. When e.g. using AWS SDK you'd need to create it yourself, example of how one might want to do this below:
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
export class LambdaUrlStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const myLambda = new cdk.aws_lambda.Function(this, "myLambda", {
code: cdk.aws_lambda.Code.fromAsset("lambda"),
handler: "index.handler",
runtime: cdk.aws_lambda.Runtime.NODEJS_16_X,
});
const lambdaUrl = new cdk.aws_lambda.CfnUrl(this, "lambdaUrl", {
targetFunctionArn: myLambda.functionArn,
authType: cdk.aws_lambda.FunctionUrlAuthType.NONE,
});
const lambdaPermission = new cdk.CfnResource(this, "lambdaPermission", {
type: "AWS::Lambda::Permission",
properties: {
Action: "lambda:InvokeFunctionUrl",
FunctionName: myLambda.functionArn,
Principal: "*",
FunctionUrlAuthType: "NONE",
},
});
}
}
Pricing
Lambda function URLs are included in AWS Lambda's pricing - there are no additional charges for using this feature (and you can save money on not using API Gateway)
Limits
Lambda function URLs share the same limits as AWS Lambda functions:
- 6 MB response and request payload size
- Default 1,000 up to tens of thousands TPS
- 15-minute timeout
In short - there is no additional cost, no additional timeout and payload limits when choosing to use Lambda function URLs.
Check out the official AWS docs to learn more.
So, what's the difference between Function URLs and API Gateway? Are Function URLs objectively better?
Not exactly, there's always a tradeoff.
Feature | API Gateway REST APIs | Function URLs |
---|---|---|
HTTPS | Yes | Yes |
Payload limit | 6 MB (with AWS Lambda) | 6 MB |
Max timeout | 29 seconds | Up to 15 minutes |
SDK generation | Yes | No |
Cost | from $3.50/million for first 333 million | Free |
AWS WAF | Yes | No |
Usage plans | Yes | No |
Request/response validation and transformation | Yes | No |
Function URLs have a greatly extended timeout (up to 15 minutes) compared to API Gateway + Lambda, with the tradeoff of highly reduced security/usage limits capabilities.
To quote Announcing AWS Lambda Function URLs blogpost:
Function URLs are best for use cases where you must implement a single-function microservice with a public endpoint that doesn’t require the advanced functionality of API Gateway, such as request validation, throttling, custom authorizers, custom domain names, usage plans, or caching. [...] It is also the simplest way to invoke your Lambda functions during research and development without leaving the Lambda console or integrating additional services.
Use API Gateway to take advantage of capabilities like JWT/custom authorizers, request/response validation and transformation, usage plans, built-in AWS WAF support, and so on.
Learn more in Lambda function URLs documentation.
Tired of switching between AWS console tabs? 😒
Cloudash provides clear access to CloudWatch logs and metrics, to help you make quicker decisions.
Try it for free: