Hi have 100+ cloud functions and a completed app, control panel and marketing website. When testing, my client said that the site was slow. This was because of the cold start times on all these functions.
I’m not really interested in having a cron job that hits each function every minute as there are a lot, and as other posts suggest, they are not always going to work.
Last night I had an idea. I know it is slightly gross, but I want to know what the consequences (other than not being able to release individual functions) would be of having a single cloud function end point, that switches a parameter with the function name, that then calls the other local functions that are imported. This would mean that the single function would be slow the first time for some users, but then every other function would be fast, as the function would already be warm.
Unfortunately I need to do one of the above to improve performance until firebase release a feature like aws to allow paying to keep functions warm.
It's not possible to entirely eliminate cold start times. They will always exist in serverless environments - that's a matter of fact. The best you can do is organize your code to minimize the cold start times. Without seeing all your code and your specific benchmarks, there is no specific advice we can geive.
The only thing that's in your control is to make sure that each function only loads the minimum amount of code at the global scope to run correctly. So, if your functions all load some code at the global scope that's unused, all those functions will pay an unnecessary cold start cost to load and run the code they don't use.
There are resources out there that will help you do that. Watch this video for more detail.
Related
I am aware that I can set the minimum number of instances for a cloud function.
However, I have some functions that are called infrequently so this is not practical from a cost standpoint.
I do know beforehand when a user is going to call a cloud function from the UI as it is the next step in a series of steps.
Is there a way to warm the function up before the actual call so it is faster or is it the only way to actually call it?
If the only way is to call it then I could make the function so that it can be called with a warmUp parameter which just starts and then exits the function 5-10 seconds before it is called by the user. Could this approach work?
As #John Hanley mentioned you can call the function asynchronously. That will cold start an instance. You can checkout the recommendations mentioned in Document to optimize your deployed function which will reduce the cold start time. Please checkout the video minimize cold start time for details.
You can refer to the document for another workaround Cold start workaround.
To avoid the cold start you may want to consider running your own server instances using something like App Engine to have warm up requests.
I remember to have read an article where it was explained that Cloud Functions are not guaranteed to be executed and especially in the right order. I can't find any sources on this anymore.
Is this still recent information?
I am aware that the start of a function can take a couple seconds, especially when cold starting the function.
Could I reliably increment a number each time a document is created in a specific Firestore collection without getting my numbers mixed up? I know this is done often but I've never seen information on whether or not it is safe to do.
Following up on question one, are there red flags when using Cloud Functions for payment backend services?
Can I be sure that Cloud Functions are executed in the order that they were triggered i.e. are they queued or executed in parallel?
Could I reliably increment a number each time a document is created in a specific Firestore collection without getting my numbers mixed up?
You can certainly write code to do that. You will need to keep track of a running count of documents in another document, and use a transaction to keep it up to date.
I don't recommend doing this. It's kind an anti-pattern in Firestore to impose sequentially increasing numbers for documents in a collection. If you want time-based ordering, you should consider using a timestamp instead.
Can I be sure that Cloud Functions are executed in the order that they were triggered i.e. are they queued or executed in parallel?
Cloud Functions provides absolutely no guarantee that functions invocations will happen in any order. They are asynchronous and can execute in parallel on multiple server instances, depending on the load applied to the function.
I strongly suggest reading through the documentation to understand the execution environment provided by Cloud Functions.
So according to the Google Cloud docs:
Max inactivity time for background functions = 30 days
The maximum amount of time that a background function can be kept without any invocation. Functions that are not invoked even once during this time may enter a state in which new events will not trigger them anymore. If this happens, such functions have to be redeployed to start working again. Note: This inactive state is not reflected in the UI, CLI, or API in any way.
I have an application with close to 40 cloud functions and there doesn't seem to be an easy way for me to tell if a function is close to becoming inactive so I know to take action before it happens and I really don't want to filter through the logs in the console with each function every week to see when each was invoked last.
Outside of just doing a redeploy of my functions every month to insure they are fresh is there anyway to easily tell when a function is becoming stale in case it does happen so I only have to deploy said function before it becomes stale?
Also, for any firebase'r that might read this, is there any solutions possibly coming to this in the future?
Thanks in advance.
Sorry, there's no way to tell where your function is during its 30 day idle expiration. The good news is that the Cloud Functions team is working on removing this limitation, but there's no public timeline for that.
EDIT: This problem is resolved now for all newly deployed functions.
I tried a couple of my trigger functions as https.onCall and called them after promise return and so far they work really well and faster than the triggers.
What's the catch? Are they also affected by the cold starts too?
If not, then unless it's cron job or lack of support of app language, why should anyone use use a trigger function at all?
All Cloud Functions are affected by cold starts. This is how all serverless function architectures work. In order to scale down to zero (so you pay nothing if you use nothing), all server instances must be able to be decommissioned. Cold start up cost is paid when a new server instance is allocated, so going from zero to one will cost you one cold start.
You haven't defined what a "trigger function" is, so I'll assume you mean a "background function" which triggers in response to events that occur within your project.
Background functions are absolutely required when you want to have some work performed in response to those changes when you can't trust the client to perform that work directly. This is important to maintain data consistency, and also to prevent having to duplicate logic among all your different clients that are all doing the same thing. This also allows you to ship new features and bug fixes without having to ship new client code, which can be difficult and time-consuming.
After watching a fair amount of youtube videos, it seems that Google is advocating for multipath updates when changing data stored in multiple places, however, The more I've messed with cloud functions, it seems like they're and even more viable option as they can just sit in the back and listen for changes to a specific reference and push changes as needed to the other references in real time. Is there a con to going this route? Just curious as to why Google doesn't recommend them for this use case.
NEWER UPDATE: Literally as I was writing this, I received a response from Google regarding my issues. It's too late to turn our apps direction around at this point but it may be useful for someone else.
If your function doesn't return a value, then the server doesn't know how long to wait before giving up and terminating it. I'd wager a quick guess that this might be why the DB calls aren't getting invoked.
Note that since DatabaseReference.set() returns a promise, you can simply return that if you want.
Also, you may want to add a .catch() and log the output to verify the set() op isn't failing.
~firebase-support#google.com
UPDATE: My experience with cloud functions in the last month or so has been sort of a love-hate. A lot of our denormalized data relied on Cloud Functions to keep everything in sync. Unfortunately (and this was a bad idea from the start) we were dealing with transactional/money data and storing that in multiple areas was uncomfortable. When we started having issues with Cloud Functions, i.e. the execution of them on a DB listener was not 100% reliable, we knew that Firebase would not work at least for our transaction data.
Overall the concept is awesome. They work amazingly well when they trigger, but due to some inconsistencies in triggering the functions, they weren't reliable enough for our use case.
We're currently using SQL for our transactional data, and then store user data and other objects that need to be maintained real-time in Firebase. So far that's working pretty well for us.