Under the Hood with GCP’s App Engine


Google’s App Engine service is a great way to get web applications up and running with minimal effort. In fact, I have an article on how you can spin up a Node.js application on this platform in about 10 minutes. This service is part of Google’s free tier and getting started with the App Engine is easy but one can struggle with understanding the different configuration options and the pricing structure. This article outlines in three sections what you need to consider when configuring and deploying your applications on the App Engine platform.

Hosting Options — Things to keep in mind when configuring and deploying your App Engine application.

Pricing —How App Engine charges are incurred.

Other Considerations — Some other considerations when deploying an App Engine application.

Let’s get started.

Hosting Options

When deploying an application you must provide instructions to the App Engine on what settings to use via a app.yaml config file. This section aims to help you understand the difference in deployment options and how they can be specified in this file.

Here is an example of a app.yaml file:

runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:    
    max_instances: 2    
    min_instances: 0    
    min_idle_instances: 0    
    max_idle_instances: 1

Runtime

When deploying an application the runtime language has to be specified. Documentation on support runtime environments can be found here and in the config file the runtime attribute is used — here is an example for a deployment using Node.js v14:

runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:    
    max_instances: 2    
    min_instances: 0    
    min_idle_instances: 0    
    max_idle_instances: 1

Environment

You may select from two different environment types — Standard and Flexible. This document outlines the detailed differences between the two options. In short, Flexible environments will cost you much more to run and are recommended only if you are using a language not supported by the Standard environment. Here is the list of supported languages:

  • Python 2.7, Python 3.7, Python 3.8, Python 3.9 (preview)
  • Java 8, Java 11
  • Node.js 8, Node.js 10, Node.js 12, and Node.js 14 (preview)
  • PHP 5.5, PHP 7.2, PHP 7.3, and PHP 7.4
  • Ruby 2.5, Ruby 2.6, and Ruby 2.7
  • Go 1.11, Go 1.12, Go 1.13, Go 1.14, Go 1.15 (preview)

There are other reasons to go Flexible but it should be an exception. You can find the full feature matrix here contrasting environment type capability. The environment type can be specified in the app.yaml file via the env attribute — the values are either flex or standard:

runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:    
    max_instances: 2    
    min_instances: 0    
    min_idle_instances: 0    
    max_idle_instances: 1

Instance Class

Like most other cloud services, when deploying an App Engine application you may select a class that will dictate allocated resources and functionality options.

Screen capture from GCP docs

It’s important to remember that Google’s free tier covers 28 hours of F1or 9 hours of B1 instance usage for free per day.

Screen capture from GCP docs

F instances are considered “Front End Instances” and B instances are considered “Back End Instances”. As you can see in the above table, the main difference is the scaling options available. The instance type can be specified in the app.yaml file via the instance_class attribute:

runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:    
    max_instances: 2    
    min_instances: 0    
    min_idle_instances: 0    
    max_idle_instances: 1

Service

The App Engine runs applications as services. Your first App Engine deployment is associated with the default service but anything you deploy afterward must be associated with a dedicated service name. If a specified service does not exist, a new one will be created, and if one exists the pushed application will take its place. Failing to specify a service in your app.yaml file will have your default service application overwritten. You can see the list of running services in your App Engine dashboard.

Screen capture from GCP docs

The environment type can be set in the app.yaml file via the service attribute :

runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:    
    max_instances: 2    
    min_instances: 0    
    min_idle_instances: 0    
    max_idle_instances: 1

Scaling Types

Instance scaling is a very important configuration to understand because it can significantly impact your costs and performance. As mentioned, F-type instances support automatic scaling and B-type instances can leverage either manual or basic scaling. You can find the matrix of the options here and the configuration flag details can be found here. Here is a summary.

Automatic Scaling — Instances are created and terminated based on requests and performance. Configuration can get a little complicated but I would recommend at the very least setting the min and max setting for total and idle instances using the max_instances, min_instances, min_idle_instances and max_idle_instances attributes. This should prevent incurring unexpected charges. There are other flags like target_cpu_utilization and max_pending_latency that the App Engine can use to optimize performance and trigger scaling changes. Here is an example running 0 to 2 instances and a restriction of at most 1 idle instance:

runtime: nodejs14
env: standard
instance_class: F1
service: my-node-app
automatic_scaling:    
    max_instances: 2    
    min_instances: 0    
    min_idle_instances: 0    
    max_idle_instances: 1

Basic Scaling —  Instances are spun up and down as the load on the application fluctuates. In the app.yaml file the maximum number of instances can be set using the max_instances attribute and the idle period using the idle_timeout attribute like so:

runtime: nodejs14
env: standard
instance_class: B1
service: my-node-app
basic_scaling:
  max_instances: 11
  idle_timeout: 10m

Manual Scaling — Spins up and maintains a set number of instances regardless of the load on the service. In the app.yaml file the number of instances can be set using the instances attribute like so:

runtime: nodejs14
env: standard
instance_class: B1
service: my-node-app
manual_scaling:
  instances: 5

Costs and Pricing

Google provides a set number of App Engine uptime hours in their free tier however, depending on your application is set up you may incur costs even if your application is up for a fraction of the allotted time. Understanding where these charges are coming from can sometimes be a challenge — the detailed documentation on costs can be found here but I will outline the key elements below.

Instance Uptime Charges

As of today, Google will charge you for instance uptime as follows:

You might end up getting charged and reading the below three caveats might save you countless hours of scratching your head, and aimlessly searching for answers online.

Photo by T.H. Chia on Unsplash

As the documentation outlines here, you will be billed for uptime plus an additional 15 minutes when an instance spins down.

If your instance receives four evenly spaced out requests (every 15 minutes) within an hour and only takes a second to process each before spinning down you will still be charged 60 minutes despite only using 4 seconds of uptime.

Your app might scale to multiple instances if usage spikes and scaling is enabled. In this scenario, you may see an hourly charge that is a multiple of the above cost table.

Application versions might also produce some unexpected charges. By default, the App Engine maintains all of your application’s version history and makes each version available mapped to a unique endpoint. If not used, these historic builds should only consume storage resources, but if requests are made against historic versions, they will spin up dedicated instances — this will of course come with additional utilization costs.

Quotas

The App Engine caps your application’s utilization of resources through quotas. There are three types of quotas; free, daily, and per-minute, if you are deploying hobby applications it is unlikely that you will come close to exceeding any of these quotas. If you do exceed a quota limit your application will be unavailable until the resources are reset at the end of the period, you can read more about this here.

Other Considerations

Google Cloud Storage

There are a few different ways for the App Engine to leverage GCS:

  1. The staging.<project-id>.appspot.com bucket is used to stage some objects as applications are deployed
  2. The us.artifacts.<project-id>.appspot.com bucket is used to store build artifacts
  3. Some applications may use buckets for runtime object storage
  4. Buckets can be used to store your source build files for App Engine deployments

GCS has a great free usage tier as outlined here.

Other Services

The App Engine might utilize a few other Google Cloud Platform services for general operation. The utilization of these services should be covered under the free tier but it’s important to understand what these services are in case you do start seeing charges. You can see the full list here.

Conclusion

Although the App Engine is a great way to get your application up and running on a highly scalable platform, understanding how to properly configure your deployments and costs can be a bit confusing. In this article, I shine some light on a few areas where beginners typically get bogged down. I hope my post was informative and saves you some headache and googling.

Good luck and happy coding!