Firebase Functions, Cold Starts and Slow Response

Viewed 274

I am developing a new React web site using Firebase hosting and firebase functions.

I am using a MySQL database (SQL required for heavy data reporting) in GCP Cloud Sql and GCP Secret Manager to house the database username/password.

The Firebase functions are used to pull data from the database and send the results back to the React app.

In my local emulator everything works correctly and its responsive. When its deployed to Firebase Im noticing the 1st and sometimes the 2nd request to a function takes about 6 seconds to respond. After that they respond less than 1 sec. For the slow responses I can see in the logs the database pool is initialized. So the slow responses are the first hit to the instance. Im assuming in my case two instances are being created. Note that the functions that do not require a database respond quickly regardless of it being the 1st or 2nd call.

After about 15 minutes of not using a service I have the same problem. Im assuming the instances are being reclaimed and a new instance is being created.

The problem is each function will have its own independent db pool so each function will initially provide a slow response (maybe twice for the second call). The site will see low traffic meaning most users will experience this slow response.

By removing the reference to Secret Manager and hard coding username/password the response has dropped to less than 3 seconds. But this is still not acceptable.

Is there a way to:

  1. Increase the time that a function is reclaimed if not used?
  2. Tag an instance that it should not be reclaimed?
  3. Is there a way to create a global db pool that does not get shutdown between recycles?
  4. Is there an approach to work with db connections in Firebase Functions to avoid reinit of the db pool?
  5. Is this the nature of functions and Im limited to this behavior?

Since I am in early development, would moving to AppEngine/Node.js (the Flexible Plan) resolve recycling issues?

1 Answers

First of all, the issues you have been experiencing with the 1st and the 2nd requests taking the longest time are called cold starts.

This totally makes sense because new instances are spun up. You may have a cold start when:

  1. Your function has been deployed but not yet triggered.
  2. Your function has been idle(not processing requests) enough that it has been recycled for resources.
  3. Your function is auto-scaling to handle capacity and creating new instances.

I understand that your five questions are intended to work around the issue of Cloud Functions recycling the instances.

The straight answer from questions 1 to 4 is No because Cloud Functions implement the serverless paradigm.

This means that one function invocation should not rely on in-memory state(database pool) set by a previous invocation.

Now this does not mean that you cannot improve the cold start boot time.

Generally the number one contributor of cold start boot time is the number of dependencies.

This video from the Google Cloud Tech channel exactly goes over the issue you have been experiencing and describes in more detail the practices implemented to tune up Cloud Functions.

If after going through the best practices from the video, your coldstart shows unacceptable values, then, as you have already suggested, you would need to use a product that allows you to have a minimum set of instances spun up like App Engine Standard.

You can further improve the readiness of the App Engine Standard instances by later on implementing warm up requests.

Warmup requests load your app's code into a new instance before any live requests reach that instance. The last document talks about loading requests which is similar to cold starts in which it is the time when your app's code is being loaded to a newly created instance.

I hope you find this useful.

Related