Deploying on Heroku vs App Engine – the basics

If you’re looking for somewhere to test deploying a small web service without much hassle and incurring costs/ much costs, Heroku and Google App Engine are 2 possible choices. This posts compares deployment of a bare web application for free on Heroku vs Google App Engine.

The objective: Comparing deployment of a bare web application on Heroku vs Google App Engine

The app

To keep things really simple I created a Flask app that returns just a single line for now. No database connections, environment variables, Javascript, no CSS, not even HTML. Might experiment with adding on the rest next time. The app can be run on its own and accessing the port assigned to it (via a web browser) will return the line:

This is all there is ... for now.

Here’s the few lines of code for the app (main.py), also available on Github:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return "This is all there is ... for now."

if __name__ == '__main__':
    app.run()

Common files

For this basic app there are 2 files that are common to both Heroku and App Engine. First is main.py above, and second, requirements.txt, which contains the dependencies: Flask and Gunicorn.

Flask==0.12.2
gunicorn

Those are almost all that is needed to deploy on Heroku or App Engine, less a specs file each coming up next. For Heroku, requirements.txt plays an additional role in allowing Heroku to recognize that the app you’re deploying is a Python application. There are other ways to indicate that (your app is a Python app) on Heroku, but this is the most straightforward way in my opinion, assuming your app runs on the default Python runtime.

Procfile for Heroku

The Procfile

specifies the commands that are executed by the app on startup

https://devcenter.heroku.com/articles/procfile

In this case you’d need to specify that your app is a web application running on a Gunicorn application server, and that the name of your app is main.py. In order to do this, the only line required in Procfile is:

web: gunicorn main:app

Note that the Procfile has no file extension.

app.yaml for App Engine

For Google App Engine, the file to specify the application configuration is app.yaml. There are many details you can specify here, but the bare minimum is defining the runtime, and leaving the rest of the settings to default:

runtime: python37

Also on Github here. Note that the application configuration does not specify the filename of the application to run. By default, when a Python runtime is indicated, App Engine will run main.py (in the same folder) as the main application.

And those are all the files you’d need to deploy a basic app on the web! All those files described above (really, not much) can be found here. Next, slightly more complicated stuff.

Creating an app instance on Heroku

You’d first need to install the Git CLI and Heroku CLI on your local command line interface (Command Prompt/ Terminal/ etc). You’d also need a Heroku account prior to carrying on. You’ll also need the project directory/ folder already created (sample directory contents here) and initialized as a Git repository. Let me know if more details are needed on these.

For either way below, the app name provided will be the default address to access your application, at <app name>.herokuapp.com/. When creating a named app, if someone else has already used that name you will not be able to create the app.

The first way to create a new app is through the web interface, which should be pretty straightforward. After that you’d need to set up a Heroku Git remote from your local directory containing your project. This also works if you already have a Heroku app instance that you want to write your application to. The command is:

heroku git:remote -a <your app name>

The other way is to create a new app directly from command line. From your project directory, run:

heroku create

This will create a new app with a randomly assigned name, for example, thawing-inlet-61413 in the more detailed explanation. If you want to create an app through command line with a name, simply add the desired app name after “create”.

heroku create <your desired app name>

With your files ready and app set up, you’re ready to deploy! But first, setting up an app on App Engine, for comparison.

Creating an app instance on App Engine

First you’ll need to set up a Google Cloud Platform account. Next, ensure you have the GCloud CLI installed. The last step is creating the project. For either steps below, if you do not assign a custom domain to your app engine application, the address for your application deployed will be <project id>.appspot.com.

The first way to create a project through the Google Cloud Console web interface. Remember your project ID.

Alternatively, run on your command line interface:

gcloud projects create [YOUR_PROJECT_ID] --set-as-default

Setting as default will save you some commands later, but if you’re running multiple projects concurrently it may not be helpful.

Regardless, you now have your project set up, and all that is left is to deploy your application to your project. Note that for App Engine it is not required to initialize your folder as a Git repository nor set up any config in your folder pointing it to App Engine. All is specified at point of deployment.

Deployment through Heroku CLI

As mentioned earlier, your project directory should have been initialized as a Git repository and your Heroku app set up as a Git remote. You should also have a Procfile in your root directory. To launch or update your app, commit your files/ changes to your repository’s master branch, then run the command from your repository/ project directory in your command line interface:

git push heroku master

The Procfile should be detected and the app will start building. To deploy from a non-master branch, check out the documentation here.

Deployment through GCloud CLI

For App Engine, you won’t have to dabble with the Git commands, and instead, from your project directory in the command line interface, enter:

gcloud app deploy <app.yaml> <--project your-project-id>

