bref icon indicating copy to clipboard operation
bref copied to clipboard

Replace API Gateway with CloudFront + Lambda Function URLs everywhere in Bref?

Open mnapoli opened this issue 2 years ago β€’ 16 comments

Right now, Bref's docs/examples/defaults deploy:

graph LR;
API(API Gateway)-->Lambda(Lambda);

For websites, it deploys:

graph LR;
CloudFront-->API(API Gateway)
API-->Lambda(Lambda);

Lambda Function URLs are great to replace API Gateway. However they don't have custom domains. That means you need CloudFront (for the custom domain). That works for websites right now (we already have CloudFront there), but not APIs (which don't use CloudFront).

How about dropping API Gateway entirely (for the docs/examples, Bref would still work with it of course) and go full Lambda Function URLs + CloudFront.

We would have 3 different scenarios:

  • No custom domain: Lambda Function URL That would be super cheap for testing and deploying preview URLs.
  • Website: CloudFront -> Lambda Function URL Same as today, no changes except API Gateway is removed.
  • API: CloudFront -> Lambda Function URL
graph LR;
CloudFront-->Lambda(Lambda Function URL);

Pros:

  • Slightly simpler serverless.yml config
  • Websites would be cheaper to host (no API Gateway)
  • Possibly slightly faster first deployments (no API Gateway to setup/deploy)
  • Slightly less HTTP latency as Function URLs are slightly faster than API Gateway
  • Simpler infrastructure, always the same regardless of the use case
  • CloudFront takes care of redirecting HTTP -> HTTPS (API Gateway doesn't), that's a win!
  • Longer HTTP timeouts!

Cons:

  • Longer deployment time when you want a custom domain on an API (for websites we already deploy CloudFront, so it wouldn't be slower)
  • The Lambda Function URL would be publicly (on top of the CloudFront URL), making it private would require some more effort (custom header or using Lambda@Edge)
  • Cannot use API Gateway features: that would still be possible, but be advanced, which makes sense to me. We don't use API Gateway features in Bref docs.
  • Is CloudFront more expensive than API Gateway for APIs? I did rough calculations and it seems that it could be actually cheaper for 99% of use cases! CloudFront has a much bigger free tier (10 million HTTP requests, compared to 1 million for API Gateway). Beyond that, it seems to be about the same price, but even at this scale it can be optimized on a case by case basis.

Summary:

Running APIs and websites might be simpler, faster and cheaper!

Am I missing anything? Feedback is welcome πŸ™

mnapoli avatar Aug 27 '23 18:08 mnapoli

A couple of questions:

  1. Since websites with a custom domain would now effectively have 2 URLs (Lambda Function URL, CloudFront custom URL), would Bref provide a helper that would let me block direct access to the function URL, so that only the custom domain/URL is used?
  2. Would it make sense to provide "skip API Gateway" as a feature toggle, so that users could choose to keep the current behavior?

shadowhand avatar Aug 28 '23 12:08 shadowhand

@shadowhand regarding question 1, I listed it in the "Cons" (but edited early today, so you might have missed it):

The Lambda Function URL would be publicly (on top of the CloudFront URL), making it private would require some more effort (custom header or using Lambda@Edge)

To expand on the first option, here are more info: https://stackoverflow.com/a/72271684/245552

I'm not sure if that should be a native Bref feature πŸ€” Deploying lambda@edge would for sure not be, because it's complex and it sucks. But maybe the header thing…

Would it make sense to provide "skip API Gateway" as a feature toggle, so that users could choose to keep the current behavior?

Existing users wouldn't be impacted. Their serverless.yml wouldn't change. Only the Bref docs would change, but the main difference is about replacing events with url: true, so I don't think there would be too much confusion in the docs.

The server-side-website Lift construct would still work, it will (should? that might not be the case currently but I can work on that) detect whether there's an API Gateway or a Function URL and automatically use it as the source of the CloudFront distribution.

mnapoli avatar Aug 28 '23 13:08 mnapoli

I only recently learned about function URLs myself (because they also allow streaming responses - which is great for AI-powered applications!). However three questions came up:

  1. Does the current setup always link to $LATEST or does it handle switching to the new version internally? Sometimes things can go wrong and you have to go back a version
  2. Would rate-limiting be done via CloudFront in this case? Even if lambda can support millions of requests, I don't need to have more than 5k requests/sec for most smaller apps.
  3. Api Gateway also offers a firewall, does AWS WAF work the same when it's just CloudFront?

spaceemotion avatar Aug 28 '23 15:08 spaceemotion

Very good points!

1. Does the current setup always link to $LATEST or does it handle switching to the new version internally? Sometimes things can go wrong and you have to go back a version

I'm not sure it could do what you may want. Here are what the docs say:

You can apply function URLs to any function alias, or to the $LATEST unpublished function version. You can't add a function URL to any other function version.

You could use aliases, but I don't think the Serverless Framework does anything clever. But you may achieve that yourself?

Given most Bref users don't use Lambda versions at all, that's not something I intend to support for getting started templates/docs. Users can grow into these features by themselves if they want this, Bref is compatible with whatever Lambda can do.

2. Would rate-limiting be done via CloudFront in this case? Even if lambda can support millions of requests, I don't need to have more than 5k requests/sec for most smaller apps.

Good point, here are the Lambda docs:

Your function's maximum request rate per second (RPS) is equivalent to 10 times the configured reserved concurrency. For example, if you configure your function with a reserved concurrency of 100, then the maximum RPS is 1,000.

Whenever your function concurrency exceeds the reserved concurrency, your function URL returns an HTTP 429 status code. If your function receives a request that exceeds the 10x RPS maximum based on your configured reserved concurrency, you also receive an HTTP 429 error. For more information about reserved concurrency, see Configuring reserved concurrency.

It seems you can easily limit the RPS, so it seems to do the job, right? (at least as good as API Gateway?)

3. Api Gateway also offers a firewall, does AWS WAF work the same when it's just CloudFront?

WAF works with CloudFront (and it's even better because AWS Shield Advanced only supports CloudFront, not API Gateway).

mnapoli avatar Aug 28 '23 18:08 mnapoli

WAF works with CloudFront

Also on API gateway v1, I think. Though v1 does not have great performance or pricing.

GrahamCampbell avatar Aug 28 '23 22:08 GrahamCampbell

I'm interested in this because ApiGatewayV2 is not supported in eu-south-2 (Spain) region. If any help is needed please tell me

kevincerro avatar Oct 04 '23 13:10 kevincerro

@kevincerro the main thing we need to have is make https://github.com/getlift/lift/blob/master/docs/server-side-website.md use Function URL if API Gateway is not used (it requires code changes in Lift).

For the documentation I can take care of that πŸ‘ (but it's currently blocked by the Lift issue).

mnapoli avatar Oct 05 '23 15:10 mnapoli

@kevincerro the main thing we need to have is make https://github.com/getlift/lift/blob/master/docs/server-side-website.md use Function URL if API Gateway is not used (it requires code changes in Lift).

For the documentation I can take care of that πŸ‘ (but it's currently blocked by the Lift issue).

I'm going to try to take care of this

kevincerro avatar Oct 22 '23 18:10 kevincerro

Draft PR here, some improvements are needed regarding configuration logic https://github.com/getlift/lift/pull/368

kevincerro avatar Oct 22 '23 23:10 kevincerro

I'm interested in this because ApiGatewayV2 is not supported in eu-south-2 (Spain) region. If any help is needed please tell me

function urls is not supported either. https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html

honktang avatar Nov 13 '23 08:11 honktang

I'm interested in this because ApiGatewayV2 is not supported in eu-south-2 (Spain) region. If any help is needed please tell me

function urls is not supported either. https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html

Yes I know, I hope that AWS will add lambda url to eu-south-2 soon. In the meantime I'm using eu-west regions.

kevincerro avatar Nov 13 '23 17:11 kevincerro

I know there hasn't been progress here. I'm posting two updates in favor of using FURL over API Gateway v2:

  • FURL can now be authenticated to be called from CloudFront (without having to use Lambda@Edge), so that the FURL is not public -> solves the major blocker
  • API Gateway v2 has path encoding issues that FURL doesn't have (https://stackoverflow.com/q/69677023/245552)

mnapoli avatar May 01 '24 09:05 mnapoli