Directly proxying Lambda via Cloudfront without API Gateway

That’s definitely the configuration that allows you to directly call lambda from cloudfront. I think the key bit was using a custom SSL certificate. It is just a free AWS certificate with my domain name in it.

I am going to add this in here that API Gateway actually does a helluva lot for you to justify its price. For one, its already solved the problem of calling Lambdas via Cloudfront for you. Other than that it allows for ease of integration with authorizers to protect your API’s behind credentials, throttling of requests to prevent your architecture from getting flooded, API key control to 3rd parties to allow you to control their usage limits, caching of queries, generation of swagger definitions and with that SDK’s for your clients and a lot more.

As a counter to APIGateway – it adds cost and slows every call down. If you are using Sig4 as your authorizer you don’t need it. If you are not using Sig4 you have to have it. Similar throttling can be achieved by setting lambda currency limits. This throttling is not DOS protection - AWS Shield addresses that.

One thing you missed, lambda can only return JSON. API Gateway can use transforms to change that JSON into other things. For example if a lambda returns HTML as a JSON result, API Gateway can strip the JSON and return an HTML page. If you are selling gateway access to a third party, APIGateway is definitely the way to go.

API caching is a mixed bag. For our situation the calls are rarely repeated (they are unique to the user) so there isn’t much to cache. Plus our lambda response is very fast so I am not sure that a cache response from API gateway would matter. We don’t generate content dynamically for non-logged in users. That content is generated once (when it changes) into S3 where it then gets picked up by cloudfront.

I also believe a majority of mobile apps call lambda directly. If you use the AWS SDK in the mobile app, then you are calling lambda directly. I stumbled into this initially because we wanted to make a web app that mimicked our phone app. The phone app used the AWS SDK so it called lambda directly. When I went to work on the web app I simply make it work like the phone app.

2 Likes

Have you investigated requests/responses with binary body in this context? It’s apparently possible through API Gateway, but perhaps isn’t through the invoke SDK?

As far as I know the only thing you can return from a lambda is JSON. In my case I catch that JSON in the browser and then turn it back into whatever form I need it in.

I was looking to use flatbuffers both in the browser, passed whole into WebAssembly, and in the lambda. Encoding that as something that fits into a JSON defeats both the bandwidth and the performance advantages significantly.

@jonsmirl I also quickly came to the realization that API gateway wasn’t doing much for my use case, except slowing down the eventual invocation of my Lambda. Therefore, I’m just directly invoking the lambda from a website. The only issue I’d like to improve is global performance. My lambda currently exists in us-east-1 and it takes a bit too long to ‘ping’ my lambda from Europe & especially Asia. I’d like to deploy a Lambda in a couple more regions and then rely on Route 53 geolocation routing to call the ‘right one’. I haven’t been able to find a way to do this. Have you encountered any similar ideas or solutions? Note, I still don’t want to use API GW and Lambda@Edge even though it would help “a little” with some of this because my Lambda is implemented in Java and Java is not supported by Lambda@Edge.

Thanks,
Cliff

You can make multiple origins with cloudfront pointing to the different lamba regions. Make one for each region you are interested in.

Then can your front end query route53 and then figure out which origin to use? Or it could even ping all of them and see which one responds the quickest.

I am looking for this solution as well. Currently, we are using Angular for our SPA that hosted on AWS using CloudFront with S3 origin. Angular app will call our API via API Gateway, then API Gateway will call our Lambda functions, API Gateway works as a middleware between our client app and Lambda function.

When I starting to review and evaluate the Lambda@Edge, I also have the same idea to remove API Gateway, it does nothing except forward API request from client side to Lambda function, so it adds some latencies. Our APP is simple, we don’t want to expose API to the world, so we won’t need to use API gateway at all.

Is this a good solution for a small application that the limits of Lambda@Edge won’t impact to the overall product performance?

One limiting factor is that Lambda@Edge does not allow method to be rewritten.

So, whilst you may get the above working for POST requests from the client, if you’re wanting to rewrite to a Lambda origin on GET requests from the client, you’re out of luck.

It seems your only options for deploying Lambdas that can be called with GET are either deploying API Gateway (and pay for the extra cost & latency there) or deploying a 2nd Lambda@Edge distribution (and pay for the 3x execution cost… @Edge costs roughly 3x more than regular Lambda).

It’s also worth noting that since this discussion started, AWS has introduced HTTP API: their stripped-down version of API Gateway, just for HTTP-ifying Lambdas.

It’s almost 1/4 the cost of the original flavour of API Gateway (which they’re now calling REST API) and doesn’t come with the extra baggage that put many of us off due to our simpler use-cases. For example, HTTP API does not come with: API keys, caching, usage plans, transformations and WAF.

That said, it does still add a cost: your $0.20 per 1M requests for your Lambdas gets an extra $1.00 per 1M requests from HTTP API’s pricing… so your total cost is $1.20 per 1M requests. However, if your requests take in the order of 1 second to complete (or longer) then this cost becomes somewhat negligible next to your CPU seconds spent with Lambda.

All food for thought. I do wish AWS would allow Lambdas to be easily set as origins dynamically in CloudFront, and also allow method rewriting, so your clients can use GETs while calling Lambdas on the backend. NVM, at least there’s a solution that no-longer costs the earth :grinning: