Last week, I worked on a project that used Lambda as an API to run an algorithm triggered by multiple services in my company. I implemented it with AWS Serverless Application Model (AWS SAM), wrote the template, and set up CI/CD with no problem, except for one, the first request was slow.
A Lambda function instance created at startup will disappear after a certain period. Therefore, if Lambda is executed after a certain period, there is a good chance that the function instance has disappeared and is re-executed from its creation. This is what we call Cold Start.
If Lambda is re-executed before the function instance is lost, the container is reused, as shown in the following slide, and execution without startup time (warm start) becomes possible. If Lambda functions are executed frequently, the container is more likely to be reused, and the probability of a cold start will decrease.
My goal is to prevent cold start so that customers using our services will have a good user experience. I could implement an event that fires lambda every minute, but In addition to the time-consuming setup process, There is no fixed amount of time before a function instance goes into an unconscious state. Therefore, periodic execution is only a method to reduce the probability of a cold start and cannot guarantee a warm start.
Another way, which guarantees a warm start and can be done with a bit of setup, is Provisioned Concurrency.
In my case, I use AWS SAM Template to Implement it. If you prefer to configure it on the console, I recommend reading AWS Official's blog post about how to do it.
AWS SAM Template Example
It is as simple as adding these three lines to the
template.yaml. I will pretend we all know about SAM Template and some basic Code as Infrastructure in AWS.
.... Resources: MyFunction: Type: AWS::Serverless::Function Properties: ..... AutoPublishAlias: live ProvisionedConcurrencyConfig: ProvisionedConcurrentExecutions: 1 .....
And if you have multiple environments (QA, test, etc.) and want to apply it only on production to save cost. Here is my approach to doing that.
... Parameters: Environment: Type: String Description: 'Enter Env Name' Conditions: ConfigureConcurrency: !Equals - !Ref Environment - prd Resources: MyFunction: Type: AWS::Serverless::Function Properties: ..... AutoPublishAlias: live ProvisionedConcurrencyConfig: !If - ConfigureConcurrency - ProvisionedConcurrentExecutions: 1 - !Ref "AWS::NoValue" .....
It will create an alias but will not set provisioned concurrency in other environments except
prd, which is an alias for production.
Note About Provisioned Concurrency
- Provisioning Concurrency need time, we can set
Linear10PercentEvery1Minuteetc). as of my research, I couldn't find if it causes downtime or not.
- Cannot use $LATEST. We must create a version or alias.
- To make sure we use Provisioned Concurrency, access with arn of the alias. (
- It is not cheap (sadly). Here is some simple Lambda simulation
As of my finding, here is a way to lower the price:
- Lower Concurrency count. Chances are we don't need it
- Use Application Auto Scaling to scale down outside busy hours.
- Use it only in an environment that needs it.
Here, I have summarized my understanding. I hope it will be helpful to those who may have difficulty setting it up in AWS SAM template or making it work in multiple environments.
Did you find this article valuable?
Support Alvin Endratno by becoming a sponsor. Any amount is appreciated!