Cloud Run and Cloud Function: What do I use? And Why?
By: Guillaume Blaquiere
Tags: Google Cloud, Google Cloud Functions, Serverless, Google Cloud Platform, Google Cloud Run

However, when I want to implement, in Python, Go or NodeJS, a workload triggered by an HTTP request, like a batch processing triggering by a Cloud Scheduler or a single purpose HTTP webhook, What I should use ?

It’s possible to use a Cloud Function to address this problem. Single purpose, http triggered and language in GA. But it’s also possible to build a HTTP container and to deploy it with Cloud Run.

When I have to cope with this question, I always use Cloud Run. Why ? Indeed, this choice could seem overkill for a single purpose usage. However, I have 2 main reasons

Portability

When you develop for Cloud Run, you have to build a container. This container have the ability to be deployed anywhere: on premise, on Kubernetes/GKE, on Cloud Run (serverless and GKE), on a VM,… anywhere.

On the other side, code deployed on Cloud Function implicitly assumes that there is a webserver, somewhere, able to route the request to the code. For changing the execution environment, you have to repackage the code, maybe in a container, but at least with a webserver in front of it.

Cloud Run has here this strong advantage to reduce the rework and the refactoring when you want to change the environment. And, you are less locked in to Google Cloud.

Testability

In mission critical development, the testability and the reliability are paramount. I’m not talking about unit test here, but about end-to-end tests also called “integration” tests. In a production environment in real time IoT application, we can’t be approximative or accept to lose messages because of a bad version.

With Cloud Function, the code handles the request forwarded by the webserver of the execution environment.

Python Callback Cloud Functions with Basic Authorization

Thereby, for testing your function you have to simulate the webserver request and to fill correctly the request object passed in parameter of the code. Not sure that is the best way, but, even in the GCP doc, there is no example in Python; I did what could with my (low) level in Python -> I’m open to suggestions!

Test code with custom request for Callback Cloud Function

Here is the problem: How can you be sure that the simulated object is correct ? Do you know all the headers passed in this object ? How arebasic authentication, Bearer or API keys set ? Do you know the version of the request object used in Cloud Function environment ?

Personally, I’m not able to answer these questions. And the new developer that joins your team, is he able ? Moreover, I’m not confident in my test code, and it’s a problem not to be confident in tests !

My solution for solving this issue is to create a test file, with a webserver that imports the function code.

Test webserver for Cloud Function

To launch a test, simply calls the webserver with CURL command. This way, the webserver will format correctly your request object, with all the rules and the parameters, and forward it to your code. The additional advantage is that you can change your webserver, and even your dev language, without changing your CURL test requests.

And, it’s at this moment that Cloud Run make all its sense. In this context, Cloud Run is no more than Cloud Function code + simple webserver that forwards requests. Simply add a standard Dockerfile for your language. And it’s over - you don’t have a Cloud Function with a test server, but a packaged container ready to be deployed on Cloud Run.

Cloud Run everytime!

So, Cloud Run is the good mix of simplicity of Cloud Function, end-to-end testability and portability. Many pain-points are solved, many advantages are gained, that’s why I use and I recommend Cloud Run for all your stateless HTTP container, even for events like PubSub (create a push subscription for calling your Cloud Run) or Storage (create a PubSub notification on GCS). For other events, Cloud Functions are, until now, unavoidable.

In addition, you can consider several other advantages of Cloud Run like the capacity to handle several entry-points in only one deployment. Or also, the capability to run a workload up to 15 minutes (only 9 minutes with Cloud Function). But also, the capability to be charged only once and to be impacted by the cold-start once when several requests are handled concurrently (up to 80), but with the trade-off of a loss of isolation/memory sharing between all requests (also possible with Cloud Run if you set the concurrency param to 1).

Finally, for me, Cloud Run is the best solution for a majority of use cases. The development team is very active and new features are constantly added: Metrics, Cloud SQL connectivity, Service Account Identity,… I strongly recommend you to stay tuned of this product, it will become essential for all purposes!