A Firebase Cloud Functions Cold Start Solution
A few weeks ago, one of the biggest recent Firebase features was quietly announced – a solution for the Firebase Cloud Functions cold start problem.
If you use Cloud Functions, you know the issue very well: new instances of your server often needs to be created from scratch, which can take 10 or 20 seconds. This is due to the nature of serverless cloud functions where you are allocated instances on demand (as you need them). The benefit is theoretical infinite scaling and you only pay for the computing power you need. The downside is it takes time to instantiate the new instances.
The time to instantiate the new instances can have a major impact on your users’ experience by slowing down the site. We sometimes have progress bars going for many seconds when it should be instantaneous.
As the Firebase team states:
Functions are stateless, and the execution environment is often initialized from scratch, which is called a cold start. Cold starts can take significant amounts of time to complete. It is best practice to avoid unnecessary cold starts, and to streamline the cold start process to whatever extent possible (for example, by avoiding unnecessary dependencies).
If you search the web for solutions you get a lot of band-aids, such as lazy initialization of global variables, to urban legends, such as having a cron job to call your function every 5 minutes to keep it warm.
A Firebase Cold Start Solution
Fret not! A solution, or at least a start (no-pun-intended), is at hand.
Tucked away in the Firebase docs is technique to keep a minimum number of instances warm.
By default, Cloud Functions scales the number of instances based on the number of incoming requests. You can change this default behavior by setting a minimum number of instances that Cloud Functions must keep ready to serve requests. Setting a minimum number of instances reduces cold starts of your application. We recommend setting a minimum number of instances if your application is latency-sensitive.
This means you can choose how many instances are always available for use…no more 10-20 seconds creation time!
But there’s a catch, which we’ll discuss below, but first let’s look at how you set the minimum instances.
How to Set Firebase Cloud Functions Minimum Instances
In your function definition add the run time options, such as:
exports.getAutocompleteResponse = functions.runWith({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
}).https.onCall((data, context) => {
// Autocomplete a user's search term
});
The minInstances
can be set as low as 1 or as high as you wish. However, it will cost you.
The Price You Pay
Nothing comes for free, and neither do warm instances.
You’re charged for idle warm instances. The pricing starts around $6 per month per function and goes up from there.
A minimum number of instances kept running incur billing costs at idle rates. Typically, to keep one idle function instance warm costs less than $6.00 a month.
You’ll now need to decide if it is worth it to have cloud functions or just pay for servers at AWS or Digital Ocean.
I suggest starting at one minimum instance for your key functions, see what impact it has vs cost, and increase or remove based on your findings. We’ve gone with one instance for infrequently used function and 5–10 instances for frequently used functions.
Our Impression
We’ve been running our servers for a week now and I can say it makes a huge difference. The app is snappier and the progress bars barely show.
We forgot to add minInstances for one of our pages and immediately users complained the page was slow relative to the rest of the site. Awesome!