Google App Engine Deployment Best Practices

Siva Dirisala
Nov 6 · 5 min read

Recently I worked on an app idea developed using Google App Engine technology. The app allows anyone to gather 360 degree feedback whether or not their work culture promotes such self-improvement processes. Essentially it promotes “You Own Your Own Career” #YOYOCareer.

This app is based on several microservices deployed on GCP and AWS and using Stripe Payments. AWS is exclusively used for sending emails and monitoring email reputation. The technologies used on GCP are Google Cloud Datastore, Google Cloud Tasks and Google Cloud Scheduler along with Google App Engine. The backend is done using Golang while the frontend is based on VueJS.

The App is divided into three separate App Engine services. The frontend (default service used for the end user UI), backend and admin (UI). The rest of the article is going to talk about the deployment pipeline I follow to ensure everything goes smoothly.

Local Environment

The app is developed and tested on a local environment thanks to GCP SDK support for Cloud Datastore emulator that can be run on local environment. I initially used to start the datastore along with the app engine using dev_appserver.py. While this is the easiest option, it takes more than 10 seconds everytime dev_appserver.py needs to start. There is no real reason to start a database along with the app. So, I separated these two by running the Cloud Datastore emulator as an independent service. With this change, the app server startup is instantanous. Time only goes in building the golang app.

With the above setup of a separate cloud datastore emulator and app server, I created three such instances. One is used for development, one for testing (manual and automated) and the third can be thought of as a local staging/pre-prod environment. During the initial stages, dev instance is most frequently used followed by testing and towards the end the staging environment.

Cloud Pre-Prod Environment

After ensuring everything is fine on the above mentioned local environments, every time a change needs to go to the production, it is first staged on to a pre-prod instance on GCP. GCP provides free daily quota for each project. Even though there are 3 GAE services, using the right settings for the GAE instances will ensure that the pre-prod is practically running for free. I used the pre-prod project extensively for a week just before the final launch. But these days it is hardly used except when new code needs to be pushed to production.

When deploying GAE app it is possible to specify a version. This is useful to rollback if needed. For the pre-prod, I always use a version called “testing”.

Cloud Prod Environment

After ensuring everything went smoothly on the pre-prod instance, the code is promoted to the production instance. When promoting to the production, I use the git commit short hash as the version.

git rev-parse --short HEAD

This gives a version string like 6e57ed97, making it hard to know which version is from when, there is no need to worry. First, the git commit hash gives a very precise state of the code that is deployed it also gives the timestamp. But this timestamp is that of the code commit, not deployment. But that’s also not a problem since on the GCP, each version has information of when it was deployed. So, using the git commit as version along with the GCP console, you get a lot of information of what’s running on your instance.

While gcloud command makes it very easy to deploy code, there are a couple of things to pay attention to in order to make sure there is no mistake. First, GAE supports ignoring files when deploying. This is important because you don’t want all kinds of files like node modules and other stuff get uploaded. During deployment, gcloud gives the count of files getting deployed. And this is incremental. That is, the first time it uploads all the files but subsequently it only uploads changed files. The feature I seem to miss with gcloud is to provide me with a list of files that will get uploaded without actually doing the deployment. I currently have my own script that gives me the entire set of files that will get uploaded. If you ever wondered what files actually got uploaded, you can get this info by going to a specific version on GCP and selecting the debug action. That will open a tab with all your code with the file structure on the side navigation.

Another checklist item for me is whether I have the UI built for development (npm run watch) or production (npm run build). So, I have a pre-deployment checklist item that checks this (by comparing the app js file size at the moment) and stop the deployment if it detects that the artifacts were meant for development.

I also take a snapshot of any deployment tracked by test and prod. While git provides all the history, there is a reason for doing the snapshot. Not all deployment artifacts are git controlled. This is because, what files are used to code vs their final deployable counter parts can be different. There is no point source controlling both. So before starting the deployment, I can do a diff between the prior snapshot and the current code that is about to get deployed to do a final sanity check. Think of this as a code review, but not against the git artifacts but against the deployment artifacts.

Lastly, the script also uses gcloud to get the currently running instances before and after the deployment to act as an extra checklist item.

One thing to note is that if you are using autoscaling for any of your GAE instances, then deploying a new version will continue to run the old version. However, once all the traffic is migrated, there will not be any idle instances running against the old version. Autoscaling doesn’t support stopping the instances. You would have to explicitly delete the version. What I do is to keep the current and prior version and delete anything older. This ensures that I will not accidentally have too many instances running for any reason.

So far everything seems to work fine. The gcloud option to stream the logs is also wonderful as it allows doing any additional checks before and after deployment all from the command line.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade