I'm using the Serverless framework (serverless.com) and it looks like I can save some pretty serious money by only scaling up the provisioned capacity of my Lambda functions during business hours (9am-5pm, 40 hour per week) and then down to zero during off hours. My application isn't used very much in off hours, and if it is, my users are okay with cold starts and it taking longer.
In my serverless.yml, I have functions declared such as:
home_page:
handler: homePage/home_page_handler.get
events:
- http:
path: homePage
method: get
cors: true
authorizer: authorizer_handler
provisionedConcurrency: 1
I also have a Lambda that runs on a regular basis to set the provisioned capacity of the other Lambdas in the account depending on the time of day. In that Lambda if I call:
await lambda.putProvisionedConcurrencyConfig({
FunctionName: myFunctionName,
ProvisionedConcurrentExecutions: 0,
Qualifier: "provisioned",
}).promise();
Then I get this error:
Received error: ValidationException: 1 validation error detected: Value '0' at 'provisionedConcurrentExecutions' failed to satisfy constraint: Member must have value greater than or equal to 1
at Object.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:52:27)
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/rest_json.js:55:8)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:688:14)
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:690:12) {
code: 'ValidationException',
time: 2021-08-14T17:45:48.932Z,
requestId: '8594fad6-d5dd-4a00-adca-c34f9d38b25e',
statusCode: 400,
retryable: false,
retryDelay: 77.81562781029108
}
On the other hand, if I try to delete the provisioned capacity entirely, like this:
await lambda.deleteProvisionedConcurrencyConfig({
FunctionName: myFunctionName,
Qualifier: "provisioned",
}).promise();
That works fine, but when I try to deploy my function again in off hours (which is the norm), CloudFormation errors out with:
No Provisioned Concurrency Config found for this function (Service: AWSLambdaInternal; Status Code: 404; Error Code: ProvisionedConcurrencyConfigNotFoundException; Request ID: 75dd221b-35d2-4a49-80c5-f07ce261d357; Proxy: null)
Does anybody have a neat solution to turn off provisioned capacity during some hours of the day?