Compare App Engine and Cloud Run

Region ID

The REGION_ID is an abbreviated code that Google assigns based on the region you select when you create your app. The code does not correspond to a country or province, even though some region IDs may appear similar to commonly used country and province codes. For apps created after February 2020, REGION_ID.r is included in App Engine URLs. For existing apps created before this date, the region ID is optional in the URL.

Learn more about region IDs.

This guide provides an introduction to Cloud Run for those who are familiar with App Engine. It covers the key similarities and differences between the Serverless platforms to help prepare for migration from either App Engine standard environment or App Engine flexible environment.

Overview

Cloud Run is the latest evolution of Google Cloud Serverless, building on the experience of running App Engine for more than a decade. Cloud Run runs on much of the same infrastructure as App Engine standard environment, so there are many similarities between these two platforms.

Cloud Run is designed to improve upon the App Engine experience, incorporating many of the best features of both App Engine standard environment and App Engine flexible environment. Cloud Run services can handle the same workloads as App Engine services, but Cloud Run offers customers much more flexibility in implementing these services. This flexibility, along with improved integrations with both Google Cloud and third-party services, also enables Cloud Run to handle workloads that cannot run on App Engine.

Comparison summary

While there are many similarities and differences between App Engine and Cloud Run, this overview focuses on the areas that are most relevant for App Engine customers getting started with Cloud Run.

App Engine standard environment App Engine flexible environment Cloud Run
Terminology Application N/A
Service Service
Version Revision

URL endpoints

App URL
(default service)
https://PROJECT_ID.REGION_ID.r.appspot.com N/A
Service URL https://SERVICE_ID-dot-PROJECT_ID.REGION_ID.r.appspot.com
  • https://SERVICE_NAME-PROJECT_NUMBER.REGION.run.app
  • https://SERVICE_IDENTIFIER.run.app
Version/Revision URL https://VERSION-dot-SERVICE-dot-PROJECT_ID.REGION_ID.r.appspot.com
  • https://TAG---SERVICE_NAME-PROJECT_NUMBER.REGION.run.app
  • https://TAG---SERVICE_IDENTIFIER.run.app

Scaling

Automatic scaling Yes Yes Yes
Manual scaling Yes Yes While there is no specific manual scaling setting, the same behavior can be replicated by configuring maximum instances equal to minimum instances
Scale-to-zero Yes No Yes
Warm-up requests Configurable No Automatic
Idle instance timeout (after finishing last request) Up to 15 minutes Depends on CPU allocation setting. Use CPU always allocated to emulate App Engine behavior
Request timeout
  • Automatic scaling: 10 minutes
  • Manual/Basic scaling: 24 hours
60 minutes Configurable up to 60 minutes (default: 5 minutes)

Deployment

From source Yes Yes
Container image No Yes (custom runtimes) Yes

Compute resources

vCPU
Instance class vCPU* Memory
F/B1 .25 384MB
F/B2 .5 768MB
F/B4 1 1.5GB
F/B4_1G 1 3GB
B8 2 3GB
* vCPU equivalents are approximate
Up to 80 vCPU Up to 8 vCPU
Memory Up to 6.5GB per vCPU Up to 32GB

Pricing model

Per-request fee No No, when CPU is always allocated.
Yes, when CPU is only allocated during request processing.
Idle minimum instances Same cost as active instances Lower cost for idle minimum instances (see Billable container instance time)
Committed use discounts (CUDs) No Yes

Security

Ingress settings Yes Yes Yes
Invoker role No Yes
IAP Yes Yes Configure using Cloud Load Balancing
Firewalls Yes Yes Configure using Google Cloud Armor

Connectivity

Custom domains Yes Yes Configure using Cloud Load Balancing
VPC connectivity (including Shared VPC) Yes N/A Yes
VPC egress settings Yes N/A Yes
Multi-region load-balancing No Yes

Accessing Google Cloud services

Cloud SQL Yes Yes Yes
Cloud Client Libraries If you are using Cloud Client Libraries in App Engine, you do not need to change anything when migrating to Cloud Run. These client libraries work everywhere, which means that your application is more portable.
App Engine legacy bundled services Yes (Java, Python, Go, PHP only) No No

Resource model

App Engine and Cloud Run resource model diagram

The Cloud Run resource model is very similar to App Engine, but there are some key differences:

  • Cloud Run does not have a top-level Application resource, or the corresponding default service.
  • Cloud Run services in the same project can be deployed to different regions. In App Engine, all services in the project are in the same region.
  • Cloud Run uses the term Revision, instead of Version, to align with the Knative resource model.
  • Cloud Run revision names use the format: SERVICE_NAME-REVISION_SUFFIX, where REVISION_SUFFIX is either auto-generated, or set using the --revision-suffix=REVISION_SUFFIX deployment flag.
  • Cloud Run revisions are immutable, meaning that you cannot reuse names like you can with App Engine versions (using the --version=VERSION_ID deployment flag).
  • Cloud Run service URLs are based on a Service Identifier that is automatically generated on the first deployment of the service. The Service Identifiers use the format: SERVICE_NAME-<auto-generated identifier>. The Service Identifier is unique, and does not change during the lifetime of the service.
  • In Cloud Run, only the service URLs (SERVICE_IDENTIFIER.run.app and https://SERVICE_NAME-PROJECT_NUMBER.REGION.run.app) are exposed by default. To address a specific revision, you must configure a traffic tag. In App Engine, both the service and version URLs are exposed automatically.

Deployment and configuration

In App Engine, most configuration is done in the app.yaml that is included in every deployment. This simplicity comes at a cost, in that, while a few settings can be updated using the Admin API, most changes require redeploying the service.

While Cloud Run has the service.yaml configuration file, it is not used in the same way as the app.yaml. The Cloud Run service.yaml cannot be used when deploying from source, as one of the required elements is the path to the final container image. Also, the service.yaml conforms to the Knative spec, and can be difficult to read for those not familiar with Kubernetes-style configuration files. For more information on using the service.yaml to manage configuration, see the Cloud Run documentation.

For App Engine customers getting started with Cloud Run, using the gcloud CLI deployment flags aligns much more closely with the App Engine at-deployment configuration management.

To set the configuration when deploying new code in Cloud Run, use gcloud run deploy flags:

gcloud run deploy SERVICE_NAME \
--cpu CPU \
--memory MEMORY \
--concurrency CONCURRENCY

While it is not necessary to use the configuration flags with every deployment (see Managing configurations), you can do so to help simplify configuration management.

In Cloud Run, you can also update the configuration without redeploying the source code using gcloud run services update:

gcloud run services update SERVICE_NAME \
--cpu CPU \
--memory MEMORY \
--concurrency CONCURRENCY

As Cloud Run revisions are immutable, this command will create a new revision with the updated configuration, but will use the same container image as the existing revision.

Managing configurations

For App Engine deployments, all settings must be provided for every deployment, and any settings not provided are assigned default values. For example, take App Engine service-a, with versions using the app.yaml files shown below:

App Engine service-a version1 App Engine service-a version2
app.yaml
runtime: python39
service: service-a
instance_class: F4
runtime: python39
service: service-a
Applied configuration
runtime: python39
service: service-a
instance_class: F4
default values:
..
..
runtime: python39
service: service-a
default values:
instance_class: F1
..
..

version1 is configured with instance_class: F4, while version2, which provided no value for instance_class, is configured with the default instance_class: F1.

For Cloud Run, any configuration settings provided are applied, but any that are not provided keep their existing values. You only need to provide values for settings that you want to change. For example:

Cloud Run service-a revision1 Cloud Run service-a revision2
Deployment command
gcloud run deploy service-a \
--cpu=4
gcloud run deploy service-a
Applied configuration
service: service-a
vCPUs: 4
default values:
..
..
service: service-a
vCPUs: 4
default values:
..
..

In App Engine, deploying with no configuration settings creates a version using all default settings. In Cloud Run, deploying with no configuration settings creates a revision using the same configuration settings as the previous revision. For the first revision of a Cloud Run service, deploying with no configuration settings creates a revision using all default settings.

Configuration defaults

Configuration setting App Engine standard environment App Engine flexible environment Cloud Run
Compute resources F1 1 vCPU, .6GB 1 vCPU, 512MB
Maximum concurrency (requests) 10 None 80
Request timeout
  • Automatic scaling: 10 minutes
  • Manual/Basic scaling: 24 hours
60 minutes 5 minutes
CPU utilization target 60% 50% 60%
Maximum instances None 20 100
Minimum instances 0 2 0

Entrypoint

When deploying from source, App Engine reads the entrypoint command from the entrypoint attribute in the app.yaml. If no entrypoint is provided, a runtime-specific default is used. Cloud Run uses Google Cloud's buildpacks when deploying from source, and some languages do not have a default entrypoint, meaning you must provide one or the build will fail. For example, Python buildpacks require either a Procfile, or specifying the GOOGLE_ENTRYPOINT build environment variable.

Please review the buildpacks documentation for any language-specific configuration requirements.

Scaling

While Cloud Run and App Engine standard environment share much of the same scaling infrastructure, Cloud Run has been streamlined to enable much faster scaling. As part of this streamlining, the configurable settings are limited to:

For Cloud Run instances, the target CPU utilization is not configurable, and fixed at 60%. See the Cloud Run documentation for more details about autoscaling.

App Engine flexible environment uses the Compute Engine Autoscaler, so has very different scaling characteristics than both App Engine standard environment and Cloud Run.

Idle instance timeout

In App Engine, idle instances remain alive for up to 15 minutes after the last request finished processing. Cloud Run allows you to configure this behavior using CPU allocation. To get the same behavior as App Engine, set the CPU allocation to CPU always allocated. Alternatively, use CPU only allocated during request processing to have idle instances shut down immediately (if there are no pending requests).

Warmup requests

Cloud Run automatically warms up instances using the container entrypoint command, so you do not need to manually enable warmup requests, or configure an /_ah/warmup handler. If you have code that you want to run at instance startup, before any requests are processed, you can either:

Static content

In App Engine standard environment, you can serve static content without using compute resources by serving from Cloud Storage, or by configuring handlers. Cloud Run does not have the handlers option for serving static content, so you can either serve the content from the Cloud Run service (same as dynamic content), or from Cloud Storage.

Cloud Run Invoker role

Cloud Run also offers the ability to control access to a service with Identity and Access Management (IAM). The IAM policy bindings for a service can be set using the gcloud CLI, Console, or Terraform.

To replicate App Engine behavior, you can make the service public by allowing unauthenticated requests. This can be set at deployment, or by updating the IAM policy bindings on an existing Service.

Deployment

Use the --allow-unauthenticated deployment flag:

gcloud run deploy SERVICE_NAME ... --allow-unauthenticated

Existing service

Use the gcloud run services add-iam-policy-binding command:

gcloud run services add-iam-policy-binding SERVICE_NAME \
--member="allUsers" \
--role="roles/run.invoker"

where SERVICE_NAME is the Cloud Run service name.

Alternatively, you can choose to control who has access to the service by granting the Cloud Run Invoker IAM role which is configurable per-service.

Deployment

gcloud run deploy SERVICE_NAME ... --no-allow-unauthenticated
gcloud run services add-iam-policy-binding SERVICE_NAME \
--member=MEMBER_TYPE \
--role="roles/run.invoker"

where SERVICE_NAME is the service name, and MEMBER_TYPE is the principal type. For example, user:email@domain.com.

For a list of acceptable values for MEMBER_TYPE, see the IAM concepts page.

Existing service

gcloud run services add-iam-policy-binding SERVICE_NAME \
--member=MEMBER_TYPE \
--role="roles/run.invoker"

where SERVICE_NAME is the service name, and MEMBER_TYPE is the principal type. For example, user:email@domain.com.

For a list of acceptable values for MEMBER_TYPE, see the IAM concepts page.

Environment variables and metadata

Both App Engine and Cloud Run have certain environment variables that are automatically set. The table below shows the App Engine environment variables, along with their Cloud Run equivalents. Cloud Run only implements a few environment variables, as compared to App Engine, but the data available from the metadata server is mostly equivalent.

Default environment variables

App Engine Name Cloud Run Name Description
GAE_SERVICE K_SERVICE The name of the current service. In App Engine, this is set to `default` if not specified.
GAE_VERSION K_REVISION The current version label of your service.
PORT PORT The port that receives HTTP requests.
N/A K_CONFIGURATION The name of the Cloud Run configuration that created the revision.
GOOGLE_CLOUD_PROJECT N/A The Cloud project ID associated with your application.
GAE_APPLICATION The ID of your App Engine application. This ID is prefixed with 'region code~' such as 'e~' for applications deployed in Europe.
GAE_DEPLOYMENT_ID The ID of the current deployment.
GAE_ENV The App Engine environment. Set to `standard` if in the standard environment.
GAE_INSTANCE The ID of the instance on which your service is currently running.
GAE_MEMORY_MB The amount of memory available to the application process, in MB.
NODE_ENV (Only available in the Node.js runtime) Set to production when your service is deployed.
GAE_RUNTIME The runtime specified in your app.yaml file.

Common metadata server paths

Path Description Example
/computeMetadata/v1/project/project-id Project ID of the project the service belongs to test_project
/computeMetadata/v1/project/numeric-project-id Project number of the project the service belongs to 12345678912
/computeMetadata/v1/instance/id Unique identifier of the container instance (also available in logs). 16a61494692b7432806a16
(string of alpha-numeric characters)
/computeMetadata/v1/instance/region
** Not available for App Engine flexible environment
Region of this service, returns projects/PROJECT_NUMBER/regions/REGION projects/12345678912/regions/us-central1
/computeMetadata/v1/instance/service-accounts/default/email Email for the runtime service account of this service. service_account@test_project.iam.gserviceaccount.com
/computeMetadata/v1/instance/service-accounts/default/token Generates an OAuth2 access token for the service account of this service. This endpoint will return a JSON response with an access_token attribute. {
"access_token":"<TOKEN>",
"expires_in":1799,
"token_type":"Bearer"
}

What's next