Yes, designed for usecases like those handled by Cloudflare Workers, which boil down to updating data cached in edge servers without requiring global redeployments or pinging a central server. We're talking about stuff like adding timestamps to images or adding headers to HTTP responses or pre-rendering some HTML or emit CDN-aware metrics.
> Now you can run a JS function for every single request that hits your CloudFront Distribution
Not exactly. Lambda@Edge are event handlers from CDN events. You use them when they suit your needs.
> so that you can run logic in there to strip the prefix before it gets passed to your origin.
Your strawman example doesn't even feature among the dozen examples provided by AWS regarding how to use Lambda@Edge.
Everyone is free to come up with silly ideas and absurd examples, but if you design systems around braindead ideas then that says a lot about you and nothing about the tools you chose to abuse
> You read that right! Execute code every time a request hits your proxy!
Yes, that's what web servers do. What exactly is your point?
> But wait, doesn't executing code for every single request sound insane
It doesn't. That's what a web server does. Moreso, Lambda@Edge (and Cloudflare Workers too) only do it if you explicitly decide to make them do it, to match precisely what you tell them to do.
What point are you trying to make, exactly?
> AND doesn't it also add latency which this was trying to remove?
It does. It adds tens of milliseconds when the alternatives can add hundreds of milliseconds. You're also expected to do basic engineering work and do basic performance work when seeking performance improvements, such as measuring things instead of mindlessly jumping on bandwagons without caring for the outcome.
> Isn't cloud just lovely?
I feel your comment manifests too much cinicism to cover too much ignorance on a topic you are not familiar nor understand the basic premise.
> Yes, designed for usecases like those handled by Cloudflare Workers, which boil down to updating data cached in edge servers without requiring global redeployments or pinging a central server. We're talking about stuff like adding timestamps to images or adding headers to HTTP responses or pre-rendering some HTML or emit CDN-aware metrics.
> Not exactly. Lambda@Edge are event handlers from CDN events. You use them when they suit your needs
> Your strawman example doesn't even feature among the dozen examples provided by AWS regarding how to use Lambda@Edge.
For all of these counterpoints, see [0].
> Everyone is free to come up with silly ideas and absurd examples, but if you design systems around braindead ideas then that says a lot about you and nothing about the tools you chose to abuse
I take it you are directing this particular comment at AWS considering they are recommending this solution? [0]
> Yes, that's what web servers do. What exactly is your point?
Don't be daft. You know what I mean. Obviously web servers execute code. In this case the web server (CloudFront Distribution) is passing the request to yet another "thing" which happens to be a JS function that is invoked specifically to handle something web servers like nginx were built to do extremely efficiently on their own. CloudFront could easily support this without additional dependencies that add complexity to your system design and introduce additional failure modes. In this case, I am making your point for you: using Lambda@Edge for this IS ridiculous, but that's the AWS way.
> It doesn't. That's what a web server does. Moreso, Lambda@Edge (and Cloudflare Workers too) only do it if you explicitly decide to make them do it, to match precisely what you tell them to do.
> It does. It adds tens of milliseconds when the alternatives can add hundreds of milliseconds. You're also expected to do basic engineering work and do basic performance work when seeking performance improvements, such as measuring things instead of mindlessly jumping on bandwagons without caring for the outcome.
Sorry for not writing a detailed blog post to describe all of my findings. FYI, the latency added with Lambda@Edge caused my request time to double and added much more variance.
I'm surprised a lot of your counterpoints are just blaming me for doing the wrong thing, when this is actually what is recommended by AWS. Invoking a custom function to process the request. See [0]. Of course the right solution is to use nginx (but then you lose out on AWS scaling) or completely redesign your system to fit another solution like API Gateway.
From AWS's blog:
> In this scenario we can use Lambda@Edge to change the path pattern before forwarding a request to the origin and thus removing the context. For details on see this detailed re:Invent session. [0]
[0] https://aws.amazon.com/blogs/architecture/serving-content-us...
I don't, I can just teach my backend to process /api. The backend is running code under my control anyway. This seems like one of the least difficult "problems" to solve in any non-trivial codebase.
> doesn't executing code for every single request sound insane
How would you strip some url path without executing code for every single request? It could be code you did not write, but some code is always needed to do something. If latency of lamdba@edge is an issue, you can try CloudFront functions, which should be better for small tasks like this (though I don't have any experience with them as we switched to a similar competitor)
Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1]
[0] https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope...
[1] https://aws.amazon.com/blogs/architecture/serving-content-us...
For stripping /api/ from the path, I don't know what would be the benefit of doing it at the origin request, rather than at the viewer request?
Cloudfront functions are pretty new, so some older docs might still reference lamdba@edge only.
Therefore stripping must be performed on the origin request, which is not supported by CloudFront Functions.
See https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope...
I have used lamdba@edge and our primary use case was to rewrite url (to add languages information for example) so I'm sure it works in viewer request events.
I could be wrong as I did this lambda@edge a while ago, but the main difference between the two request event is that viewer request is done in all cases, while origin request is done only in case of cache miss.
[EDIT] you are right, updating the origin is indeed something that cannot be done on the viewer side. My bad, I should have checked earlier.
What difference are you alluding to?
Of course it doesn't matter, basically logging takes more resources than whatever routing is needed. (Especially because even if it requires running a Cloudflare worker it's just a NodeJS V8 isolate, very lightweight. As far as I know. But I have no idea of its costs.)
But AWS Lambdas are pretty pricey compared to a free nginx rewrite.
Kind of why CloudFront Functions we're invented for this use case, AWS Lambda@Edge is the more general purpose edge computing facility.
I'm not sure you're making a informed observation. "Spinning up a container image" is just fancy jargon/handwaving to refer to launching a process, which is something nginx already does under the hood in a myriad usecases without warranting complains from users.
> and queried for each request, don't you think?
I'm not sure if either you framed your sentence poorly or you don't have a clear idea about what you're talking about. In AWS lambda, you don't "spin up containers" at each request. You launch your lambda once it's deployed or when it scales up, and it stays up as long as you see traffic.
I’m pretty sure Lambda@Edge is not a container image like regular Lambda (why it only supports JS and not the broader set of Lambda runtimes) and is relatively local to the edge environments serving CloudFront anyway (why it is support in CloudFront the way regular Lambda isn't, and what the @Edge part refers to.)
but surely executing code at the source of your web app is more efficient than having the client and server attempt to perform it? faster than 40-90ms per request at least
No, CloudFront Functions is the Another Cloud Thing AWS invented more specifically for this use case. Lambda@Edge is the older and more general purpose edge computing facility.
> You read that right! Execute code every time a request hits your proxy!
Any rewrite rule in any platform, and heck, any other functionality provided by the distribution, is executing code every time it gets a request (whether or not you are writing code for the purpose.)
Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1]
[0] https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope...
[1] https://aws.amazon.com/blogs/architecture/serving-content-us...
Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1]
[0] https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope...
[1] https://aws.amazon.com/blogs/architecture/serving-content-us...
See: https://github.com/aws-samples/amazon-cloudfront-functions/b...
The viewer request is the one you make from the client, with /api. The origin request is the one CloudFront sends to your backend, which, without using Lambda@Edge via the origin request, will get sent as-is with the /api prefix. You have to strip it from the origin request.
If you strip /api from the viewer request, your `domain.com/api/users` request becomes a redirect to `domain.com/users` which results in a call to your frontend instead of your backend.
The example you referenced solves a completely different issue, not the one we are talking about.
Request manipulation is not the duty of a cache - even though other CDN providers mix request manipulation functionality with caching. In my opinion, they don’t need to be in the same product.
If you still need request manipulation, because you don’t control the origin or you don’t want to introduce another service between CloudFront and the origin, you would use CloudFront Functions, which is cheaper than Lambda@Edge and easy to set up.
Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1]
[0] https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope...
[1] https://aws.amazon.com/blogs/architecture/serving-content-us...
I agree that AWS products are all over the place.
It's the customers. They run into issues using something against all advice in the docs and then request features and services or AWS sees all the clamor around a perceived issue and they create a "solution."
Developers are really averse to reading and understanding documentation. It's why they all jumped on the cloud. But it turns out it isn't all just magical infinite performance.
Is your lambda awake?
app.UsePathBase("/api");
And we have 0 issues.
Only Lambda@Edge can help the scenario which I provided, which is also AWS's recommended solution. [1]
[0] https://docs.aws.amazon.com/AmazonCloudFront/latest/Develope...
[1] https://aws.amazon.com/blogs/architecture/serving-content-us...
For the stated purpose, either function is fine:
With Lambda@Edge you'd use origin request if you were caching these paths, because your function would be called less often so your costs would be lower.
With CF Functions you can only do the pre-cache-lookup modification, so it will be called for every request, but the cost is much lower than Lambda@Edge so it may not matter, and maybe you were not caching these paths anyway in which case it's virtually identical.
Basically, using the Viewer Request trigger and modifying the URI there causes CloudFront to force a 301 to the user to the new URI, because it's for the viewer. Therefore, in the example of /api/users, if you modify the viewer to remove /api, CloudFront literally removes /api from your request URI, meaning the client accesses /api/users but the server instead sends you to /users (read: server returns 301 location: /users when you hit /api/users) because of your viewer rewrite. You end up hitting your frontend instead of your backend because in order for it to hit your backend, the viewer request has to have /api in it. Therefore you cannot strip it in the viewer request. You must do it in the origin request, which is not supported by CloudFront functions.
But don't worry! AWS thought of this! They invented Another Cloud Thing, namely Lambda@Edge, to solve this. Now you can run a JS function for every single request that hits your CloudFront Distribution so that you can run logic in there to strip the prefix before it gets passed to your origin. You read that right! Execute code every time a request hits your proxy! But wait, doesn't executing code for every single request sound insane AND doesn't it also add latency which this was trying to remove? Yes! Isn't cloud just lovely?