DEV Community

Cover image for Introducing Lambda Function URLs

Introducing Lambda Function URLs

AWS has just launched a new, not entirely unfamiliar feature - there is now a new way to invoke a Lambda function via HTTP API call.

Lambda Function URLs are built into Lambda itself, so there's no need to configure an external API Gateway (V1) or HTTP Api (V2).

You can create one right now through the AWS console, either by creating a new function or editing an existing function:
Function URL

This short post will help you understand what Lambda Function URLs are, when to choose them, and when to reach for a more traditional API integration.

At a glance

Lambda Function URLs allow your function to be called via a HTTP request. This capability isn't new, previously you'd need to pair Lambda with API Gateway (v1 or v2) to invoke a function via HTTP request. API Gateway had a free tier, but after that you'd be charged $1.00/million requests (not including the time your Lambda function required to execute).

The key distinction between API Gateway and Lambda Function URLs is that Function URLs are a free* way to invoke your Lambda function via HTTP request *(you only pay for the very small additional running time incurred by serializing the request and response).

That's right, Lambda Function URLs are free

This is clearly the biggest selling point for Function URLs because it's not uncommon for API Gateway to be the biggest part of a Serverless bill!

There are also more significant advantages:

  • Function timeout is 15 minutes, instead of API Gateway's 29 seconds
  • Ease of setup and use
  • Performance seems to be really good for an API-based Lambda integration. With a vanilla Node.JS App, cold starts take about 900ms until the function is invoked, and warm starts are a blistering 8.35ms 🤯 Cold Start and Warm Start

But there are some drawbacks over a API Gateway/HTTP API:

  • No specified routes or payload formatting options
  • No custom domain names. Your URL is randomly assigned an ID: https://<url-id>.lambda-url.<region>.on.aws
  • IAM authorization or public endpoints only, no authorizers are supported.
  • Only synchronous invocation is supported

Routing

Function URLs are similar to the proxy+ integration you may be familiar with in API Gateway.
This means that any HTTP method to any endpoint will route to your function, eg:
POST https://<url-id>.lambda-url.<region>.on.aws/foo/123/bar
and
GET https://<url-id>.lambda-url.<region>.on.aws/biz/456/
will both invoke your function.

If you want to serve multiple resources from the same Function URL, you'll need to parse the route from the requestOptions in your Lambda Function. This effectively places you into a Mono-Lambda API pattern.

Authorization Options

Function URL Authorization
Your authorization choices are limited to Public, or IAM authorized. This lets you write IAM policies to restrict which users or services can invoke your Lambda Function via the Function URL. It's worth noting that you can still use IAM to limit who can invoke the function explicitly via the aws sdk or CLI, which opens up some interesting configuration choices.

Payload Specification

As there is no method for specifying Lambda integration method, like with API Gateway, Lambda Function URLs infer response format and use the API Gateway payload v2 request format.

  • If your function returns a string, API Gateway will return a HTTP 200 status code and your message.
  • If your function returns valid JSON, it will be sent (along with a HTTP 200 status code).

Most users will want more control over the full HTTP response, and thus specific keys like headers, statusCode, and isBase64Encoded are properly assigned to the API response. cookies can also be set, and are represented as a string array.

Function output:

{
  "statusCode": 201,
  "headers": {
    "specified-header": "specified-header-value"
  },
  "body": "\"result\":\"success\"",
  "cookies": ["User_Id=abcd1234; Expires 19 Nov 2021 20:22 GMT"]
}
Enter fullscreen mode Exit fullscreen mode

Client response:

HTTP 201
content-type: application/json
specified-header: specified-header-value
set-cookie: User_Id=abcd1234; Expires=19 Nov 2021 20:22 GMT
{
  "result": "success"
}
Enter fullscreen mode Exit fullscreen mode

The full documentation is available here, and goes into several more examples.

Key takeaways

Having played with Lambda Function URLs, I think they're useful in a couple of important cases - Mono-Lambda APIs, Service to Service communication, and lightweight webhooks. I think with a few iterations, Function URLs could get much better - and possibly be the default integration mechanism for HTTP-based Lambda invocation.

The Mono-Lambda API

Given the caveat that your authentication and authorization is already handled via IAM, or you can resolve it in your function against a provider like Auth0 - Lambda Function URLs are a cheap and easy way spin up a Mono-Lambda API. I've written extensively about why you might consider this pattern, so dig in to this blog post if you're curious to learn more.

The Webhook use case

Sometimes I just need a darn lambda function to talk to Slack, or to receive a webhook from Github. Gluing workflows together has been one of the key attractions of Serverless technology, and Function URLs fit a great niche as they are easy to set up when I don't care to have an api.company.com domain name.

Service-to-Service communication

Serverless APIs often use Cognito or Auth0 to authenticate requests from users, but in a service oriented architecture, one system often needs to authenticate with another system as a service (not acting as a user).

Function URLs protected with IAM roles fill a gap here, as previously you'd either need to pass user authentication context (which is not desirable, especially if the downstream service is being invoked via some persistent mechanism like DynamoDB Streams), or call the Lambda function directly with the AWS SDK (which is either a slight hassle or massive headache).

Wrapping up

Long term I see Function URLs fitting a pattern of service discover via Outputs, where public APIs are served with API Gateway, and internal API endpoints are surfaced with Function URLs and shared via CloudFormation Outputs (which I suggest you to use for sharing configuration between services).

Good luck out there. Feel free to reach out on twitter with specific questions, or to share something you're building!

Discussion (8)

Collapse
amcquade profile image
Aaron McQuade

really awesome, excited to try this out

Collapse
astuyve profile image
AJ Stuyvenberg Author

Thanks Aaron! Yes, it's a really compelling new feature for a bunch of use cases

Collapse
zirkelc profile image
Chris

That’s a great feature for testing Lambdas during development or for Proof of Concepts.

Collapse
astuyve profile image
AJ Stuyvenberg Author

Or so many other things!

Collapse
mmuller88 profile image
Martin Muller

Nice one thanks :)

Collapse
amitkayal profile image
Amit Kayal

nice one

Collapse
darrinndeal profile image
Darrin Deal

This is really exciting. I wonder if there will be the ability to add a custom domain to a set of lambdas.

Collapse
astuyve profile image
AJ Stuyvenberg Author

Seems like you can do that using CloudFront