Guide to AWS Lambda Function URLs
Tags: aws, lambda, serverless
Published: 2022-08-23 19:43:28

---
title: Guide to AWS Lambda Function URLs
published: true
description: Learn how to create dedicated HTTP(S) endpoints for Lambda functions without an API Gateway
tags: aws, lambda, serverless
canonical_url: https://cloudash.dev/blog/guide-to-lambda-function-urls
---

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](https://aws.amazon.com/blogs/aws/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/) - 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:

```bash
https://vg7sczk62ycloct63yi3wjpoj40sgkuz.lambda-url.eu-central-1.on.aws/
```

or, in general:

```bash
https://<url-id>.lambda-url.<region>.on.aws/
```

Lambda function URL can point to either `$LATEST` or to an [user-defined alias](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html). 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:

```ts
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](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html) 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"
                }
            }
        }
    ]
}
```

[Source](https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html)

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:

```ts
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](https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html).

## 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               |

[Source - AWS Summit SF 2022 - Best practices for building interactive applications with AWS Lambda (CON302)](https://www.youtube.com/watch?v=B-Mz-HTSavM)

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](https://aws.amazon.com/blogs/aws/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/) 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](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html).