Best practices for optimizing Lambda functions(cloudash.dev)
cloudash.dev
Best practices for optimizing Lambda functions
https://cloudash.dev/blog/best-practices-for-optimizing-lambda-functions
26 comments
Initialization code is mentioned...
"In addition to that, consider whether you can move initialization code outside of the handler function."
There's an example too, but this could use more emphasis. I see quite of a lot of code in the main body of lambdas that doesn't need to be run over and over, things that could be safely cached in a hashmap, etc.
"In addition to that, consider whether you can move initialization code outside of the handler function."
There's an example too, but this could use more emphasis. I see quite of a lot of code in the main body of lambdas that doesn't need to be run over and over, things that could be safely cached in a hashmap, etc.
I think a lot of this comes from people forgetting what would be considered normal and good practice everywhere else but something about serverless functions causes people to treat them as a quick and dirty hack solution. Then the inevitable refactor when that becomes a problem.
Absolutely. Java Lambdas are often particularly bad in this respect; all the nice abstractions and class hierarchies seem to go out the window as soon as one “implements RequestHandler”. Everything is a singleton all of a sudden, environment variables being read statically, etc.. The worst Java codebases I’ve ever seen have been Lambdas :(
There was a worrying trend in the .NET space of this for Azure Functions but I think there was enough complaints - it's now possible to configure DI yourself and use the .NET config stuff for getting env variables.
> There's an example too, but this could use more emphasis.
To be fair, handling lambda cold start is AWS lambda 101, and initialization is the starting point. I'd say that the only people not aware of this is those who are just taking their first steps.
This requirement is even notorious in JDK lambdas, and leads to the need to use dependency injection frameworks to handle initialization and consequently favour compile-time dependency injection frameworks such as Dagger over runtime ones like Guice.
> things that could be safely cached in a hashmap, etc.
I'd add that caching data in /tmp to get it through lazy evaluation is also a quite basic technique. The contents of /tmp are preserved between some calls and checking if the data is still there is an effective technique to shave off some milliseconds.
To be fair, handling lambda cold start is AWS lambda 101, and initialization is the starting point. I'd say that the only people not aware of this is those who are just taking their first steps.
This requirement is even notorious in JDK lambdas, and leads to the need to use dependency injection frameworks to handle initialization and consequently favour compile-time dependency injection frameworks such as Dagger over runtime ones like Guice.
> things that could be safely cached in a hashmap, etc.
I'd add that caching data in /tmp to get it through lazy evaluation is also a quite basic technique. The contents of /tmp are preserved between some calls and checking if the data is still there is an effective technique to shave off some milliseconds.
I clicked this expecting an article about compilers.
I clicked this expecting an article about how to avoid performance pitfalls when writing code with many closures.
I got through the first few comments thinking that too! There are real similarities I hadn't considered up to this point
Well written and well cited. Is there nuance? Definitely. But I think the author does a great job explaining the details as they relate to Lambda.
> AWS Lambda is the backbone of every serverless architecture.
What a weirdly bold and provably untrue claim.
What a weirdly bold and provably untrue claim.
Didn't you know? AWS is the only cloud provider.
AWS is, additionally, the only way of doing functions as a service.
/s
AWS is, additionally, the only way of doing functions as a service.
/s
And because all that is true and soon there will be no other functions, neither ways to implement them nor run them, they also did this gross hijack of the lambda term..
(Yah I'm mad that the title wasn't at least "AWS Lambda functions" - isn't "serverless" a funny enough name on its own for that domain?)
(Yah I'm mad that the title wasn't at least "AWS Lambda functions" - isn't "serverless" a funny enough name on its own for that domain?)
> What a weirdly bold and provably untrue claim.
Not really. Given the context is clearly AWS, it's Well-Architected Framework is centered on AWS Lambdas.
https://aws.amazon.com/architecture/well-architected/
Not really. Given the context is clearly AWS, it's Well-Architected Framework is centered on AWS Lambdas.
https://aws.amazon.com/architecture/well-architected/
Regarding bullet 4. Provisioned Concurrency:
If you use AWS SDK v3 and use node.js runtime 14.x, you can use top level await. Using top level await lets you more easily do async initializations outside your handler code, before invocation. This has a major benefit of reducing cold start latency when using provisioned concurrency.
See https://aws.amazon.com/blogs/compute/using-node-js-es-module...
If you use AWS SDK v3 and use node.js runtime 14.x, you can use top level await. Using top level await lets you more easily do async initializations outside your handler code, before invocation. This has a major benefit of reducing cold start latency when using provisioned concurrency.
See https://aws.amazon.com/blogs/compute/using-node-js-es-module...
That blog post author is mistaken. You can fire off async stuff outside of your handler just fine without AWS SDK v3 or top level await. Just run an async IIFE and assign it to a variable outside your handler. You can await that promise when you need it in your handler, but it kicked off running before your handler was invoked.
> It's not clear at which point Lambda function receives access to more than 2 vCPU cores
This is one of the more annoying things about the service. Why can't AWS publish this information? I might get 4 vCPUs at 5308MB today, but there's no guarantee they won't raise that threshold to 6144MB tomorrow and cause my run times to increase. There should be a better way to figure out what my execution environment looks like than trial and error.
This is one of the more annoying things about the service. Why can't AWS publish this information? I might get 4 vCPUs at 5308MB today, but there's no guarantee they won't raise that threshold to 6144MB tomorrow and cause my run times to increase. There should be a better way to figure out what my execution environment looks like than trial and error.
> There should be a better way to figure out what my execution environment looks like than trial and error.
To be fair, once you start to be bothered with how many threads you get, I'd argue you are already way outside of AWS Lambda's domain and well inside plain old ECW/ECS territory.
Keep in mind that AWS Lambdas are appropriate for a) glue code to plug together AWS events b) offload seldomly-ran background tasks, c) rarely executed tasks, such as a terribly simple REST API that is simpler to develop and maintain as a API Gateway+Lambda app instead of, say, express/spring/flask/whatever.
Once your requirements don't unquestionably fit any of these scenarios, you have to take a very hard look at what you're doing to explain why aren't you just rolling your own web service and instead you're opting to both pay a premium and increase your maintenance needs.
To be fair, once you start to be bothered with how many threads you get, I'd argue you are already way outside of AWS Lambda's domain and well inside plain old ECW/ECS territory.
Keep in mind that AWS Lambdas are appropriate for a) glue code to plug together AWS events b) offload seldomly-ran background tasks, c) rarely executed tasks, such as a terribly simple REST API that is simpler to develop and maintain as a API Gateway+Lambda app instead of, say, express/spring/flask/whatever.
Once your requirements don't unquestionably fit any of these scenarios, you have to take a very hard look at what you're doing to explain why aren't you just rolling your own web service and instead you're opting to both pay a premium and increase your maintenance needs.
Well stated. Lambda is a specialized tool. It isn't some generic. Lambda doing image processing is damn impressive [s3 bucket hooks, almost no code, ...]. Lambda doing sql inserts is a tragic disaster [boot latency, hanging queries, ...].
Well written. Nothing to disagree with in there on the face of it. Nuance dictates as always, but solid baselines to write deployment tooling around.
I clicked wondering if this was JS or Java Lambdas...but fair enough, liked the article anyway.
Shipping smaller artifacts is definitely the most important step to reducing serverless latency. Bundling Node.js serverless functions helps a lot.
I thought this was going to be about Lambda functions as in functional programing, please say AWS in your title.
I’m fairly new to using AWS Lambdas so loved this post. Lots of tangible insights on how we can improve things.
One amazing piece of tooling I’ve come across is SST: https://serverless-stack.com/
They build on top of AWS CDK & they have a very clever way to do “local” development by injecting a websockets into your deployed lambda & you can work against real infra instead of mocks