Cold starts usually entails:
- higher invocation latency as Lambda provisions another container to load and run your code, this can vary greatly by language runtime (see this post for comparison)
- if you keep any state in the function, you lose those too; AWS generally recommend keeping functions stateless but you might still cache static data as optimization, or you simply have to main a live connection to your database (eg. I find connecting to MongoDB is a good 1–2s so wouldn’t make sense to create a new connection for each invocation, not to mention the possibility of blowing up the database with excessive no. of connections)
The simplest way to keep seldom used functions is to have another Lambda function (hook up to a CloudWatch schedule that runs every X mins) do the job for you and ping other functions that need to be kept warm. Usually I do this for Lambda functions that serves user-facing APIs, and the pinger function would use Lambda’s
ListFunctions API to find all functions with the
-api suffix (a convention we use) and invokes them programmatically with a payload that indicates it’s a ping as opposed to an API Gateway invocation. All these api functions handles this payload in a standardised way, without executing the normal code path and just returns straight away.
Seriously, if you’re gonna use Lambda then don’t bother with Fission/Kubeless — they’re great if you are worried about vendor lock-in but you have to reimplement all the hooks to the rest of the AWS ecosystem yourself (which is where you get the power of the event-driven model with Lambda, not to mention many cost savings).
ps. Lambda also terminates functions that are actively used after some time — from my recent experiment I see that happen after 7 hours of uptime. It’s a good thing in my opinion — no need to worry about a whole class of problems associated with long-lived servers, from subtle memory leaks to having long-lived servers that have been compromised by attackers, etc.