Google Cloud Run: the best  hosting platform for dynamic apps
Tags: cloud, googlecloud, docker, serverless
Published: 2020-11-12 22:07:20

Hello and welcome to my TED Talk.

Today I will be talking about a problem that all of us can relate to as developers with ultra-cool side projects in GitHub that have 0 stars: how to host lots of half-baked tiny apps for as cheaply as possible.

As a public-sphere-oriented side project, I built [a small web app to show Canadians their next holiday](https://canada-holidays.ca). It’s a zippy little express app with a bunch of server-rendered pages and an embedded DB, and it’s [open-source](https://github.com/pcraig3/hols/) so anyone can use it (even non-Canadians).

[express](https://expressjs.com/) is a popular JavaScript framework that’s fun to use and lets devs like us build simple applications quickly, which is one of the joyful things about programming. But as cool as it is when your app works on `http://localhost:3000`, the point of websites is really that other people can see them, so you gotta find somewhere to host them. But not every app is gonna make you a ton of cash or be an ad vehicle — sometimes you just want to host a cutesy little app without having to come up with a business plan.

So what’s the best option for hosting a basic web app while paying as little as possible? Well, if this was a mystery novel, I would introduce 12 shifty characters right around now, but the answer is **you should use [Cloud Run](https://cloud.google.com/run)**. 

**Cloud Run is easy to set up and it’s [basically free](https://dev.to/pcraig3/cloud-run-vs-app-engine-a-head-to-head-comparison-using-facts-and-science-1225) for low-volume apps**.

However, anyone who’s ever had a Grade 3 math teacher knows it’s important to show your work, so I’m going to go over some of the options I looked at and how they stack up against each other.

## Free hosting

In roughly chronological order, I started with free hosting options and then moved on to paid options. In general, free hosting comes with limitations that you can either accept or pay your way out of, so what you end up looking for is a good balance of uptime vs cost.

### Totally free static hosting 

#### eg, [Github Pages](https://pages.github.com/) or [Surge](https://surge.sh/)

Static hosting services are super reliable and super free (😻), but the major caveat here is that they restrict you to static sites (or in-browser JS, to split a hair). Does this work for you? Maybe, if you’re using a “compiles to static” framework like [Gatsby](https://www.gatsbyjs.com/) or [Next.js](https://nextjs.org/) (both Very Fun™️ in their own right). But not if you have picked up a more traditional <abbr title="model, view, controller">MVC</abbr> framework,  like [Flask](https://flask.palletsprojects.com/en/1.1.x/), [Rails](https://rubyonrails.org/), [Laravel](https://laravel.com/), or, in my case, express. 

If all you need is a totally static site — a bunch of HTML files — or you’re building a Single-Page App that offloads the logic onto a web browser, then you should probably just use a static hosting service and call it a day. (eg, [My personal website](https://pcraig3.ca) is running on GitHub Pages). 

However, if you’re writing server-side logic to listen for requests and build your pages, you might have leveled-up and out of this category.

### Totally free dynamic app hosting 

#### eg, [Heroku](https://www.heroku.com/dynos) or [Glitch](https://glitch.com/)

Usually you have to pay for server uptime, but a few prominent companies have a category called “the free tier”. <abbr title="Platform as a Service">PaaS</abbr> products like Heroku or Glitch offer this: they will host your app for free (!!) but — like [Jurassic Park](https://www.youtube.com/watch?v=T4kBRC2co7Y) after Dennis Nedry leaves — will **shut it down** after [x] minutes without traffic. Once your app is down, the next request that comes in can take 20 or 30 seconds to load because it needs to spin up _a whole server_ for the first request. For not-serious prototypes or little “Hello World!” tutorial apps, this is probably fine because your entire audience is your roommate and your mom. But once you want a site that will actually be usable, you come to two realizations:  

 1. this is untenable, and 
 2. more like “the free tear 😢” because it’s what happens to your eyes after staring at 20 seconds of a white page

## Paid hosting

Maybe it’s time to bite the bullet and pay to host. _Okay fine_, I reason to myself, _I am not bankrupt_. Truth be told, I regularly pay money for things (eg, [groceries](https://us.mattandsteve.com/products/the-extreme-bean-hot-spicy-3-x-1l) and [other necessities](https://www.amazon.ca/s?k=round+ice+cube+tray&rh=n%3A6647610011&ref=nb_sb_noss)). But I’m also not Geoff Bezos, [who makes more money](https://simpletexting.com/tech-ceo-salary/) in the time it takes for him to read this article than you or I will make in a year. So let’s see what’s on offer, but let’s also try to be cost-conscious.

### Paid server hosting

#### eg, Upgrading Heroku/Glitch, using [Digital Ocean](https://www.digitalocean.com/products/droplets/), or  [GoDaddy](https://www.hostgator.com/)  

Traditional server hosting is a well-trod path here, with many commodity services competing to sell you  uptime. Whether you want to upgrade your Heroku or Glitch plan, squeeze out a [Digital Ocean](https://www.digitalocean.com/docs/droplets/#:~:text=DigitalOcean%20Droplets%20are%20Linux-based%20virtual%20machines%20%28VMs%29%20that,or%20as%20part%20of%20a%20larger%2C%20cloud-based%20infrastructure.) droplet or poach yourself a big ol’ [HostGator](https://www.hostgator.com/web-hosting), the principle is pretty much the same. You pay a fixed rate for permanent server uptime and then your app runs all the time until either you die or you run out of money. If you’re looking for the cheap plans, they’re usually around $5-9 (USD!!) a month. 

Sure, not like it’s the end of the world, but I can also buy Netflix for $10/month (<abbr title="Canadian dollars">CAD</abbr>) and get like a million shows I’ll never watch. So it would be good if there were some cheaper options here, because $10/month quickly adds up to $9,360.00 (79 years being the average human lifespan).

#### Splitting the difference; axing our bills

The reason we’re getting such crap experiences with the free tier is that dynamic sites need a server to do some computation before they return pages. To use [my Canadian holidays site](https://canada-holidays.ca/) as an example, I look up how many days until the next holiday, so I need to check the current date every time a request comes in.

Building a page itself is pretty quick, but booting up a hibernating server takes a while. For the fastest responses, we end up keeping the engine idling 24/7. This way, our server is always ready to respond to incoming requests, but at the cost of a lot of uptime we don’t need.

So how do we split the difference? If we could find a way to pay _only for the time that we are serving web traffic_ (💡) then we can launch fleets of rarely-visited websites for next-to-free. Sounds simple enough, but how does it work in practice?

### Paid “serverless” hosting 

#### eg, [AWS Lambda](https://aws.amazon.com/lambda/) or Google [Cloud Functions](https://cloud.google.com/functions/)

Probably you’ve heard of serverless functions, aka Lambdas, aka Functions as a Service (FaaS): the idea is you run individual functions rather than a big fat web framework. “Server-less” makes more sense as two words in this context, because we need less of a server than all of one. What if, instead of our web server listening 24 hours a day for requests, we handled each request with a function that only runs when requests come in, and we pay _only_ for the time it took to run those functions?

What we’re talking about here is **function invocations**, which, for small projects, end up being cheap as chips. At 10k requests a month, you’re looking at [an estimate](https://cost-calculator.bref.sh/) of ~21 cents. There’re a lot of options in this space: the Big Three ([AWS](https://aws.amazon.com/lambda/), [Azure](https://azure.microsoft.com/en-us/services/functions/), [GCP](https://cloud.google.com/functions/)) all offer <attr title="Function as a Service">FaaS</abbr> services, as well as more upstart-y platforms like [Vercel](https://vercel.com/docs) or [Netlify](https://functions.netlify.com/). 

**But wait!** Is this going to work with express or Rails or whatever? Erm, there are options I suppose (eg, [serverless express](https://vercel.com/guides/using-express-with-vercel)). But out of the box, no. 

To be clear, if this works for you, then this is a great option. For low-volume sites, you are looking at pennies a month. But if you already have a conventional web app, it probably means a big, fat rewrite: a thing I was definitely *not* interested in, and I would posit that you shouldn’t be either.

### Containerized serverless (aka, the Holy Grail)

#### at long last, [Cloud Run](https://cloud.google.com/run/)

If you read the title of this post or the earlier-mentioned ‘TL;DR’, you might have guessed this, but for super unobservant people, the moment you have been waiting for is here. 

🥁🥁🥁

✨ Cloud Run ✨ is the gold at the end of this rainbow. Instead of paying for the time it takes to run function invocations, Cloud Run charges you for time spent running your app as a container — but the trick is that the container _only runs_ when requests come in. Unlike traditional server-hosting, the time to boot up a container is dramatically less than it takes to spin up a server. You don’t have to provision a VM or download anything: containers bundle together everything they need at build time. Building a container can take a while (sometimes several minutes), but starting them up is pretty zippy. 

It’s a really neat way to slice the Gordian knot here. As we’ve seen, the other options are:

- be static
- deal with downtime
- pay a lot for uptime you don’t need
- rewrite your whole damn app

With Cloud Run, get the best of both worlds: you get the pay-per-use model of serverless functions without overly constraining how you build your app. And since we’re talking about low-volume side projects presumably without much in the way of growth hacking, most of the time you’re not paying anything. 

You know the phrase, “make money while you sleep”? Well, this is similar: only it’s more like “most of the time you’re asleep, you’re not paying for Cloud Run.” And Cloud Run has a free tier too, which means if you’re really unpopular, hosting is free! 

### Okay, I’m interested. What’s the catch?

Glad you asked! Basically, the catch is you need a [`Dockerfile`](https://medium.com/bb-tutorials-and-thoughts/docker-a-beginners-guide-to-dockerfile-with-a-sample-project-6c1ac1f17490). Unlike with <abbr title="Function as a Service">FaaS</abbr> platforms, you don’t have to carve up your app like an LA plastic surgeon, but you **do** need to be able to run it as a container, which isn’t always part of the “Hello World!” tutorial you started with. 

The good news is that if you’re using a pretty established framework, examples abound. Google’s excellent “Build and Deploy” Quickstart tutorial [includes sample Dockerfiles](https://cloud.google.com/run/docs/quickstarts/build-and-deploy#containerizing) for 8 major programming languages. The JS one is 6 lines of code but I am a little more `l33t` than they expected so I got mine up to 15.

If you need an intro to Docker, [check out this excellent guide by Robert Cooper](https://www.robertcooper.me/docker-guide).

## Wrap up

If you’re still not convinced and you want to do more research, then that’s fine too. A good place to start is at the beginning of this article. Otherwise, you should give it a shot! Here are a few more resources to help you on your way.

- Hit up Google’s [“Build and Deploy” Quickstart for Cloud Run](https://cloud.google.com/run/docs/quickstarts/build-and-deploy)
- Learn [how much cheaper it is to use Cloud Run than App Engine](https://dev.to/pcraig3/cloud-run-vs-app-engine-a-head-to-head-comparison-using-facts-and-science-1225)
- [Deploy automatically to Cloud Run using Github Actions](https://dev.to/pcraig3/quickstart-continuous-deployment-to-google-cloud-run-using-github-actions-fna)

Thanks for reading! Happy devving!