Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mnapoli opened this issue Aug 27, 2023 · 15 comments · May be fixed by getlift/lift#368
Open

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

mnapoli opened this issue Aug 27, 2023 · 15 comments · May be fixed by getlift/lift#368

Comments

@mnapoli
Copy link
Member

mnapoli commented Aug 27, 2023

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

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

For websites, it deploys:

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

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);
Loading

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 🙏

@shadowhand
Copy link
Contributor

shadowhand commented Aug 28, 2023

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?

@mnapoli
Copy link
Member Author

mnapoli commented Aug 28, 2023

@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.

@spaceemotion
Copy link

spaceemotion commented Aug 28, 2023

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?

@mnapoli
Copy link
Member Author

mnapoli commented Aug 28, 2023

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).

@GrahamCampbell
Copy link
Contributor

GrahamCampbell commented Aug 28, 2023

WAF works with CloudFront

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

@kevincerro
Copy link
Contributor

kevincerro commented Oct 4, 2023

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

@mnapoli
Copy link
Member Author

mnapoli commented Oct 5, 2023

@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).

@kevincerro
Copy link
Contributor

@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
Copy link
Contributor

kevincerro commented Oct 22, 2023

Draft PR here, some improvements are needed regarding configuration logic
getlift/lift#368

@kevincerro kevincerro linked a pull request Oct 23, 2023 that will close this issue
6 tasks
@honktang
Copy link

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

@kevincerro
Copy link
Contributor

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.

@mnapoli
Copy link
Member Author

mnapoli commented May 1, 2024

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)

@pra-cloud
Copy link

hey, @mnapoli can we deploy on AWS Lambda edge right now by using bref ??

@GrahamCampbell
Copy link
Contributor

No, lambda@edge does not support custom runtimes.

@mnapoli
Copy link
Member Author

mnapoli commented Dec 17, 2024

Taking the opportunity to update regarding this:

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

That's not true for most use cases actually. The client needs to send a header for requests with bodies, which means you can't run most websites/APIs that way. It sucks. Still need Lambda@Edge for a private FURL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants