yarbsemaj / sveltekit-adapter-lambda

An adapter to build a SvelteKit app into a lambda ready for deployment with lambda proxy via the Serverless Framework or CDK.
https://www.npmjs.com/package/@yarbsemaj/adapter-lambda
MIT License
77 stars 16 forks source link

Moving away from Lambda Edge or towards it. #10

Closed ivands closed 2 years ago

ivands commented 2 years ago

I've been thinking more about improving the costs of the system, and I think it's probably best to remove the lambda edge router. The edge router is used to tell CloudFront to get the static files from s3. The problem however is that lambda edge is expensive and will now be triggered for every missed cache hit. And because SSR pages can't be cached we trigger the lambda edge function for no reason. Plus we don't gain any speed benefit by using the edge because SSR is still happening on a normal lambda function.

We could just move the lambda edge router functionality to the normal lambda that is doing SSR right now. The lambda just needs to get the static assets from s3 when necessary and return it with proper caching headers for CloudFront. If the request isn't for a static asset we just do the normal SSR stuff.

This approach should reduce costs even more. What do you think?

ivands commented 2 years ago

More thinking happened. If we could just do SSR on the edge we wouldn't need API Gateway anymore. Plus we would get the additional speed benefit that the edge provides.

Both options seem like an upgrade to me. (Going fully on the edge is a lot cheaper tho)

MicMonen commented 2 years ago

I am trying to get this to work on the edge with this package.

I have a CloudFront instance that has 1 origin (S3 bucket with all the static files). I've attached an edge lambda (origin-response) that checks if the request is found on the origin or else execute the SSR code and return that as a response. The problem is that I cannot get the SSR code (serverless.js) to work.

I hope you understand the logic behind this and maybe can help me try to get this working.

(An upgrade to this solution is to get SSR working on the origin-request edge function)

yarbsemaj commented 2 years ago

Hi @MicMonen Do you have any logs of any errors your seeing that i could take a look at? Could you try hitting the SSR API gateway directly, and seeing if you get back the expected response?

yarbsemaj commented 2 years ago

Hi @ivands Thank You very much for your suggestions.

I disagree with your assertion that SSR pages cannot be cached, this is quite common practice and in fact it's probably more advantages to cache SSR content vs static content as there is not only a transfer cost associated with generated data, but also a time and monetary cost associated with rendering the page. I cache SSR pages for my personal blog using this adapter. I have a long cache on all the blog pages, then when a blog post is added or updated I programmatically invalidate the cache on specific paths.

I Considered all these options when developing the initial solutions before coming up with my final design, below are the Pros and Cons of each approach so i hope you get a understanding of the tradeoffs I had to consider. I have highlighted in bold the deal breaker for me with the 2 rejected options.

SSR at the edge

Pros

ivands commented 2 years ago

Hi @yarbsemaj,

Let me just be clear about the caching point. When I say "cache" I'm talking about the CloudFront CDN cache. This package can't set default caching headers for SSR pages because not every SSR page can be cached. However static content from s3 can always be cached. (And because s3 content can be cached some of your points are incorrect).

SSR at the edge

Serve everything from a Lambda

The Hybrid approach

I hope you see why using this hybrid approach doesn't add any real benefit other than unlimited file size.

yarbsemaj commented 2 years ago

Hi @ivands Thank You for you comment, I thought I would do the maths on SSR at the edge just to be sure (TBH id not done it before) I just assumed it would be more expensive. I can confirm it is quite a bit more expensive (nearly 2x or more depending on how long it takes to process your page). Below are my calculations.

image

A few notes.

Don't get me wrong, those are still gains but the goal with the project is to make something that "just works" and I can see someone building something and including a video or large image in there public folder and then wondering why its not working when they go to deploy, I know you shouldn't do this, but people will.

yarbsemaj commented 2 years ago

Im very tawn on this and once sveltekit leaves alpha I may revisit this at a later date.

ivands commented 2 years ago

I'm not sure if I agree that the current hybrid version is cheaper. But I should run some tests myself.

On a different note: We have some good news 🥳: Lambda Function Urls are here. https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html

And it seems you can return any type of HTTP response. So this should eliminate the need for ApiGateway and reduce the cost of your hybrid version even more. 🎉

yarbsemaj commented 2 years ago

Hi @ivands Thank You so much for the update! I have just published a new version v0.8.0 that adds support for this. If you look at the commit history you will see the small update you need to make to your serverless.yml file. (as well updating the the latest version of the serverless framework)