Should You Use Amazon API Gateway in 2024? Consider Function URLs Instead!

Did you know that you can now invoke Lambda functions using an HTTP API via Function URLs?

Lakindu Hewawasam
Bits and Pieces

--

After the launch of AWS Lambda, there really wasn’t a way to invoke these Lambda functions through an HTTP API unless it was hooked onto an Amazon API Gateway.

So, your AWS Architecture would’ve looked something like this:

Figure: An API powered using AWS Lambda consumed using API Gateway

By using this API Gateway, you ultimately provided an entry point to your internal APIs (Lambda Functions) that helped generate the required responses for your apps to work.

But, since 2022, AWS introduced Function URLs for AWS Lambda Functions. This meant that your Lambda functions can be given a unique HTTP endpoint (allocated by AWS) that enables your Lambda Function to be invoked over the web, with no configuration required. So, by doing so, your architecture would’ve looked something like this:

Figure: An API being invoked using a Function URL

As you can see, you no longer have an API Gateway. Instead, your application directly invokes the Lambda Function via a valid CORS configuration.

So, this creates the question, what should you use in 2024? Should you still use Amazon API Gateway, or should you use Function URLs?

What is an Amazon API Gateway?

The Amazon API Gateway is a fully managed service that lets you create, publish, maintain, monitor and secure HTTP and Websocket APIs at any scale.

Simply put, an API Gateway acts as the “front door” to all your internal system resources such as your business logic, data or functionality.

For example, this is how a typical API Gateway would work:

Figure: The workings of Amazon API Gateway

If you provision an API Gateway, it will first generate a stage URL for you. This would look something like this:

https://{restapi_id}.execute-api.{region}.amazonaws.com/{stage_name}/

Your users can use this stage URL to access your API via resource-based routing. For example, you might have a resource:

Your resource is indicated by the route — /users. When a user invokes the /users route, it would access the GetUsersLambda resource and would fetch the list of users from the Users Table.

So, your API Gateway will act as the entry point to all of your system resources.

By doing so, you’re able to centrally manage the way your internal resources are being accessed.

But, this doesn’t end here. Using an API Gateway creates has more advantages.

  1. You can leverage authentication and authorization mechanisms into your app using IAM, API Key, Lambda and Cognito Authorizers.
  2. You can create API Keys for different consumers of your API for secure authentication.
  3. You can create a custom domain to your API. For example, you can choose to avoid using the default API Gateway URL and map something like — https://api.myapp.com.
  4. You can leverage API Gateway level caching to cache frequently served responses to reduce the load on your internal resources.
  5. You can leverage security measures like rate limiting and even prevent DOS attacks through AWS WAF integrations.

So, with all of this mind, it makes sense to go for an API Gateway doesn’t it? But, then why would AWS introduce Function URLs?

What is a Function URL?

A Function URL is a callable HTTP endpoint that binds to a Lambda Function that lets users invoke it.

You can create and configure a function URL through the Lambda console or the Lambda API. When you create a function URL, Lambda automatically generates a unique URL endpoint for you.

Once you create a function URL, its URL endpoint never changes. Function URL endpoints have the following format:

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

By doing so, you no longer have a “front-door” to your API, but rather treat the Function URL as the entry point to your service. This looks something like this:

This approach is more straightforward, and simple to use. Not only that, but using Function URLs have more benefits:

  1. You don’t have to pay for additional services. For example, with API Gateway, you have to bear the cost of the API Gateway and the Lambda function, where as with Function URLs, you only pay for Lambda usage.
  2. You’re not bounded to the 29 second maximum timeout of the API Gateway. Instead, you can keep a Lambda Function running for the maximum timeout duration of the Lambda (15 minutes).
  3. You’re given the option to use IAM Auth to secure your Lambda function.

But when would you use a Function URL?

API Gateway vs Function URL

I’ve created a summary of the key differences between the two:

Now, based on these difference, it’s quite evident that a Function URL is a more simple approach to exposing an HTTP endpoint to your API.

But, what this means is that, you generally shouldn’t use a Function URL if you were building an enterprise level API that required features such as caching, rate limiting and complex authorization via Cogntio.

However, if you are only focused on the following:

  1. Building a server-side rendering website
  2. A service that requires long polling of greater than 29 seconds.
  3. You want to create an invocation for a webhook.
  4. You want to create a single simple service, such as a form handler.

These four candidates are perfect for a function URL. But, if you’re building a solution that has complex authorization flows, a new for tighter security, or if you’re response times are within 29 seconds, go ahead with an API Gateway to get more control!

Creating a Simple App With a Function URL

Now that we have an understand of the function URL, let’s take a look at how we can implement a simple form handler using a Function URL.

To do so, let’s create a simple React form along with a Lambda function to handles submission events to the form.

Now, one thing to understand here is that when you’re building a complete end-to-end solution, you’ll be sharing entities. Therefore, it’s important that you leverage a tool that makes entity sharing between your frontend and backend components simpler. So, I’ll be using Bit to build this solution.

If you’re not familiar with Bit, Bit is a next-generation build system for composable software. It lets you design, develop, build, test and version components in an isolated space. It’s able to keep track of component usages and propagate changes up a component tree using its CI Server — Ripple CI.

For example, in the figure shown above, Bit is able to keep track of all components that are being used in the tree and update the entire tree if one of the components undergo a change.

So, in our case, let’s create the following:

  1. A Lambda Function
  2. A Form

To do so, we’re going to be focusing on the Bits and Pieces Form Submission for Writers. This form itself is developed and maintained using Bit:

Figure: Dependency tree of Bits and Pieces Submission Form

As you can see, it has:

  1. A React Form
  2. A Shared Entity
  3. A Lambda Function Handler
  4. A React App that consumes the form.

So, you don’t even need to create your solution from scratch. First, let’s create a Bit workspace using the command:

bit init

Next, grab a copy of this code and make it your own using the command:

bit fork bits-and-pieces.article-submission/entities/article-submission-scheme && bit fork bits-and-pieces.article-submission/forms/article-submission-form && bit fork bits-and-pieces.article-submission/handlers/form-submission-handler && bit fork bits-and-pieces.article-submission/article-submission-app

If you’ve done this successfully, you should see the output:

Figure: Forking the Components Sucessfully

Next, run the command:

bit install --add-missing-deps

This will install any missing dependencies for your Bit workspace and will show the output:

Figure: Installing the Missing Dependencies

Next, launch your Bit server using the command:

bit start

You’ll see the output:

Figure: Launching the Bit Server

Next, you can start updating the code to your requirements by updating each component:

Figure: Viewing the Code

Next, after you’ve made the changes you can export it to a Bit Scope of your own.

A Bit Scope is where your components live.

Afterward, you can configure Ripple CI environment variables to assign an AWS Access Key and a Secret Access Key to ensure your Lambda function gets deployed on AWS. Additionally, you will also have to add an environment variable for a Netlify Token to publish your app to Netlify.

Wrapping Up

Function URLs are a good choice for simple operations, while API Gateways must be used for managing complex APIs that require comprehensive security and more.

This article presented an in-depth comparison between the two while providing tips on selecting the correct approach.

To sum things up, use a Function URL if you’re:

  1. Building a server-side rendering website
  2. A service that requires long polling of greater than 29 seconds.
  3. Creating an invocation for a webhook.
  4. Creating a single simple service.

And, use an API Gateway is you’re:

  1. Leveraging authentication and authorization mechanisms into your app using IAM, API Key, Lambda and Cognito Authorizers.
  2. Creating API Keys for different consumers of your API for secure authentication.
  3. Creating a custom domain to your API.
  4. Leveraging caching.
  5. Leveraging security measures like rate limiting and even prevent DOS attacks through AWS WAF integrations.

I hope you found this article helpful.

Thank you for reading.

--

--