The more I explore Google Cloud's endless catalog of cloud services, the more I really like Google Cloud. This is why before moving forward, I'd like to be transparent that this blog has become little more than thinly veiled Google propaganda, where I will henceforth bombard you with persuasive and subtle messaging to sell your soul to Google. Let's be honest; they've probably simulated it anyway.

It should be safe to assume that you're fairly familiar with AWS Lambda Functions, which have served as the backbone of what we refer to as "serverless." These code snippets in the cloud have restructured entire IT departments and are partially why almost nobody knows enough basic Linux to configure a web server or build anything without a vendor. In my opinion, Google Cloud Functions are better than that, so strap in.

AWS vs GCP Comparison

First off, let's talk about a big one: price. AWS charges based on Lambda usage, whereas Google Cloud Functions are free. The only exception to this is when you break 2 million invocations/month, at which point you'll be hemorrhaging as ghastly 40 cents per additional million. That's ridiculous. I think we've just discovered Google Cloud's lead generation strategy.

What about in terms of workflow? AWS holds an architecture philosophy of chaining services together, into what inevitably becomes a web of self-contained billable items on your invoice. A fine illustration of this is a fine post on common AWS patterns which provides a decent visual of this complexity, while also revealing how much people apparently love this kind of shit, as though SaaS is the new Legos. To interact with a Lambda function in AWS via HTTP requests, you need to set up an API Gateway in front. I hate setting up API Gateways: it's a feat more convoluted and difficult than actually coding. Pair this with an inevitable user permission struggle just to get the right Lambda roles set up, and you quickly have yourself a nightmare- especially if you're just trying to get a single function live. Eventually you’ll get to write some code or upload a horrendous zip file like some sort of neanderthal (friendly reminder: I am entirely biased).

GCP has clearly been taking notes on the sidelines on how to improve this process by removing red tape around service setup or policy configuration. AWS and GCP are tackling opposites approaches; AWS allows you to build a Robust API complete with staging and testing with the intent that some of these APIs can even be sold as standalone products to consumers. GCP takes the opposite approach: cloud functions are services intended for developers to develop, which covers the vast majority of use cases in my opinion.

Cloud Function Deployment

To create our first function to serve as an endpoint, we'll utilize the following:

  • A new Cloud Function running Python 3.7
  • Google's Source Repositories: AKA a Github/Bitbucket clone with auto-syncing to your real repos, along with direct access to GCP services (think Heroku's source control).
  • The gcloud CLI to enable us to work locally.

You should immediately notice the glaring lack of any mentions of API endpoints, methods, stages, or anything related to handling web requests. It should not be understated that Cloud Functions are preconfigured with an endpoint, and all nonsense regarding whether endpoints accept GET or POST or AUTH or OPTIONs is missing entirely. These things are handled in the function itself, and because Google Cloud functions running Python are preconfigured with Flask, all of that stuff is really trivially easy. That's right, we've got Flask, Python, and GCP all in a single post. Typing these words feels like eating cake while Dwyane The Rock Johnson reads me bedtime stories and caresses me as I fall asleep. It's great.

Create your Function

Our function will intend to serve as a Python HTTP endpoint:

Single-page setup. Easy.
  • Trigger specifies what will have access to this function. By selecting HTTP, we will immediately receive a URL.
  • Source code gives us a few options to deploy our code with cloud source repository being by far the easiest solution, especially when working locally.
  • Runtime allows you to select NodeJS by accident.

Before we get to code, let's talk Python libraries.

Including Dependencies in your Function

Our function comes prepared with two files: and our friend requirements.txt. These files do exactly what you'd expect, as per every project ever:

Unfortunately, ease-of-use ensures that GCP certifications will be in low demand.

Our function immediately installs all dependencies in requirements.txt for use upon deployment. Once deployed, we can import these libraries as expected. So, let's deploy something.

Google Source Repositories

Google's source repositories can serve as a stand-in replacement for Github (unlikely), or auto-sync to any repo on the version control behemoth of your choice. The advantage of this extra layer is mostly to trigger deployments upon commits, which in turn feed into GCP's own CI/CD processes (which remain young for now). Create a repo locally using gcloud:

$ gcloud source repos create real-repo
$ cd myproject/
$ git init
(take a moment to write or save some actual code here)
$ git add --all
$ git remote add google
$ git commit -m 'cheesey init message'
$ git push --all google

Now make that puppy go live with gcloud functions deploy totally-dope-function, where totally-dope-function is name of your function, as it should be.

Now let's get to the coding part.

The Coding Part (ft. Flask)

Here's perhaps the most basic endpoint you'll ever create:

import requests

def endpoint(request):
    """Does the things."""
    if request.method == 'POST':
    # Allows POST requests from any origin with the Content-Type
    # header and caches preflight response for an 3600s
    headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'POST',
        'Access-Control-Allow-Headers': 'Content-Type',
        'Access-Control-Max-Age': '3600'
    request_json = request.get_json()
    if request_json:
        plaintext = request_json['plain']
        html = request_json['html']
        return html
        return 'You didn't pass a JSON body you idiot.'

If you're familiar with Flask (you are, because you're on this blog) you already know what all of this does. Look at that simple copy-paste of headers, as opposed to working them into a horrible web interface. Gasp in disbelief as you realize that typing if request.method == 'POST': would be a 10-minute task in a visual API building tool. We've made it fam.

Ease of Logging

Because we have a real endpoint to work with, we don't need to waste any time simulating stupid fucking tests where we send fake JSON to our function. We can use postman or anything to immediately interact with our endpoint, and the logs are a click away:

Easy. Breezy. Beautiful.

There's no point in me droning on at this point because you've surely already ventured into the Google Cloud console in blissful disbelief as a good obedient drone would. If adopting Google Cloud is the last shred of hope we have to resist Google's all-knowing algorithms which have already replaced the illusion of free will, I'd gladly take that dystopia over setting up monolithic API Gateways any day.

The Downsides

Time for the asterisks to kill that euphoric buzz you might've experienced for a brief moment. My sole purpose as an engineer is to have my dreams crushed full-time; I simply cant resist returning the favor.

First notable drawback of Cloud functions is a lack of out-of-the-box custom DNS configuration. Firebase has workarounds for this, but Firebase is a beast of its own.

When it comes to debugging, functions tend to fall short in comparison to their Lambda rivals. Most Cloud Function debugging involves deploying, testing in dev, and sifting through cryptic error logs (they can be quite bad). There's nearly no UI mock testing to speak of. You'd better brush up on PyTest.

My best advice is to be careful with what services you play around with on GCP. Let's not forget this is a platform geared exclusively towards enterprises; the fact that we're even playing ball here makes us weirdos in the first place. Don't let yourself hemorrhage money like an enterprise.