The commands in angle brackets are optional (and used without the angle brackets, if you’re wondering). If your config file is not app.yaml you can replace <app.yaml> with your config filename, in the same format as app.yaml. For project, if you have set up a default Google Cloud Platform project for your command line interface’s installation of Gcloud CLI, and that is the project you’d like to deploy your app on, you can ignore the second command in angle brackets. In any other case you can specify it here, without the angle brackets. For example, if my config file is indeed app.yaml but the project I want to deploy to is thisproject-123 and not the default project, I’ll use:

gcloud app deploy --project thisproject-123

Controlling costs on Heroku

Controlling costs on Heroku is pretty straightforward if what you want is a free app. Personal accounts are allocated free monthly dyno hours. By default when you create a new app, it will be set to utilize the free dyno hours. When the hours run out, your app will not be accessible for the rest of the month. You will not have to worry about accidentally incurring costs.

Of course, the downside is that your app may not be running in the later part of the month, but as it is meant to be somewhat of a sandbox and accounts are allocated 1000 free dyno hours a month, you’ll unlikely hit it for something you’re experimenting around with.

The other (potential) drawback is that free dynos shutdown after 30 minutes of inactivity, and if you’re accessing it for the first time after being shutdown, the initial calls can take a long time to return. On the other hand, the shutting down of the dyno preserves your free hours.

Controlling costs on App Engine

And here’s where it gets tricky if you’re aiming to build an app that will not incur any costs. Generally speaking there are free tiers available for many Google Cloud products, but usage can exceed the free tiers and you will be charged up to the billing limit set. Unfortunately billing limits are not set by default, and can’t seem to be set at 0. Also, while many products offer free tiers, they are for specific regions and configs only, and there aren’t indications along the way to let you know if you’re selecting a free-tier-available setting, so lots more caution when deploying if you want to avoid running up nasty unintended costs.

This is in contrast to a Heroku dyno, where you have to take explicit action if you want your app to not be bounded by free tiers. Also, unlike Heroku where billing/pricing details are on a single page, there are a few pages to refer to even just to understand billing for using App Engine.

App Engine

Pricing for App Engine itself is still quite manageable. The daily free limits should be sufficient for most sandbox apps. As long as you do not set in app.yaml to use the Flexible Environment and your app is not huge nor heavily accessed I think you’re unlikely to incur specific App Engine costs.

Cloud Build

However, deploying an app to App Engine triggers Cloud Build, another Google Cloud Platform product. 120 minutes of free build minutes a day should be sufficient in most cases, but again, something to look out for.

Cloud Storage

Finally, Cloud Build creates huge images when building applications, and stores them on multi region buckets on Google Cloud Storage. In practice, this was the (almost) unavoidable (though small) cost. There weren’t any warnings that these were being created and I only noticed when I received a (tiny, but non-zero) bill the next month after experimenting on what I thought was should be a free app. Cloud Storage has free tiers too but these images created do not fall into the free tier (due to region and size, I’m guessing).

Not much of a engineer to say how the images can or will be used, but deleting the images after each build helped. Will just need to remember deleting the images from Google Cloud Storage after deploying to ensure your app remains free.

Minimizing app engine costs

While incurring costs are almost unavoidable without additional steps, there are more steps you can take to avoid nasty shocks. Firstly, you can set very small (non-zero) spending limits on App Engine (Cloud Console > App Engine > Settings). This is useful in the event your app receives an unexpectedly large amount of requests. Next, you can monitor billing across your project(s) on the billing console to nip unexpected bills in the bud before they explode. Finally, Google Cloud Platform offers new users US$300 credit for 1 year, a good amount and length of time to get familiar to the complex billing structures on Google Cloud Platform. In short, lots more configs relating to app and billing management on GCP, but probably more scale-able and reliable.

What’s next

This post covers deployment of a stripped down (to a single line) web application with no add-ons nor features. It is possible to build much larger and complex applications on both platforms. Both offer a suite of add-ons and related products you can easily connect to, some for free and some paid. Running your application with a proper front and back end, static files, database connections and environmental variables is going to change the game significantly. With my present expertise (or lack of) I don’t think I should go deeper into these topics, but hopefully, somewhere in the future.

If you’re looking for something that’s quick to set up and easy to deploy with minimal steps, don’t intend to scale your project very much and don’t mind the lag at start up, Heroku may be the better alternative. On the other hand if you prefer having greater control over the little details, have an eye on scaling your app or connecting with other Google Cloud products in future and don’t mind a bit more hassle, App Engine might be perfect. Happy deploying!

Further reading

Heroku

Google App Engine

Leave a Reply

Your email address will not be published. Required fields are marked *